6

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

Community
  • 1
  • 1
sat
  • 5,489
  • 10
  • 63
  • 81
  • Please do not ask the same question twice. I have answered [the other one](http://stackoverflow.com/a/25720857/1082681). – kriegaex Sep 08 '14 at 09:17
  • possible duplicate of [Spring Boot AOP load time weaving](http://stackoverflow.com/questions/25689814/spring-boot-aop-load-time-weaving) – kriegaex Sep 08 '14 at 09:18

2 Answers2

5

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
kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • @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. – sat Sep 08 '14 at 17:22
  • 1
    An easier solution is to dynamically load the agent without the need of jvm arguments: https://github.com/subes/invesdwin-instrument – subes Jan 16 '16 at 12:12
  • What I'm trying to understand is, why do I need to load both Java Agents? The documentation doesn't mention that – LppEdd Feb 18 '19 at 16:04
  • 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](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-aj-ltw) 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. – kriegaex Feb 19 '19 at 03:46
4

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
    }
}
Vikram Palakurthi
  • 2,406
  • 1
  • 27
  • 30