1

I have a spring book application, which works fine. I would like to send email notifications to me if there are exceptions thrown from my application. I think aspectj is a good fit.

First, I tried to use Spring AOP runtime weaving, which works OK for public methods. However, I would like to get notified on private methods as well, and I have scheduled tasks. According to Spring AOP doc, runtime weaving won't work for scheduled tasks and private methods. Thus I have decided to use aspectj compile time weaving in my boot application.

I found the official aspectj gradle plugin here:

https://plugins.gradle.org/plugin/at.jku.isse.gradient-gradle

My boot application has this dependency:

compile group: 'org.springframework.boot', name: 'spring-boot-configuration-processor', version:'1.5.14.RELEASE'

My project compiles fine if I use default compiler. But if I use AspectJ compiler, it always complains:

[ant:iajc] warning Field value processing of @ConfigurationProperty meta-data is not supported
[ant:iajc] warning Hibernate JPA 2 Static-Metamodel Generator 4.3.11.Final
[ant:iajc] error at (no source information available)
D:\work\proj\build\classes\java\main\com\abc\dao\entity\Channel_.java:0::0 Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/metadata/JsonMarshaller at org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:169)

If I remove that dependency, aspectj compiles ok, I get the jar file. But then when I run my code, I got this:

Caused by: org.springframework.aop.framework.AopConfigException: Advice must be declared inside an aspect type: Offending method 'public void com.proj.aop.AspectConfiguration.afterThrowing(org.aspectj.lang.JoinPoint,java.lang.Throwable)' in class [com.proj.aop.AspectConfiguration]

And this is my Advice class:

package com.proj.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class AspectConfiguration {
    @AfterThrowing (pointcut="execution(* org.hibernate..*.*(..)) || execution(* com.proj..*.*(..))", throwing="excep")
    public void afterThrowing(JoinPoint joinPoint, Throwable excep){
        System.out.println("inafterthrowing");
    }
}

and my appconfig has annotation @EnableAspectJAutoProxy added.

If I replace @Configuration with @Component in my Advice class, I can run my application but the afterthrowing method is not called. Same if I remove @Configuration.

So my questions are:

  1. Why I get the java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/metadata/JsonMarshaller if I have spring-boot-configuration-processor as dependency when compiled by AspectJ?
  2. What is the correct way to use AspectJ in spring boot application and build with gradle? (use @Configuration or @Component? and why my afterthrowing is not called if I use @Component or, why I get exception if I use @Configuration?)

Thanks

kriegaex
  • 63,017
  • 15
  • 111
  • 202
The MW
  • 401
  • 4
  • 15
  • Of course you can use CTW if you like. This is what I usually do, too. But OTOH I do not use Spring, but you do. The Spring manual describes how to use LTW with AspectJ, thus most Spring users go that way. May I ask why you don't? That way you could avoid compilation issues. – kriegaex Jul 14 '18 at 04:27
  • One more thing: AspectJ is completely independent from Spring even if you happen to use it from within Spring, so you neither need `@Configuration` (which is wrong anyway because an aspect is not a configuration) nor `@Component` (which is correct for Spring AOP only). – kriegaex Jul 14 '18 at 04:30
  • Thanks. The reason I am not able to use spring AOP is that 1: I want to have the advice working on private methods, 2, I have scheduled tasks, and it seems Spring AOP doesn't work with scheduled tasks. – The MW Jul 14 '18 at 11:15
  • I know what you were asking, I read your question carefully. But you did not read mine carefully. I was not asking about Spring AOP, I was asking about AspectJ with LTW (load-time weaving) instead of CTW (compile-time weaving). – kriegaex Jul 14 '18 at 11:50
  • Thanks, just checked this example: https://github.com/spring-by-example/spring-by-example/tree/master/core/aspectj-load-time-weaving is it still valid? it was created 4-5 years ago. Also any gradle example? And the AspectJ LTW works on private methods and scheduled tasks? (I assume so?) – The MW Jul 14 '18 at 14:38
  • The sample should still be valid. The Spring manual also describes how to use [AspectJ via LTW](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-using-aspectj). Yes, LTW vs CTW behave the same (both can intercept private methods) as both are real AspectJ, but for LTW you do not need to compile with the AspectJ compiler, Javac is enough. The aspects are still unfinished then, but the AJ load-time weaver can do the rest. Of course you can also compile with Ajc and then weave the finished aspects into your application code. There are several options. – kriegaex Jul 15 '18 at 01:16
  • But still I am curious about your CTW attempt: With my hints about unneeded `@Component` annotation, does the project compile and run? Of course your pointcut `execution(* org.hibernate..*.*(..))` would still not intercept Hibernate classes because probably you did not configure Gradle to weave into the Hibernate classes and produce new, woven ones, but with LTW it should be easier. There are so many things to say about your approach and possible problems, it would be overwhelming for you if you are an AspectJ beginner. Both CTW and LTW can work if done correctly. – kriegaex Jul 15 '18 at 01:30
  • Thanks, got the LTW working, but somehow the advice doesn't work in forked threads. I have a scheduled task, and within this task, it forks multiple threads to do the job. The afterthrowing is not called If an exception is thrown from the forked thread. any idears? – The MW Jul 16 '18 at 01:49
  • I might have ideas if you share an [MCVE](http://stackoverflow.com/help/mcve) reproducing the problem on GitHub, please also include a Maven build configuration and describe what to do to reproduce the problem. – kriegaex Jul 16 '18 at 03:14
  • Thanks, I will try to create sample projects for it. Our environment is kind of complicated, we have a base DAO project, all other projects depend on it. One of the 'other' projects has lots of scheduled tasks, and within these scheduled tasks, we fork multiple threads to do the work. We use Gradle, so main project and sub-projects. The gradle script is pretty much standard, still use javac (apply plugin java). Then I have ``@EnableLoadTimeWeaving`` added to my application, and have an aop.xml in META-INF folder. – The MW Jul 16 '18 at 10:39
  • My aspect is in package ``com.proj.aop``, the point cut is this: ``@Pointcut("execution(* com.proj..*.*(..)) && !within(com.proj.aop..*)")``, and my aop.xml has include of ````. The above configuration works in the scheduled task itself, but not in forked threads from the scheduled task. – The MW Jul 16 '18 at 10:42
  • So where is your sample project? I am still here to help you, but first I need your help to reproduce the problem. – kriegaex Jul 19 '18 at 03:03

0 Answers0