Java – apt and AOP use Maven in the same project
I have to use annotation processing (APT) and AspectJ in the same Maven project
Both are suitable for me, but I need to create aspects based on the code created by apt So I need binary weaving (the original source file is extended by APT) How do I enable binary weaving in Maven projects?
I know that the only standard option is to provide dependencies using the weaveddependencies parameter, but this is terrible Is there any other way?
Well, I can use maven antrun plugin to embed AspectJ ant tasks, but I don't want to resort to it
Solution
I'm obviously the only one who can answer my own questions
I have used maven antrun plugin to compile AspectJ through ant This is my POM clip:
<plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.4</version> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> <executions> <execution> <id>ajc-compile</id> <phase>process-classes</phase> <configuration> <tasks> <property name="aspectj.sourcepath" value="${project.basedir}/src/main/aspect" /> <property name="aspectj.binarypath" value="${project.build.outputDirectory}" /> <property name="aspectj.targetpath" value="${project.build.directory}/aspectj-classes" /> <property name="scope_classpath" refid="maven.compile.classpath" /> <property name="plugin_classpath" refid="maven.plugin.classpath" /> <ant antfile="ajc-ant.xml" /> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> <execution> <id>ajc-test-compile</id> <phase>process-test-classes</phase> <configuration> <tasks unless="maven.test.skip"> <property name="aspectj.sourcepath" value="${project.basedir}/src/test/aspect;${project.basedir}/src/main/aspect" /> <property name="aspectj.binarypath" value="${project.build.testOutputDirectory}" /> <property name="aspectj.targetpath" value="${project.build.directory}/aspectj-test-classes" /> <property name="scope_classpath" refid="maven.test.classpath" /> <property name="plugin_classpath" refid="maven.plugin.classpath" /> <ant antfile="ajc-ant.xml" /> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin>
I first compile the Java class (let apt do it), use the compiled class as the binary input of AspectJ, compile AspectJ into a new folder, and move the generated woven class to the original compilation directory to overwrite the non AspectJ class This is my ant XML file (the good part is that I can use it for compilation and test compilation):
<project basedir="." default="ajc"> <path id="classpath"> <pathelement path="${scope_classpath}" /> <pathelement path="${plugin_classpath}" /> </path> <taskdef classname="org.aspectj.tools.ant.taskdefs.AjcTask" name="iajc" classpathref="classpath" /> <target name="ajc"> <iajc sourceroots="${aspectj.sourcepath}" inpath="${aspectj.binarypath}" destdir="${aspectj.targetpath}" classpathref="classpath" source="1.6" target="1.6" /> <move todir="${aspectj.binarypath}"> <fileset dir="${aspectj.targetpath}"> <include name="**/*.class" /> </fileset> </move> </target> </project>
In the next step, I have now created a maven plug-in, which can complete all these ant calls internally Although I can't share the code here, I'll show how it simplifies POM configuration:
<plugin> <groupId>com.myclient.maven.plugins</groupId> <artifactId>maven-ajc-plugin</artifactId> <version>1.0-SNAPSHOT</version> <executions> <execution> <id>compile-ajc</id> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>testcompile-ajc</id> <goals> <goal>test-compile</goal> </goals> <configuration> <aspectSourcePath>${project.basedir}/src/main/aspect</aspectSourcePath> </configuration> </execution> </executions> <configuration> </configuration> </plugin>
With Ant / gmaven integration, the functions of maven, groovy and ant can be easily combined