I’m try to implement a simple AspectJ annotation example from https://www.baeldung.com/aspectj. The difference is, that I want to use the annotation at a JUnit TestClass. I googled a while for the solution but don’t find the right hint.
Part of my pom.xml
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> </dependency> </dependencies> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <complianceLevel>1.8</complianceLevel> <!--<source>1.8</source> <target>1.8</target>--> <showWeaveInfo>true</showWeaveInfo> <verbose>true</verbose> <Xlint>ignore</Xlint> <!--<encoding>UTF-8 </encoding>--> </configuration> <executions> <execution> <phase>process-sources</phase> <goals> <!-- use this goal to weave all your main classes --> <goal>compile</goal> <!-- use this goal to weave all your test classes --> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> </plugins>
My Annotation:
package com.mb.mtpp.main.extension.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD}) public @interface Secured { public boolean isLocked() default false; }
My Aspect:
package com.mb.mtpp.main.extension.aspectj; import com.mb.mtpp.main.extension.annotations.Secured; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public final class SecuredMethodAspect { @Pointcut("@annotation(secured)") public void callAt(Secured secured) { } @Before("callAt(secured)") public void around(JoinPoint pjp, Secured secured) throws Throwable { System.out.println("++++++++test++++++++"); //return secured.isLocked() ? null : pjp.proceed(); } }
@Secured(isLocked = true) public class DummyClassTest { @Test @Secured(isLocked = true) public void dummyTest4(){ log.info("Test 4"); } }
The Advice is mentions to the class annotation, I see it in the logs:
CLASSPATH component C:Program FilesJetBrainsIntelliJ IDEA Community Edition 2021.3.2pluginsmavenlibmaven3bootplexus-classworlds.license: java.util.zip.ZipException: error in opening zip file [INFO] Join point 'staticinitialization(void com.mb.mtpp.main.dummy.DummyClassTest.<clinit>())' in Type 'com.mb.mtpp.main.dummy.DummyClassTest' (DummyClassTest.java:23) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62) [INFO] Join point 'method-execution(void com.mb.mtpp.main.dummy.DummyClassTest.dummyTest3())' in Type 'com.mb.mtpp.main.dummy.DummyClassTest' (DummyClassTest.java:64) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62) [INFO] Join point 'method-execution(void com.mb.mtpp.main.dummy.DummyClassTest.dummyTest4())' in Type 'com.mb.mtpp.main.dummy.DummyClassTest' (DummyClassTest.java:71) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62) [INFO] Join point 'method-call(void com.mb.mtpp.main.extension.DummyClass.function1())' in Type 'com.mb.mtpp.main.dummy.DummyClassTest' (DummyClassTest.java:79) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62) [INFO] Join point 'method-call(void com.mb.mtpp.main.extension.DummyClass.function2())' in Type 'com.mb.mtpp.main.dummy.DummyClassTest' (DummyClassTest.java:80) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62) [INFO] Join point 'method-execution(void com.mb.mtpp.main.extension.DummyClass.function1())' in Type 'com.mb.mtpp.main.extension.DummyClass' (DummyClass.java:8) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62) [INFO] Join point 'method-execution(void com.mb.mtpp.main.extension.DummyClass.function2())' in Type 'com.mb.mtpp.main.extension.DummyClass' (DummyClass.java:13) advised by before advice from 'com.mb.mtpp.main.extension.aspectj.SecuredMethodAspect' (SecuredMethodAspect.java:62)
But the log “++++++++test++++++++” is not shown in the console. It executes as the advice is not there. I annotated the class, the testcase and a method as in the example. I tried different settings for my Pointcut but the shown is the best. Then the class is also advised. I don’t know what’s wrong.
Advertisement
Answer
Sorry, I was busy. Assuming that your directory layout is like this:
Some sample classes might look like this:
package com.mb.mtpp.main.extension.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD }) public @interface Secured { boolean isLocked() default false; }
package com.mb.mtpp.main.extension; import com.mb.mtpp.main.extension.annotations.Secured; public class MyClass { @Secured public void doSomething() {} }
package com.mb.mtpp.main.extension.aspectj; import com.mb.mtpp.main.extension.annotations.Secured; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public final class SecuredMethodAspect { @Pointcut("@annotation(secured) && execution(* *(..))") public void securedMethods(Secured secured) {} @Before("securedMethods(secured)") public void interceptSecuredMethods(JoinPoint joinPoint, Secured secured) { System.out.println(joinPoint); } }
package com.mb.mtpp.main.extension; import com.mb.mtpp.main.extension.annotations.Secured; import org.junit.jupiter.api.Test; @Secured(isLocked = true) public class MyTest { @Test @Secured(isLocked = true) public void dummyTest4(){ System.out.println("Test 4"); } @Test @Secured(isLocked = true) public void dummyTest5(){ System.out.println("Test 5"); new MyClass().doSomething(); } }
Your POM would be:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>SO_AJ_AspectNotTriggered_72344739</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M6</version> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <complianceLevel>1.8</complianceLevel> <showWeaveInfo>true</showWeaveInfo> <verbose>true</verbose> <Xlint>ignore</Xlint> <encoding>UTF-8</encoding> </configuration> <executions> <execution> <goals> <!--<goal>compile</goal>--> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
Then if you either run mvn clean test
or simply import the project into IntelliJ IDEA, the log output will be:
execution(void com.mb.mtpp.main.extension.MyTest.dummyTest4()) Test 4 execution(void com.mb.mtpp.main.extension.MyTest.dummyTest5()) Test 5
Now if for whatever reason you also want to apply the aspect to the annotated application class, simply
- move the aspect from
src/test/java
tosrc/main/java
, - remove
<scope>test</scope>
fromaspectjrt
and - uncomment
<goal>compile</goal>
.
Then the console log would be:
execution(void com.mb.mtpp.main.extension.MyTest.dummyTest4()) Test 4 execution(void com.mb.mtpp.main.extension.MyTest.dummyTest5()) Test 5 execution(void com.mb.mtpp.main.extension.MyClass.doSomething())
See? Application class MyClass
also gets intercepted in this case.
Update: Concerning why it was not working in your own example, that was because your POM was configured in such a way that Maven Compiler Plugin recompiled your classes after the aspects had been woven my AspectJ Maven Plugin. The result was that the aspect information was lost due to overwritten class files.