Search code examples
javaaopaspectj

How do I import a project containing AspectJ aspects and annotation in another project


I'm having some difficulties importing a utility jar file containing some custom aspects into another project. It should be noted, that I'm not using Spring for this project, as my client is somewhat averse to Spring.

I have created a proof of concept (full code example below). When I run a test runner in the utility jar, any method annotated with my AspectJ annotation gets their aspects executed just fine. When I use the self-same jar in another project, the aspects are ignore.

When I run the main class in the utility I get:

$> java -cp aspectjrt-1.8.2.jar;aop-util-1.0-SNAPSHOT.jar TestOne
AspectOne's aroundAdvice's body is now executed Before aspectTestMethod is called. 
Executing TestOne.aspectTestMethod() 
AspectOne's aroundAdvice's body is now executed After aspectTestMethod is called.

If I run the main class of the consumer class, I get:

$>java -cp aspectjrt-1.8.2.jar;aop-util-1.0-SNAPSHOT.jar;aop-consumer-1.0-SNAPSHOT.jar Test
Test.testAspectOne
AspectTwo's aroundAdvice's body is now executed Before aspectTestMethod is called.
Test.testAspectTwo
AspectTwo's aroundAdvice's body is now executed After aspectTestMethod is called.

As I'm fairly new to aspect oriented programming, I'd really appreciate a pointer as to what I'm missing :)

utility jar

pom.xml

<?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>sandbox.aop</groupId>
        <artifactId>aop-util</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>

        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.8.2</version>
            </dependency>
        </dependencies>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>1.7</version>
                    <configuration>
                        <complianceLevel>1.8</complianceLevel>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

Annotation

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)
public @interface AnnotationOne { }

Aspect

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.JoinPoint;

@Aspect
public class AspectOne {

    @Pointcut("@annotation(AnnotationOne)")
    public void annotationPointCutDefinition(){
    }

    @Pointcut("execution(* *(..))")
    public void atExecution(){}

    @Around("@annotation(AnnotationOne) && execution(* *(..))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        Object returnObject = null;
        try {
            System.out.println("AspectOne's aroundAdvice's body is now executed Before aspectTestMethod is called.");
            returnObject = joinPoint.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        }
        finally {
            System.out.println("AspectOne's aroundAdvice's body is now executed After aspectTestMethod is called.");
        }
        return returnObject;
    }

    @After("annotationPointCutDefinition() && atExecution()")
    public void printNewLine(JoinPoint pointcut){
        System.out.print("\n\r");
    }
}

Main class

public class TestOne {

    public static void main(String[] args) {
        TestOne testOne = new TestOne();
        testOne.aspectTestMethod();
    }

    @AnnotationOne
    public void aspectTestMethod(){
        System.out.println("Executing TestOne.aspectTestMethod()");
    }
}

AOP consumer

pom.xml

<?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>sandbox.aop</groupId>
    <artifactId>aop-consumer</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>sandbox.aop</groupId>
            <artifactId>aop-util</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <complianceLevel>1.8</complianceLevel>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Annotation

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)
public @interface AnnotationTwo {}

Aspect

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AspectTwo {

    @Pointcut("@annotation(AnnotationTwo)")
    public void annotationPointCutDefinition(){
    }

    @Pointcut("execution(* *(..))")
    public void atExecution(){}

    @Around("@annotation(AnnotationTwo) && execution(* *(..))")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        Object returnObject = null;
        try {
            System.out.println("AspectTwo's aroundAdvice's body is now executed Before aspectTestMethod is called.");
            returnObject = joinPoint.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        }
        finally {
            System.out.println("AspectTwo's aroundAdvice's body is now executed After aspectTestMethod is called.");
        }
        return returnObject;
    }

    @After("annotationPointCutDefinition() && atExecution()")
    public void printNewLine(JoinPoint pointcut){
        System.out.print("\n\r");
    }
}

Main class

public class Test {

    public static void main(String[] args) {
        Test test = new Test();
        test.testAspectOne();
        test.testAspectTwo();
    }

    @AnnotationOne
    public void testAspectOne() {
        System.out.println(Test.class.getName() + ".testAspectOne");
    }

    @AnnotationTwo
    public void testAspectTwo() {
        System.out.println(Test.class.getName() + ".testAspectTwo");
    }
}

Solution

  • You need to tell the aspectj weaver to weave aspect defined in your library using aspectLibraries:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.7</version>
        <configuration>
            <complianceLevel>1.8</complianceLevel>
            <source>1.8</source>
            <target>1.8</target>
           <aspectLibraries>
                <aspectLibrary>
                    <groupId>sandbox.aop</groupId>
                    <artifactId>aop-util</artifactId>
                </aspectLibrary>
           </aspectLibraries>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>compile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>