Before marking this question as a duplicate, please read through, as I've gone through a number of posts on SO and other places but have still failed to find a solution to my problem.
I'm trying to implement a project in Spring + AspectJ and as the title says, I can see the aspectj maven plugin applying the advice but it isn't actually called.
I'm trying to apply an advice based on an annotation. Following is the annotation class:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface LogThis {
String name();
int id();
int eventID();
}
This annotation has been applied to a method which is being called from a js script on the front end through an ajax call. The method being called is as follows:
@RequestMapping(value = "/handle", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.NO_CONTENT)
@LogThis(name = "name", ID = 12345, eventID = 12345)
public void create(@RequestBody TodoDTO todo, HttpServletRequest req) {
//perform some action
}
The advice is being applied to the LogThis
annotation and the advice is as follows:
@Pointcut("@annotation(LogThis)")
public void genericPointcut() {
}
@Pointcut("execution(* *(..))")
public void atExecution() {
}
@Async
@Before("genericPointcut() && atExecution()")
public void logBefore(JoinPoint joinPoint) throws NoSuchMethodException, SecurityException {
// Perform logging
}
The annotation class and the aspect are in the same package while the class which is being advised is in a different package but everything is in the same project.
I've configured my maven pom.xml file as follows (only relevant portions shown):
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<Xlint>ignore</Xlint>
<complianceLevel>${java.source-target.version}</complianceLevel>
<encoding>${project.build.sourceEncoding}</encoding>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
The properties are:
<properties>
<sonar.language>java</sonar.language>
<java.source-target.version>1.7</java.source-target.version>
<aspectj.version>1.8.7</aspectj.version>
</properties>
The aspectj dependencies are:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
Spring version being used is 4.1.3.RELEASE
.
The spring config entry for my aspect is as follows:
<aop:aspectj-autoproxy />
<bean id="logAspect" class="somep2.LoggingAspect" />
On running mvn clean install
the build succeeds and the following log entry is present w.r.t aspectj:
[INFO] --- aspectj-maven-plugin:1.8:compile (default) @ myproj ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'method-execution(void somep.SomeC.create(param1, param2))' in Type 'somep.SomeC' (SomeC.java:63) advised by before advice from 'somep2.LoggingAspect' (LoggingAspect.java:36)
[INFO]
[INFO] --- aspectj-maven-plugin:1.8:test-compile (default) @ myproj ---
[WARNING] No sources found skipping aspectJ compile
According to the logs, the join point was found and advised but the logBefore()
method is never called when the create()
method is called. I am certain of this because I'm writing to a file using a FileWriter
but nothing is being written.
Deployment details: This project is built as part of another project which creates an ear file which is then deployed on JBoss 6.3
I've tried numerous approaches but nothing has worked. Please let me know what I'm missing.
Any help is appreciated.
I finally got it to work. Turns out I was complicating things too much. There was no need for the aspectj compiler. All that I had to do was tell spring that my aspect was a component as well so that it could inject my advice.
So here's the complete list of changes:
@Component
and made sure that it was being scanned as part of the Spring component scan.Hope this helps someone else as well.
PS. I still do not completely understand why this worked so if someone has an explanation, please comment.