tanvi
tanvi

Reputation: 997

Using AspectJ annotations without Spring

I am fairly new to AOP. I am trying to create annotations in a maven project without Spring using AspectJ. However my the method I am trying to call using the @Aspect is not being called.

This is what my pom looks like :

<?xml version="1.0" encoding="UTF-8"?>

<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>test</groupId>
<artifactId>tanvi</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
    <!-- https://mvnrepository.com/artifact/aspectj/aspectjrt -->
    <dependency>
        <groupId>aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.5.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/aspectj/aspectjweaver -->
    <dependency>
        <groupId>aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.5.3</version>
    </dependency>
    <dependency>
        <groupId>aspectj</groupId>
        <artifactId>aspectjtools</artifactId>
        <version>1.5.3</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.8</version>
            <configuration>
                <complianceLevel>1.8</complianceLevel>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
            <executions>
                <execution>
                    <phase>process-sources</phase>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

The annotation looks like this :

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HasAccess {
    Access[] accesses();
    String message() default "You are not allowed to perform this operation";
}

I created an annotation processor for my annotation :

@Aspect
public class HasAccessAdvice {
    //    @Before("execution(* *.*(..)) && @annotation(testAnnotation) ")
    @Before("execution(* *.*(..)) && @annotation(hasAccess)")
    public void myBeforeLogger(JoinPoint joinPoint, HasAccess hasAccess) {

    System.out.println("Okay - we're in the before handler...");
    System.out.println("The test annotation value is: " + hasAccess.accesses().toString());

    Signature signature = joinPoint.getSignature();
    String methodName = signature.getName();
    String stuff = signature.toString();
    String arguments = Arrays.toString(joinPoint.getArgs());
    System.out.println("Write something in the log... We are just about to call method: "
                       + methodName + " with arguments " + arguments + "\nand the full toString: "
                       + stuff);

}

}

I am calling it in this call :

public class TestMe {

    @HasAccess(accesses = {Access.CREATE_PURCHASE})
    public void createPurchase(BigDecimal bigDecimal) {
        System.out.println("create Purchase called");
    }
}

I created an aop.xml file and placed it in the same folder as pom.xml.

<aspectj>
    <aspects>
        <aspect name="HasAccessAdvice"/>
    </aspects>
</aspectj>

When I call the method createPurchase, it runs without the @Before method being called first. Please help me with what I am missing. Most of the documentation/answers I found were Spring aligned. Any pointers to any tutorial or even another way of creating simple annotations without Spring would be greatly appreciated.

Upvotes: 0

Views: 4411

Answers (1)

Ben
Ben

Reputation: 160

First, since you are using aop.xml, I assume you want to do load time weaving. See Load Time Weaving docs and docs on different weaving types.

Second, in your aop.xml file, you define which <aspect> to use, but you also need to define which class files / packages you want to weave:

<aspectj>
    <aspects>
        <aspect name="HasAccessAdvice"/>
    </aspects>
    <weaver options="-verbose">
        <!-- weave anything -->
        <include within="*" />
        <!-- weave specific packages only -->
        <include within="my.package..*" />
    </weaver>    
</aspectj>

Either use "*" to run your aspect on any classes or replace my.package with the package of TestMe. Note that double-dot .. includes sub-packages too.
Also note that <aspect name="..."> asks for fully-qualified Aspect-name with package. Did you create HasAccessibleAdvice in default-package? Add your package otherwise.

Third, aop.xml must be readable in META-INF/aop.xml on your classpath.
If you are running your test via CLI (using java -javaagent...), check your classpath settings (-cp).
If you are writing JUnit tests, you can put META-INF/aop.xml in src/test/resources and adjust the <build><plugins>-section of your pom.xml to include the load time weaver like this:

<properties>
    <aspectj.version>1.8.9</aspectj.version>
</properties>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.9</version>
            <configuration>
                <argLine>
                    -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
                </argLine>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjweaver</artifactId>
                    <version>${aspectj.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

Upvotes: 3

Related Questions