Spring Boot - Can't get load time weaving with aspectj to work

10,622

Solution 1

Okay, I took a quick look at your GitHub project. The POM is pretty weird, e.g. it does not contain any dependency on spring-instrument. Furthermore, you depend on aspectjweaver 1.8.2, but on aspectjrt 1.5.4. You should really use the same version for both.

Anyway, I experimented with different Java agents on the command line, and it seems that it is not enough to just use AspectJ weaver (result: exception) or just Spring Instrument (result: aspects do not work, just as you described). You need to use both:

java -javaagent:path/to/aspectjweaver-1.8.2.jar -javaagent:path/to/spring-instrument-4.1.0.RELEASE.jar ...

This works for me with your code and yields the following on the console when using Curl according to your description:

[AppClassLoader@58644d46] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.6.RELEASE)

2014-09-08 13:09:54.489  INFO 1464 --- [           main] App                                      : Starting App on Xander-PC with PID 1464 (C:\Users\Alexander\Documents\java-src\SO_AJ_SpringBootPrivilegedAspect\target\classes started by Alexander in C:\Users\Alexander\Documents\java-src\SO_AJ_SpringBootPrivilegedAspect)
2014-09-08 13:09:54.513  INFO 1464 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6771beb3: startup date [Mon Sep 08 13:09:54 CEST 2014]; root of context hierarchy
(...)
2014-09-08 13:09:56.257  INFO 1464 --- [           main] o.s.c.w.DefaultContextLoadTimeWeaver     : Found Spring's JVM agent for instrumentation
2014-09-08 13:09:56.259  INFO 1464 --- [           main] o.s.c.w.DefaultContextLoadTimeWeaver     : Found Spring's JVM agent for instrumentation
Aspect of called
(...)
2014-09-08 13:09:56.779  INFO 1464 --- [           main] App                                      : Started App in 2.531 seconds (JVM running for 3.067)
2014-09-08 13:09:59.115  INFO 1464 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2014-09-08 13:09:59.115  INFO 1464 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2014-09-08 13:09:59.122  INFO 1464 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 7 ms
Aspect of called
Advising getter

Solution 2

Try declaring an InstrumentationLoadTimeWeaver bean instead of explicitly using -javaagent:/path/to/org.springframework.instrument-{version}.jar. As per the documentation

To use it, you must start the virtual machine with the Spring agent, by supplying the following JVM options:

-javaagent:/path/to/org.springframework.instrument-{version}.jar

Note that this requires modification of the VM launch script which may prevent you from using this in application server environments (depending on your operation policies). Additionally, the JDK agent will instrument the entire VM which can prove expensive.

I am hoping doing the way below would be better I guess.

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

The same can be done in xml configuration.

Found a new library that just solves to dynamically setup spring InstrumentationLoadTimeWeaver to enable support for aspects without having to start the JVM with an explicit java agent

<dependency>
    <groupId>de.invesdwin</groupId>
    <artifactId>invesdwin-instrument</artifactId>
    <version>1.0.2</version>
</dependency>

Spring boot config

@SpringBootApplication
/** 
 * Make @Configurable work via @EnableLoadTimeWeaving.
 * If it does not work, alternatively you can try: 
 * @ImportResource(locations = "classpath:/META-INF/ctx.spring.weaving.xml") 
 */
@EnableLoadTimeWeaving
public class MySpringBootApplication {
    public static void main(final String[] args) {
        DynamicInstrumentationLoader.waitForInitialized(); //dynamically attach java agent to jvm if not already present
        DynamicInstrumentationLoader.initLoadTimeWeavingContext(); //weave all classes before they are loaded as beans
        SpringApplication.run(MySpringBootApplication.class, args); //start application, load some classes
    }
}
Share:
10,622
sat
Author by

sat

Updated on June 05, 2022

Comments

  • sat
    sat almost 2 years

    Could anyone please tell me why the aspect won't fire when using spring boot? I am trying to setup load time weaving with aspectj so that I can have private methods advised.

    Here is the link to the barebones project - https://github.com/satb/spring_aop_test_project.git

    Run the "App" class with "-javaagent:path/to/spring-instrument-4.1.0.RELEASE.jar" (or some other version of the lib on your computer) and run the curl command

    curl -i http://localhost:8080/test-app/motd
    

    The MyAspect class has an advice that should execute when the private method of MyService is called. But in this case, nothing happens.

    When the application starts though, I see a message like this:

    [AppClassLoader@58644d46] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified.
    

    I tried following the suggestion from here to get it to work but that didn't help - Using @Autowired with AspectJ and Springboot

  • sat
    sat over 9 years
    @kregaex - Thanks. Looks like I missed adding aspectjweaver as a javaagent. Didn't realize it was needed. Although I read about it on SO when someone else had the same problem, it didn't work for me when I added it on my earlier test. Therefore, I removed it thinking that wasn't the problem. But maybe the problem then was something else. And sorry for the same question another time. I should have added this barebones project link to the other question itself.
  • subes
    subes over 8 years
    An easier solution is to dynamically load the agent without the need of jvm arguments: github.com/subes/invesdwin-instrument
  • Juzer Ali
    Juzer Ali about 8 years
    This does not work with spring boot jar github.com/spring-projects/spring-boot/issues/739
  • Vikram Palakurthi
    Vikram Palakurthi about 8 years
    I implemented it using spring boot jar and have it working in production application, the implementation shouldn't really make any different with spring boot or normal spring implementation.
  • Juzer Ali
    Juzer Ali about 8 years
    did you deploy your spring boot application using embedded tomcat server?
  • Vikram Palakurthi
    Vikram Palakurthi about 8 years
    Yup the application runs in embedded tomcat server.
  • Juzer Ali
    Juzer Ali about 8 years
    Then I wonder what this bug is all about?
  • codeomnitrix
    codeomnitrix almost 6 years
    @VikramPalakurthi how can you achieve the Custom LoadTimeweaver with xml?
  • LppEdd
    LppEdd about 5 years
    What I'm trying to understand is, why do I need to load both Java Agents? The documentation doesn't mention that
  • kriegaex
    kriegaex about 5 years
    I am not a Spring user, I just wanted to help. I am an AspectJ expert, so I can also help a bit with Spring AOP or AspectJ via LTW within Spring. The documentation actually says that either one agent should suffice. Maybe there is a way to just use spring-instrument and make it load the AspectJ weaver automatically if done right. But what "done right" exactly means, I have no idea. There are others more qualified than I to answer that. But it does work with both agents on the command line.