Spring Cache With Couchbase Using LoadTimeWeaving - Strangely Not Working

573 views Asked by At

I'm adding Spring Cache on an existing spring project using annotations. I'm using Couchbase as cache provider. I want to use load time weaving using AspectJ to allow private method calls and case class method calls to be cached as well.

It's been three days I'm stuck over this problem and I've read dozens of articles, documentations and examples but this thing just doesn't work.

This is what I've done -

@Configuration
@EnableSpringConfigured
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
@EnableTransactionManagement
@EnableRetry
@PropertySource(
        value = {"classpath:application.properties", "classpath:${spring.profiles.active}.properties"},
        ignoreResourceNotFound = true)
public class BeanConfig implements LoadTimeWeavingConfigurer {

    ... various beans here ...

    @Override
    public LoadTimeWeaver getLoadTimeWeaver() {
        return new TomcatLoadTimeWeaver();// because I'm using Tomcat 7
    }

    @Bean
    public InstrumentationLoadTimeWeaver loadTimeWeaver()  throws Throwable {
        return new InstrumentationLoadTimeWeaver();
    }
}

@Configuration
@EnableSpringConfigured
@EnableCaching(mode = AdviceMode.ASPECTJ)
@ComponentScan(basePackages = "com.foo.bar.dao.cache.couchbase")
public class CacheConfigurer extends CachingConfigurerSupport {
    @Bean
    @Override
    public CacheManager cacheManager() {
        ... cachemanager configuration here ...
    }
}

Then I have @Chacheable on a DAO method on class, not on interface.

Finally, in my Tomcat 7's $CATALINA_HOME/conf/context.xml I have -

<Context>
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>    
</Context>

I have added following dependencies in pom.xml (its a maven project) -

  • couchbase-spring-cache
  • spring-aspects
  • aspectjweaver
  • aspectjrt
  • spring-instrument
  • spring-instrument-tomcat

If I do not use LTW caching works fine for methods calls arriving through interfaces (as it should). But after I enable LTW caching doesn't works at all - no caching for any method call, no errors either.

Has anyone tried using LTW for Spring cache with couchbase? What am I missing or doing wrong here?

I'm on Spring 4.3.5.Release.

Update -

Here is my bare-minimal code replicating the situation - https://github.com/harshilsharma63/spring-boilerplate-with-cache

1

There are 1 answers

4
Nándor Előd Fekete On BEST ANSWER

Forget classloader based load-time weaving, especially with Tomcat < 8.0. You'll have a lot of problems related to classloading order, with some classes being loaded before spring would install his weaving classloader, and you're gonna end-up with hard-to debug problems some of your classes not being weaved, etc. Instead, use a java agent.

Here's how to fix your config with Tomcat 7 by switching to java agent based weaving:

  1. Remove @EnableLoadTimeWeaving annotations.
  2. Remove <Loader loaderClass... from context.xml.
  3. Add -javaagent:/path/to/aspectjweaver.jar to your JVM startup arguments.

If you're willing to move to Tomcat 8, here are the steps needed:

  1. Move @EnableLoadTimeWeaving(aspectjWeaving=ENABLED) to a separate configuration class, let's name it WeavingConfig.
  2. Change your WebInitializer class so that for the getRootConfigClasses() you return only WeavingConfig.class.
  3. Move other required config classes to getServletConfigClasses().
  4. Remove unneded configurations like <Loader loaderClass... from context.xml, @EnableAspectJAutoProxy.
  5. Profit.

Of course, the best would still be to just use compile time weaving.