A Sourceful of Secrets

Andrew E. Bruno

Creating executable jars with Maven

with 14 comments

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.

About these ads

Written by Andrew

2008/01/24 at 20:53

Posted in Java

14 Responses

Subscribe to comments with RSS.

  1. Thank you very much for the description. I spent hours trying to figure it out.

    Karel Klic

    2008/02/27 at 14:02

  2. great tutorial, simple and to the point.Thank you.

    scott

    2008/08/29 at 08:43

  3. Thanks for the instructions!

    zzorn

    2008/11/14 at 10:40

  4. maven archiver already does this for you
    http://maven.apache.org/shared/maven-archiver/

    raycee

    2009/01/22 at 10:59

  5. Well done, it was really helpful.

    Vadym Shkil

    2009/07/03 at 06:19

  6. thanks for the info! its too bad maven doesn’t give as good examples as you

    tommy

    2010/04/11 at 17:32

  7. Thank you very much!!!!!!!!

    Miko

    2010/09/20 at 15:42

  8. Customized the pom for my app and works like a charm. Thanks.

    vj

    2011/01/21 at 15:42

  9. Great tutorial! thanks!

    Yossale

    2011/01/24 at 06:23

  10. 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

  11. 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

  12. Its working fine, thank you

    Rajasekar

    2011/11/24 at 00:09

  13. 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

  14. @Shawn – To skip unit tests you can run:
    mvn assembly:assembly -Dmaven.test.skip=true

    Andrew

    2012/10/28 at 09:12


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: