I build small library (Java and Maven) – using AspectJ. Library must be independent. Library deliver Aspects and Annotations. Function of library is – “call advice when executed a method with specific annotation”. All is ok when I use everything in one module, but problem appers when i separate library and project with classes which advice must be applied. I create simple schema. Library B – my library (aspects and annotations) Project A – project with buisness methods which adivce must be applied Is any posibility to do this?
Advertisement
Answer
According to the AspectJ Maven documentation, chapter “using aspect libraries”, you need to
- add the aspect library as a regular
<dependency>
, - also add the same dependency (without
<version>
because it is already assigned in step 1) in the plugin<configuration><aspectLibraries>
section as an<aspectLibrary>
.
Here is a concrete example:
Aspect library POM, marker annotation and sample aspect:
<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>de.scrum-master.stackoverflow</groupId> <artifactId>aspectj-lib</artifactId> <version>0.0.1-SNAPSHOT</version> <name>AspectJ Library</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.source-target.version>1.8</java.source-target.version> <aspectj.version>1.8.7</aspectj.version> </properties> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>${java.source-target.version}</source> <target>${java.source-target.version}</target> <!-- IMPORTANT --> <useIncrementalCompilation>false</useIncrementalCompilation> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.7</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> --> <!--<warn>constructorName,packageDefaultMethod,deprecation,maskedCatchBlocks,unusedLocals,unusedArguments,unusedImport</warn> --> </configuration> <executions> <execution> <!-- IMPORTANT --> <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> </dependency> </dependencies> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> </plugin> <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> --> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> <scope>runtime</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </dependency> </dependencies> <organization> <name>Scrum-Master.de - Agile Project Management</name> <url>http://scrum-master.de</url> </organization> </project>
package de.scrum_master.aspect; 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 Marker {}
package de.scrum_master.aspect; public aspect MyAspect { before() : execution(* *(..)) && @annotation(Marker) { System.out.println(thisJoinPoint); } }
Now run mvn clean install
on the aspect library project so as to install the dependency into your local Maven repo.
Java application POM and sample application:
By the way, in the POM I have also added two optional plugins:
- One-JAR plugin packages your application with all dependencies (e.g. aspect library and AspectJ runtime) into one artifact, here
target/java-app-0.0.1-SNAPSHOT.one-jar.jar
. You can just run your application viajava -jar target/java-app-0.0.1-SNAPSHOT.one-jar.jar
. - Exec Maven plugin is useful if you easily want to test your application from the command line via
mvn clean install exec:java
.
These two are only for convenience, you do not need them if you dislike them.
<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>de.scrum-master.stackoverflow</groupId> <artifactId>java-app</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Java Application</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.source-target.version>1.8</java.source-target.version> <aspectj.version>1.8.7</aspectj.version> <main-class>de.scrum_master.app.Application</main-class> </properties> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>${java.source-target.version}</source> <target>${java.source-target.version}</target> <!-- IMPORTANT --> <useIncrementalCompilation>false</useIncrementalCompilation> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.7</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> --> <!--<warn>constructorName,packageDefaultMethod,deprecation,maskedCatchBlocks,unusedLocals,unusedArguments,unusedImport</warn> --> <aspectLibraries> <aspectLibrary> <groupId>de.scrum-master.stackoverflow</groupId> <artifactId>aspectj-lib</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <!-- IMPORTANT --> <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> </dependency> </dependencies> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.4.0</version> <configuration> <mainClass>${main-class}</mainClass> </configuration> </plugin> <plugin> <groupId>org.dstovall</groupId> <artifactId>onejar-maven-plugin</artifactId> <version>1.4.4</version> <executions> <execution> <goals> <goal>one-jar</goal> </goals> </execution> </executions> <configuration> <onejarVersion>0.96</onejarVersion> <mainClass>${main-class}</mainClass> <attachToBuild>true</attachToBuild> </configuration> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> </plugin> <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> </plugin> --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <configuration> <mainClass>${main-class}</mainClass> </configuration> </plugin> <plugin> <groupId>org.dstovall</groupId> <artifactId>onejar-maven-plugin</artifactId> <configuration> <mainClass>${main-class}</mainClass> </configuration> </plugin> </plugins> </build> <pluginRepositories> <pluginRepository> <id>OneJAR googlecode.com</id> <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url> </pluginRepository> </pluginRepositories> <dependencyManagement> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>de.scrum-master.stackoverflow</groupId> <artifactId>aspectj-lib</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </dependency> <dependency> <groupId>de.scrum-master.stackoverflow</groupId> <artifactId>aspectj-lib</artifactId> </dependency> </dependencies> <organization> <name>Scrum-Master.de - Agile Project Management</name> <url>http://scrum-master.de</url> </organization> </project>
This little driver application demonstrates that you can now annotate methods with @Marker
, in this case only foo
and zot
, but not bar
:
package de.scrum_master.app; import de.scrum_master.aspect.Marker; public class Application { @Marker public static void foo() {} public static void bar() {} @Marker public static void zot() {} public static void main(String[] args) { foo(); bar(); zot(); } }
Console log:
java -jar target/java-app-0.0.1-SNAPSHOT.one-jar.jar execution(void de.scrum_master.app.Application.foo()) execution(void de.scrum_master.app.Application.zot())