I’m in the middle of converting jslint4java to use maven as its build system (yes, really). Part of this is ensuring that the antunit tests I wrote continue to work. Maven has the antrun plugin, but it’s not 100% obvious how to use an antlib inside it.
Normally, to run an antlib extension as part of your build, you first dump the jar in ~/.ant/lib (or on the command line using a -lib flag) and then reference it in a namespace. e.g.
<project name="foo" xmlns:au="antlib:org.apache.ant.antunit"> … </project>
This relies on ant being able to pick out org/apache/ant/antunit/antlib.xml from the classpath.
When doing this in maven through the antrun plugin, you can’t just dump stuff into ~/.ant/lib however. You need to tell ant where everything is. Originally, I was following the example of the rat ant task. This attempts to invoke a second copy of ant with the correct -lib argument. It’s ugly though. Why should we fork a second copy of the JVM? And ant may not even be installed (in maven, it’s just jar files in the local repository).
Eventually, I looked closer at the antlib documentation and found Load antlib from inside of the buildfile. This shows how a typedef is the key: You can associate a given antlib URI with a particular classpath entry. Thankfully, maven-antrun-plugin provides ${maven.test.classpath} (amongst others) which contains every entry that we need. So the solution now looks something like this.
Firstly, pom.xml.
<project> <dependencies> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant-antunit</artifactId> <version>1.0</version> <scope>test</scope> </dependency> </dependencies> <build> <plugin> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <phase>test</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <ant antfile="${build.testOutputDirectory}/antunit/tests.xml" inheritAll="false" inheritRefs="false"> <property name="test.classpath" refid="maven.test.classpath" /> </ant> </tasks> </configuration> </execution> </executions> <dependencies> <!-- Force an upgrade to a newer ant version. Required by antunit. --> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> <version>1.7.0</version> </dependency> </dependencies> </plugin> </build> </project>
So, when we get to the test phase, we automatically run antunit/tests.xml, passing in the correct classpath. This is what the ant file looks like:
<project name="jslint-antunit" xmlns:au="antlib:org.apache.ant.antunit"> <taskdef uri="antlib:org.apache.ant.antunit" resource="org/apache/ant/antunit/antlib.xml" classpath="${test.classpath}" /> … </project>
This appears to work quite well, and runs my tests a sight quicker than before. If anybody from the apache rat project is listening, you might want to update your POMs.