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:
- Why I get the
java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/metadata/JsonMarshaller
if I havespring-boot-configuration-processor
as dependency when compiled by AspectJ? - 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