Creating executable jars with Maven
After wrestling with Maven assemblies for while I finally figured out how to build executable jars. The Maven assembly plugin allows you to define ways to package up your project for distribution by creating various assembly descriptor files. Here’s a quick example of a Maven assembly for building an executable jar (uberjar). For this example we’ll create a brand new project from scratch but it should be easy to see how to integrate into an existing project.
First step lets create a test project:
$ mvn archetype:create -DgroupId=org.qnot.example -DartifactId=hello-world $ cd hello-world
Next add a few dependencies to the project. In this example we’ll add a few libraries from jakarta commons. The <dependencies/> section in the pom.xml should now look like this:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
Create a META-INF/ directory to store the MANIFEST.MF file which defines the main class in the executable jar.
$ mkdir -p src/main/resources/META-INF/ $ echo 'Main-Class: org.qnot.example.App' > MANIFEST.MF
Create a src/assemble directory to store the assembly descriptor files
$ mkdir src/assemble
Next we’ll create the actual assembly descriptor file which defines how to package up the jar. Create the file src/assemble/exe.xml with the following xml:
<assembly>
<id>exe</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory></outputDirectory>
<outputFileNameMapping></outputFileNameMapping>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>commons-lang:commons-lang</include>
<include>commons-cli:commons-cli</include>
</includes>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>target/classes</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
Inside the <dependecySets/> is where you can add all the libraries you’d like to include in the uberjar. These must also be defined in your pom.
Finally, add the maven-assembly-plugin to the pom:
<build>
<finalName>hello-world</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/assemble/exe.xml</descriptor>
</descriptors>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
To run the assembly and build the executable jar:
$ mvn assembly:assembly $ java -jar target/hello-world-exe.jar Hello World!
I tested the hello-world example using the latest Maven release (2.0.8) and maven-assembly-plugin-2.2-beta-1. If you run into any issues try and update your Maven plugins by running:
$ mvn -U compile
You can download the example hello-world project here.
Thank you very much for the description. I spent hours trying to figure it out.
Karel Klic
2008/02/27 at 14:02
great tutorial, simple and to the point.Thank you.
scott
2008/08/29 at 08:43
Thanks for the instructions!
zzorn
2008/11/14 at 10:40
maven archiver already does this for you
http://maven.apache.org/shared/maven-archiver/
raycee
2009/01/22 at 10:59
Well done, it was really helpful.
Vadym Shkil
2009/07/03 at 06:19
thanks for the info! its too bad maven doesn’t give as good examples as you
tommy
2010/04/11 at 17:32
Thank you very much!!!!!!!!
Miko
2010/09/20 at 15:42
Customized the pom for my app and works like a charm. Thanks.
vj
2011/01/21 at 15:42
Great tutorial! thanks!
Yossale
2011/01/24 at 06:23
You can replace
`src/main/resources/META-INF/MANIFEST.MF`
with
`org.qnot.example.App`
and remove your `MANIFEST.MF`
Ali
2011/07/29 at 02:44
Hi All,
I want to execute a java file with main class.This main class needs to read the value form the pom file during the execution.
org.apache.maven.plugins
maven-surefire-plugin
<!–
ie
tst03
mydoamin.net
–>
browserfirefox
environmenttst03
tldmydoamin.net
**/JbehaveRegressionJunitStories.java
And then in the main class ,I read it as System.getProperties(), the values in the pom are not read by the API System.getProperties() method.
Anuj
2011/09/20 at 11:21
Its working fine, thank you
Rajasekar
2011/11/24 at 00:09
Thanks. How does one make this work without having maven run all my unit tests. ie ., I just need Maven to compile the source and assemble without running all my unit tests.
Shawn San
2012/10/27 at 22:51
@Shawn – To skip unit tests you can run:
mvn assembly:assembly -Dmaven.test.skip=trueAndrew
2012/10/28 at 09:12