Executable jar file with dependent jars using Maven

Sometimes we have a simple project which is launched using main method. If we build a jar using maven plugin then dependencies are not shipped with the executable jar. One can jar all the dependent jars using maven assembly plugin with “jar-with-dependencies” descriptor.

Example :

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

Only issue with this approach is that it will expand all the dependent jars and include the class files and other dependent files as part of jar. It becomes difficult to identify your code with 3rd party class files. Sometimes few files will overshadow each other in case we have file with same name and path.

The ideal solution is to include the jars in a lib folder and the manifest.mf file of the main jar include all the jars in classpath.

This can be achieved by http://code.google.com/p/onejar-maven-plugin/. Issue with onejar plugin is that it will put its code in your project and its class will load your main class. Some sort of indirection with which we were not comfortable.

Finally we zeroed on “maven-assembly-plugin” which actually creates a zip file with similar structure as jar file. We had to just rename the zip file to jar file.

Here are the steps which we followed :

1. Add following 2 snippets to the pom.xml

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>myProj.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

—————————————————-

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>final-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/finalJar.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>

2. Add all the dependencies and jar name in pom.xml as we always do.

3. Create finalJar.xml to src/main/assembly folder of your project.

4. Append the following to finalJar.xml

<assembly xmlns=”http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0&#8243; >
<id>distribution</id>
<formats>
<format>zip</format>
</formats>
<!–to include the main jar in non transitive manner and without base directory and in expanded way –>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<useTransitiveDependencies>true</useTransitiveDependencies>
<unpack>true</unpack>
<scope>runtime</scope>
<fileMode>0755</fileMode>
<directoryMode>0755</directoryMode>
<includes>
<include>project_groupid:project_artifactid</include>
</includes>
</dependencySet>

<!–to include the dependent jars in transitive manner –>
<dependencySet>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveDependencies>true</useTransitiveDependencies>
<unpack>false</unpack>
<scope>runtime</scope>
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
<outputDirectory>lib</outputDirectory>

<includes></includes>
</dependencySet>
</dependencySets>
</assembly>

 

 
 

 

Advertisements