2

I'm facing a problem on a large scale application using SpringBoot and AspectJ for logging purposes. The logging works fine for Spring Beans, but does not work for unmanaged classes (the ones I instantiate with 'new').

I've created a sample app where you can see the problem happening, you can access it here:

https://bitbucket.org/tomkro/stack_question

The application is pretty simple, the Gradle file is a common with the standard Spring Boot starters.

There are 5 relevant classes here.

Application.java, which is the main class:

@EnableAspectJAutoProxy
@EnableLoadTimeWeaving(aspectjWeaving= EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
@SpringBootApplication(scanBasePackages = "com.test.*")
public class Application {

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

The AspectConfig file (which for the sake of simplicity also defines the RestController, could be easily separated files)

@RestController
@Configuration
@ComponentScan(basePackages = {"com.test"})
public class AspectConfig {

    @Bean
    public TestLogger testLogger(){
        return new TestLogger();
    }

    @Autowired
    TestClass testClass;

    @RequestMapping("/")
    public int get() {
        return testClass.methodFromClass1();
    }

}

The TestLogger, which defines the aspect for this app:

@Aspect
public class TestLogger {

    public TestLogger() {
    }

    @Around("execution( * com.test.classes..*.*(..))")
    public Object aroundExecution(ProceedingJoinPoint pjp) throws Throwable {
        String packageName = pjp.getSignature().getDeclaringTypeName();
        String methodName = pjp.getSignature().getName();
        long start = System.currentTimeMillis();

        System.out.println(packageName + "." + methodName + " - Starting execution ");

        Object output = pjp.proceed();
        Long elapsedTime = System.currentTimeMillis() - start;

        System.out.println(packageName + "." + methodName + " - Ending execution ["+elapsedTime+" ms]");
        return output;
    }

}

And then there's two files, one managed by Spring, the other not:

TestClass1:

@Component
public class TestClass {

    public int methodFromClass1() {
        TestClass2 test = new TestClass2();
        return test.methodFromClass2();
    }

}

TestClass2

public class TestClass2 {
    public int methodFromClass2() {
        int a = 10;
        int b = 5;

        return b + a;
    }
}

Also there's the aop.xml file in META-INF which specifies the Aspect

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver option="-debug">
        <!-- only weave classes in our application-specific packages -->
        <include within="com.test.*"/>
    </weaver>

    <aspects>
        <!-- weave in just this aspect -->
        <aspect name="com.test.utilities.TestLogger"/>
    </aspects>

</aspectj>

I followed most of this build using the tutorial on the Spring documentation here , and I've been scratching my head for two days now and I can't figure out what's happening. The managed Bean logs fine, but the unmanaged one is not being logged.

I'm using the run.bat included in the project for starting, basically it does this:

call gradle build
java -javaagent:.\src\main\resources\aspectjweaver.jar -javaagent:.\src\main\resources\spring-instrument.jar -jar build\libs\Test-0.0.1-SNAPSHOT.jar

Both jars are the latest. Usually you only would need of the JAR's, but I saw someone using both and gave it a shot. This is the output after startup and execution of a call to "localhost:8080"

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

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

2016-04-08 15:21:44.116  INFO 20400 --- [           main] com.test.Application                     : Starting Application on PC000BR23205 with PID 20400 (C:\git\Test\build\libs\Test-0.0.1-SNAPSHOT.jar started by tkroth in C:\git\T
est)
2016-04-08 15:21:44.120  INFO 20400 --- [           main] com.test.Application                     : No profiles are active
2016-04-08 15:21:44.294  INFO 20400 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2cd72cea: startup date [Fri Ap
r 08 15:21:44 BRT 2016]; root of context hierarchy
2016-04-08 15:21:44.950  INFO 20400 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope
=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; fa
ctoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]]
 with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$W
ebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAut
oConfigurationAdapter.class]]
2016-04-08 15:21:45.872  INFO 20400 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-04-08 15:21:45.888  INFO 20400 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-04-08 15:21:45.891  INFO 20400 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.28
2016-04-08 15:21:45.987  INFO 20400 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-04-08 15:21:45.987  INFO 20400 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1695 ms
2016-04-08 15:21:46.342  INFO 20400 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2016-04-08 15:21:46.347  INFO 20400 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-04-08 15:21:46.348  INFO 20400 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-04-08 15:21:46.349  INFO 20400 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-04-08 15:21:46.349  INFO 20400 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2016-04-08 15:21:46.439  INFO 20400 --- [           main] o.s.c.w.DefaultContextLoadTimeWeaver     : Found Spring's JVM agent for instrumentation
2016-04-08 15:21:46.455  INFO 20400 --- [           main] o.s.c.w.DefaultContextLoadTimeWeaver     : Found Spring's JVM agent for instrumentation
[LaunchedURLClassLoader@6d8a00e3] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
2016-04-08 15:21:46.781  INFO 20400 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2cd72cea:
startup date [Fri Apr 08 15:21:44 BRT 2016]; root of context hierarchy
2016-04-08 15:21:46.874  INFO 20400 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public int com.test.configuration.AspectConfig.get()
2016-04-08 15:21:46.877  INFO 20400 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.sp
ringframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-04-08 15:21:46.878  INFO 20400 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoco
nfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2016-04-08 15:21:46.912  INFO 20400 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-04-08 15:21:46.912  INFO 20400 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-04-08 15:21:47.030  INFO 20400 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler
]
2016-04-08 15:21:47.133  INFO 20400 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-04-08 15:21:47.204  INFO 20400 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-04-08 15:21:47.210  INFO 20400 --- [           main] com.test.Application                     : Started Application in 3.481 seconds (JVM running for 4.306)
2016-04-08 15:21:51.680  INFO 20400 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2016-04-08 15:21:51.680  INFO 20400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-04-08 15:21:51.704  INFO 20400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 23 ms
com.test.classes.TestClass.methodFromClass1 - Starting execution
com.test.classes.TestClass.methodFromClass1 - Ending execution [15 ms]

As you can see, TestClass2 is never logged, although it's called. What am I missing here?

The real question is, how can I make non-beans to be handled by LTW in a SpringBoot environment? Feel free to commit changes on the repository I provided above.

  • Add `-showWeaveInfo` and `-verbose` to your `aspect.xml` as in this answer [http://stackoverflow.com/a/34427785/2699901] to have more details about the weaving process. – Nándor Előd Fekete Apr 09 '16 at 01:04
  • That did not yield any useful information about the problem. Only some star information about the ClassLoader being loaded, but that's not readable (Only a toString on a Class reference) – Tomás Kroth Apr 11 '16 at 19:36
  • You should have similar log entries on standard output about weaved join points like in the referenced answer. If you miss those log entries, either your pointcuts are not matching your code or load-time-weaving is not working properly. – Nándor Előd Fekete Apr 11 '16 at 19:40

0 Answers0