Tuesday, September 22, 2015

Creating jar files with external dependencies using maven-antrun plugin

In most projects, you would want to write your own logic for the build to happen. You might want to copy certain files to different locations, compile source files etc. One easy way to do this is using maven-antrun plugin. By defining this in your pom file, you can execute the target commands that you perform when  creating a build.xml file.  Let us take a look at an example. Here I need to perform two tasks on a given sample at runtime.

1. Compile the source (.java) files provided.  (javac)
2. Create a jar from compiled files.    (jar)


First you need to add the plugin [2] to your pom.xml like below.

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <version>1.7</version>
                <artifactId>maven-antrun-plugin</artifactId>

              <plugin>
           </plugins>
</build>


If you were to create a simple build.xml file [1] ,you would define different targets and perform operations under these targets. In the same way, you can define tasks under this plugin, and add any operation that you would add under task, instead of target. In below sample I'm adding my first task , that is to compile and create a jar.
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <version>1.7</version>
                <artifactId>maven-antrun-plugin</artifactId>
             <executions>
                    <execution>
                        <id>create-jar</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <tasks>
                             <dependencyfilesets prefix="jarDepends." />
                                <property name="build.compiler" value="extJavac" />
                                <property name="classdir" value="target/class" />
                                <property name="jardir" value="target/jar" />
                                <property name="project" value="BookOrder" />
                                <property name="main-class" value="newProject.BookOrder" />
                                <mkdir dir="${classdir}" />
                                <path id="build.classpath">
                                    <fileset refid="jarDepends.maven.project.dependencies" />
                                </path>

                                <javac srcdir="${basedir}" destdir="${classdir}" classpathref="build.classpath">
                                  </javac>
                                <mkdir dir="${jardir}" />
                                <jar destfile="${jardir}/${project}.jar" basedir="${classdir}">
                                    <manifest>
                                        <attribute name="Main-Class" value="${main-class}" />
                                    </manifest>
                                </jar>

                            </tasks>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

What you need to remember here is that, you are running the executions under this plugin, which is a separate space. So in above sample, I'm trying to compile a source file that has external dependencies. Though these dependencies are listed in the pom, you need to load them into this plugin for the compilation to succeed.

The easy way to do is by defining fileset ref id with 'maven.project.dependencies' [3] (a property available with antrun plugin) that would load all the dependencies from the pom to the plugin. You could also load individual dependencies like below.

<fileset refid="mydeps.junit:junit:jar"/>
fileset refid="mydeps.org.apache.ant:ant:jar"/>

 So once you have them loaded, you could create a build path, and refer the loaded dependencies to that. This is done by above lines marked in green. So then in your javac command, you can add the classpath, saying to retrieve these dependencies when compiling the given sources.

In the next command 'jar' we are creating the jar file from the .class file that was created from 'javac' command.

Sometimes when using javac command with maven plugin, it tends to give an error saying 'Maybe Jre is defined instead of JDK' and fail the process. This seems to be a known issue , and the fix is to add  below property.
<property name="build.compiler" value="extJavac" />

[1] https://java.net/projects/ant-simple-sample/sources/ant-super-simple-code/content/build.xml
[2] https://maven.apache.org/plugins/maven-antrun-plugin/
[3] https://maven.apache.org/plugins/maven-antrun-plugin/tasks/dependencyFilesets.html 
 

No comments:

Post a Comment