0

Caching Aspects are not having any effects at runtime with Spring Boot and Embedded tomcat with LoadTimeWeaving enabled,but we are seeing the weaving is happening fine in the logs.

Below is the configuration, the LoadTimeWeaving is enabled along with the mode as AspectJ for Caching

    @Configuration
    @EnableConfigurationProperties
    @EnableSpringConfigured
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @EnableLoadTimeWeaving
    @EnableTransactionManagement
    @EnableAsync
    @EnableCaching(mode = AdviceMode.ASPECTJ)
    public class AppConfig {
    }

Spring Agent -javaagent:../../../spring-instrument-4.3.3.RELEASE.jar

Logs

[RestartClassLoader@2aaae670] debug weaving 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway'
[RestartClassLoader@2aaae670] weaveinfo Join point 'method-execution(java.util.List uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway.getHierarchyLevelDefns())' in Type 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway' (RestReferenceDataGateway.java:118) advised by around advice from 'org.springframework.cache.aspectj.AnnotationCacheAspect' (AbstractCacheAspect.aj:64)
[RestartClassLoader@2aaae670] weaveinfo Join point 'method-execution(java.util.Map uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway.getHierarchyLevelDefinitionMap())' in Type 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway' (RestReferenceDataGateway.java:129) advised by around advice from '**org.springframework.cache.aspectj.AnnotationCacheAspect**' (AbstractCacheAspect.aj:64)
[RestartClassLoader@2aaae670] **debug generating class** 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway$AjcClosure1'
[RestartClassLoader@2aaae670] debug generating class 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway$AjcClosure3'

there are whole bunch of discussions around this. The weaving is happening on the RestartClassLoader, not sure is it something to do with the class loader. Have also tried adding the below,

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

Please provide your suggestions.

Edit We need Aspectj mode as we are using caching on private methods. I removed the EnableAspectJAutoProxy but still that does not help.

On further analysis on the load time weaving, I noticed the below behaviour. I profile the application and investigated on the class loaders to see the weaving is done correct for the caching annotation to work(classes are trasformed). I noticed for some classes in the classloader ,we have a class with suffix($AjcClosure and those are transformed classes after weaving is done). So, if cachinng annotations is part of those weaved classes, then it works fine. Then I closely looked in to the classes why some classes are weaved correctly and some are not. Then I noticed that if classes are loaded already to the class-loader before weaving happens, then that is where the weaving is not happening.

   @Bean
    public IAService aService(){
       return new AServiceImpl();
    }

In the above case, the class is AServiceImpl is loaded to the class loader only when this instance is needed (after load time weaving and caching works perfectly). But if the same class is being initialised using @Component then it is not getting weaved.

@Service
public class AServiceImpl{
}

I think, in the above case, the class AServiceImpl is loaded to the class loader while the spring container initialises and load time weaving is trying to weave after that).

I verified this behavior again in class loader as well. So, is it an issue if aspectj tries to weave a class that was already loaded. the same problem was raised in the Spring Jira as well in the below link.

https://jira.spring.io/browse/SPR-13786

As mentioned in the above link, if I pass the aspectj weaver as java agent like the below, then all the classes are being weaved correctly. So, is it required to have two agents or do we have any other option for this.

-javaagent:../../../aspectjweaver-1.6.1.jar 
-javaagent:../../../spring-instrument-4.3.3.RELEASE.jar 
Raju
  • 9
  • 1
  • 5
  • 1
    Your question puzzles me. Is it really about AspectJ or about proxy-based Spring AOP? Because you configure both `@EnableAspectJAutoProxy` (Spring AOP) and `@EnableLoadTimeWeaving` (AspectJ). You should only use one of them. Why do you think you need full AspectJ anyway? Are you using features not present in Spring AOP, such as private method interception, pointcut types not supported in Spring AOP or similar? Or maybe you want to trace internal calls made by your target classes, such as `this.myMethod()`? The latter is what your annotation `@EnableCaching(mode = AdviceMode.ASPECTJ)` suggests. – kriegaex Dec 27 '17 at 04:29
  • thanks @kriegaex. I have investigated further along the lines with class loaders add details in my question. please suggest – Raju Jan 03 '18 at 23:30

1 Answers1

0

Yes, the weaver needs to be active before the weaving targets are loaded by the classloader.

Now, I am an AspectJ geek but not a container geek, I mainly work with Java SE and no containers. Please try to also add

-javaagent:path/to/aspectjweaver.jar

to your command line and see if it helps.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • Thanks @kriegaex. As I mentioned adding the aspectjweaver-1.6.1.jar as a java agent resolved the issue. I think this is the only option in Spring Boot as i dont faced this issue when we have configurations in xml. Thanks again – Raju Jan 05 '18 at 16:57
  • If you want to investigate this issue a little further, I [found something](https://stackoverflow.com/questions/35993888) for you, maybe it helps. :-) – kriegaex Jan 06 '18 at 04:34