Creating a Runnable Binary Distribution With Maven Assembly Plugin

There are many ways that we can use when we want to share our applications with other people. For example, we can create a binary distribution that can be downloaded from our website.

This blog post describes how we can create a runnable binary distribution by using the Maven Assembly Plugin.

The requirements of our binary distribution are:

  • The jar file that contains the classes of our example application must be copied to the root directory of the binary distribution.
  • The manifest of the created jar file must configure the classpath and the main class of our application.
  • The dependencies of our application must be copied to the lib directory.
  • The startup scripts of our application must be copied to the root directory of the binary distribution.

Let’s start by taking a quick look at our example application.

The Example Application

The example application of this blog post has only one class that writes the string 'Hello World!' to the log by using Log4j. The source code of the HelloWorldApp class looks as follows:

import org.apache.log4j.Logger;

public class HelloWorldApp
    private static Logger LOGGER = Logger.getLogger(HelloWorldApp.class);

    public static void main( String[] args )
    {"Hello World!");

The properties file that configures Log4j is called, and it is found from the src/main/resources directory. Our file looks as follows:

log4j.rootLogger=DEBUG, R


log4j.appender.R.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

The startup scripts of our example application are found from the src/main/scripts directory. This directory contains the startup scripts for the Windows and *nix operating systems.

Let's move on and find out how we can create a jar file that configures the classpath and the main class of our example application.

Creating the Jar File

We can package our application into a jar file by using the Maven Jar Plugin. We can configure the Maven Jar Plugin by following these steps:

  1. Ensure that classpath of our example application is added to the created manifest file.
  2. Specify that all dependencies of our application are found from the lib directory.
  3. Configure the main class of our example application.

The configuration of the Maven Jar Plugin looks as follows:

        <!-- Configures the created archive -->
            <!-- Configures the content of the created manifest -->
                <!-- Adds the classpath to the created manifest -->
                    Specifies that all dependencies of our application are found
                    from the lib directory.
                <!-- Configures the main class of the application -->

Let’s move on and find out how we can assemble the binary distribution of our example application.

Assembling the Binary Distribution

We can assemble our binary distribution by using the Maven Assembly Plugin. If we want to create a binary distribution that fulfills our requirements, we have to follow these steps:

  1. Create an assembly descriptor that dictates the execution of the Maven Assembly Plugin.
  2. Configure the Maven Assembly Plugin to use the created assembly descriptor.

First, we have create an assembly descriptor that dictates the execution of the Maven Assembly Plugin. We can create this assembly descriptor by following these steps:

  1. Create an assembly.xml file to the src/assembly directory.
  2. Configure the format of our binary distribution. Ensure that a zip file is created.
  3. Copy the dependencies of our application to the lib directory.
  4. Copy the startup scripts of our application from the src/main/scripts directory to the root directory of the binary distribution.
  5. Copy the jar file of our example application from the target directory to the root directory of the binary distribution.

Our assembly descriptor looks as follows:

    <!-- Specifies that our binary distribution is a zip package -->

    <!-- Adds the dependencies of our application to the lib directory -->
                Project artifact is not copied under library directory since
                it is added to the root directory of the zip package.

            Adds startup scripts to the root directory of zip package. The startup
            scripts are copied from the src/main/scripts directory.
            Adds the jar file of our example application to the root directory
            of the created zip package.

Second, we have to configure the Maven Assembly Plugin to use the assembly descriptor that we created in step one. We can do this by adding the following plugin declaration to the plugins section of our POM file:

        <!-- Configures the used assembly descriptor -->

We have now configured the Maven Assembly Plugin to create our binary distribution. Let’s move on and find out what this really means.

What Did We Just Do?

We can create our binary distribution by running the command mvn clean package assembly:single at the command prompt. After we have done this, Maven creates the file to the target directory. This zip package is the binary distribution of our example application.

The name of the binary distribution is created by using the following formula: [the value of the finalName element]-[the id of the used assembly].[the format of the distribution].

In other words, the name of the created binary distribution is because:

  1. The value of the finalName element, which is found from our pom.xml file, is maven-assembly-plugin.
  2. The id of our assembly is bin.
  3. We want to create a binary distribution that is packaged into a zip file.

When we run the command unzip at the command prompt, the maven-assembly-plugin-bin directory is created to the target directory. The content of the created directory is described in the following:

  • The maven-assembly-plugin-bin directory contains the jar file of our example application and the startup scripts.
  • The maven-assembly-plugin-bin/lib directory contains the log4j-1.2.16.jar file.

We can run our example application application by using the startup scripts found from the maven-assembly-plugin-bin directory. When we run our application, we see the following output:

$ ./ 
0    [main] INFO  net.petrikainulainen.mavenassemblyplugin.HelloWorldApp  - Hello World!  

Let’s move on and summarize what we learned from this blog post.


This blog has taught us two things:

  • We can customize the manifest of the created jar file by using the Maven Jar Plugin.
  • We can create a binary distribution, which doesn't use the so called "fat jar" approach, by using the Maven Assembly plugin.
93 comments… add one
  • x78527 May 29, 2011 @ 10:29

    Thanks! That works for me.

  • Jim Rayhawk Jul 26, 2011 @ 23:43

    Great post!! This was exactly what I needed. Thanks for putting this together.

  • Prash Oct 22, 2011 @ 17:57

    Hi Petri,
    That was a great tutorial..thanks a ton for your efforts
    before i was struggling to put together my maven build as an app to invoke from batch script
    your example provided just what i needed to do that all in one click

    Thanks again


    • Petri Oct 23, 2011 @ 12:33

      Hi Prash,

      It is good to hear that you found this tutorial useful. At least I know that I have managed to actually help someone :)

  • Radu Nov 23, 2011 @ 11:28

    Hey Petri, thanks a lot for this wonderful tutorial, I'm new to Maven and I was having a hard time trying to pack the binaries of my project into an archive with external jars and all.. your ideas served me greatly :)


    • Petri Nov 23, 2011 @ 12:04


      it is good to hear that I could help you out.

  • laurent Dec 12, 2011 @ 1:27

    You helped me too. Tanks a lot.

  • laurent Dec 12, 2011 @ 2:08

    It can be useful to use 0755 so that the script file is executable.

    Also, it is safer to use ${} instead of target.

    And since the jar is added at the root of the archive, you should use false in to prevent including it twice.

    • Petri Dec 12, 2011 @ 13:54


      Good to hear that I could help you out. Also, you gave some nice improvement ideas. I will update the code examples and the sample project as soon as possible.

  • Petri Dec 18, 2011 @ 16:37

    I moved the example application to GitHub and fixed the issues mentioned by Laurent.

  • Jacob Lorensen Jun 15, 2012 @ 13:35

    Hi. I may be extremely dense, and miss something obvious. But how do I get all the nice external jar files that I depend on in the maven build file included in the assembly generated jar file? It seems to me it only includes what is specifically present in my own project directories and not any dependencies.

    Do I combine it with "one-jar" plugin, or?

    • Jacob Lorensen Jun 15, 2012 @ 13:54

      Forget it... had a bad-brain-day or something and forgot mvn assembly:single :(

      • Petri Jun 15, 2012 @ 14:04


        No worries. It happens to all of us =)

    • Petri Jun 15, 2012 @ 14:03

      Hi Jacob,

      Thanks for your comment. You can configure this in the assembly descriptor. The dependencySets element of my assembly descriptor example configures the Maven assembly plugin to copy the dependencies of your project under the lib directory.

  • jose antonio Sep 5, 2012 @ 0:12

    Hi Petri,

    I tried with your simple example app, but it gave me an exception at runtime

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at net.petrikainulainen.mavenassemblyplugin.HelloWorldApp.(
    Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
    at Method)
    at java.lang.ClassLoader.loadClass(
    at sun.misc.Launcher$AppClassLoader.loadClass(
    at java.lang.ClassLoader.loadClass(

    I took a look inside the maven-assembly.jar and it didn´t have a log4j.jar inside not even a lib/ dir in the target directory. Have you any idea what could it be?. Would you mind try out with your example? Thanks in advance, great post.

    • Petri Sep 5, 2012 @ 8:17

      Hi Jose,

      What method were you using when you tried to run the example application (command line, IDE) and were you running it after you had assembled the binary distribution? I will describe two alternative ways of running this example:

      1) From command line without using the Maven assembly plugin.

      Run the following command at the root directory of the project:

      mvn exec:java -Dexec.mainClass="net.petrikainulainen.mavenassemblyplugin.HelloWorldApp"

      2) From command line after the binary distribution has been created.

      First, you have to create the binary distribution. You can do this by running the following command at command prompt (again, run this at the root directory of the project):

      mvn assembly:single

      Second, you have unzip the created zip package. You can find the zip package from the target directory. Look for a file called

      Third, you have to run the application. You can run the application by using the provided start up scripts (either startup.bat or Remember to run these scripts from the directory in which you unzipped the binary distribution. You can do this by running the following commands at command prompt:

      cd target
      cd maven-assembly-plugin
      startup.bat (or

      I will add this information the actual blog entry as well (Thanks for pointing this out). If this did not solve your problem, please let me know.

  • Nadia Sep 6, 2012 @ 21:07

    Thanks for putting this tutorial together, wish I have found it before, it was helpful.

    • Petri Sep 6, 2012 @ 21:20

      Hi Nadia,

      It is great to hear that I could help you out.

  • gibffe Oct 18, 2012 @ 17:05


  • Ulrich Knaack Dec 7, 2012 @ 13:39


    I downloaded your example and tried it, but maven doesn't build a zip-File.
    I'm using maven 3.0.4 , eclipse Juno SR1 and m2eclipse 0.12.1. I'm not using the embedded version of maven within m2eclipse but the stand-alone one.

    Can you help me?

    Regards, Ulrich

    • Petri Dec 7, 2012 @ 13:57

      Hi Ulrich,

      I have got a few additional questions for you:

      • Are you trying to use the Maven Assembly plugin directly from Eclipse?
      • If you run the command mvn assembly:single at the command prompt, what happens? This should create file called to the target directory.

      Also, please note that my example application creates the binary distribution only when the correct goal of the Maven Assembly plugin is executed. In real life scenario it might be better to create the distribution during the package lifecycle phase.

  • David Lilljegren Jan 18, 2013 @ 0:53

    Superb tutorial worked like a charm!

    • Petri Jan 18, 2013 @ 9:26


      Thank you! It is great to hear that this blog entry was useful to you.

  • jayasankar Feb 5, 2013 @ 20:05

    Great article; very helpful

    • Petri Feb 5, 2013 @ 20:17

      Thank you. It is good to hear that I could help you out.

  • Ramesh Feb 6, 2013 @ 9:19

    Great post :)

    • Petri Feb 7, 2013 @ 21:56

      Thank you!

  • Danilo Feb 19, 2013 @ 22:24

    Thanks a lot man, you saved my life.

    Danilo - Brazil

    • Petri Feb 21, 2013 @ 18:35

      You are welcome!

      Thank you for leaving a comment. It is always nice to get feedback from my readers.

  • Noah Camp Mar 1, 2013 @ 21:28

    Wow... THANK YOU! After days of searching and reading posts on StackOverflow, I was unable to come up with a suitable approach to a jar packaging requirement I have. This approach is exactly what I needed since I'm dealing with RSA jars that throw security exceptions if unpacked/repackaged into an uber-jar.

    As a newer person to maven, I found this article extremely helpful.

    Again, thank you!

    • Petri Mar 2, 2013 @ 21:30

      You are welcome!

  • Thiago Henrique Mar 16, 2013 @ 4:44

    Great article! Very util, nice good!

    • Petri Mar 16, 2013 @ 10:31

      Thank you. I am happy to hear that you like it.

  • Girish Mar 25, 2013 @ 13:53

    Very useful. Thanks a lot.

    • Petri Apr 16, 2013 @ 10:11

      You are welcome!

  • Phantom1024 Apr 16, 2013 @ 1:17

    Thank you for this article. I had been searching for days.

    • Petri Apr 16, 2013 @ 10:12

      You are welcome. I am happy hear that I could help you out. :)

  • Jirka Nov 14, 2013 @ 14:52

    Thanks for the article! It seems to be exactly what I'm looking for.

    I have one problem - when I package your "assembly-plugin" example, there is created only maven-assembly-plugin.jar file but not you mentioned directory structure. I am a beginner with Maven, what am I doing wrong? Do need these directories exist before I do a package command?

    • Petri Nov 14, 2013 @ 18:33


      You are not doing anything wrong.

      The package goal doesn't create the binary distribution. It simply packages the project and creates the jar file. You can create the binary distribution by running the following command at command prompt:

      mvn assembly:single

      I will add this information to the README of the example application. Thanks for pointing this out.

      • Jirka Nov 19, 2013 @ 14:50

        Hi Petri,
        one more thing. When I call mvn assembly:single plugin ZIP file is created but doesn't contain jar file, please see this screenshot -

        Do I need to cal another command to create a jar file? I have tried mvn compile, mvn package but no jar has been created. Thanks again.

        • Petri Nov 19, 2013 @ 18:27


          If you use the command mvn assembly:single, the package phase is not invoked. I didn't expect this. I tested this myself now (I used Maven 3.1.1) and it seems that you have two options:

          1. Run the command mvn package assemby:single at command prompt.
          2. Run the command mvn assembly:assembly at command prompt (This will invoke the package phase as well).
          • Jirka Nov 19, 2013 @ 20:16

            Yes, "mvn assembly:assembly" works for me, thanks. You made my day!

      • Jirka Nov 19, 2013 @ 15:05

        Petri, back to my last comment - I forgot to call "mvn package" command, now It works like a charm! You can delete my comment, thanks.

        • Petri Nov 19, 2013 @ 18:31

          If you don't mind, I will not delete it because I forgot that running the mvn assembly:single command doesn't invoke the package phase (see my answer to your previous comment).

  • Jirka Nov 19, 2013 @ 20:23

    Maybe one suggestion to improve your code - is there some chance how to use artifactId or name for new jar file name? Your code works but generates "maven-assembly-plugin.jar" / "". It's not a problem, it works, but... :)

    • Petri Nov 19, 2013 @ 20:39

      You can change the file names by using the finalName element. For example, if you change it to: <finalName>foo</finalName>, the names of the created files are: foo.jar and

  • Dec 24, 2013 @ 0:27

    Your way of describing everything in this piece of writing is genuinely nice, all be
    capable of easily be aware of it, Thanks a lot.

  • Bryan Karsh Jan 1, 2014 @ 1:33

    Hi Petri --

    Thanks for the great blog. I have a question that is stumping me. I am using the assembly plugin with a bin distribution -- it works great. My script makes use of a flexible shell script in /bin, config files in /etc, logs in /log, jars in /lib. -- everything is great.

    However, I have to add some new functionality that requires shading. I've never worked with the shade plugin. I am also not super excited to completely revamp what I have now with the assembly plugin set up.

    My question is -- any tips on shading a handful of dependency jars, but keep the rest of the assembly configuration in tact (including some external jars, my /etc config files, etc).

    Any help much appreciated!


    • Petri Jan 1, 2014 @ 1:50

      Hi Bryan,

      I haven't used to Maven Shade plugin either but it seems that it is possible to include and exclude the artifacts which are added to the "Uber jar" created by the Shade plugin. It is also possible to include and exclude the artifacts added to the binary distribution.

      I would try to solve this problem by following these steps:

      • Configure the Maven Shade plugin to include only the artifacts which must be shaded.
      • Configure the Maven Assembly plugin to exclude the shaded artifacts.
      • Configure the Maven Assembly plugin to add the "Uber jar" created by the Maven Shade plugin to the binary distribution instead of the "regular" jar.
      • Ensure that the shading is done before the binary distribution is created.

      I have no idea if this will work but based on the documentation of these two plugins, it should work. If you get it to work, it would be interesting to hear about it!

  • Adil Fulara Jan 20, 2014 @ 13:21

    Hi Petri,

    Greetings !! As always your blog is very helpful.
    Do you have any plans to make this work with multi-module project ?

    Keep up the good work.

    • Petri Jan 20, 2014 @ 18:10

      Thank you for your kind words. I really appreciate them.

      About your question:

      I can write a separate tutorial about using the Maven Assembly plugin in a multi-module projects. Do you have any special requirements which I should take into account?

      • Adil Fulara Jan 22, 2014 @ 15:29

        Hi Petri,

        Perfect !! I have been trying it without success.
        Regarding what i want is more of an open ended question.
        I am trying to architect a template where i have

        1. A module for API ( interfaces ) ( JAR )
        2. A module or two for Implementation ( ex: DB solution, In memory solution) which uses the API module ( JAR )
        3. UI module to leverage API and Implementation for User Interaction
        4. Module for Main Entry ( Not sure if this is needed or not but this would be like a public static main function and any pre or post run configurations like schema migrations etc. )
        5. Parent module to have the assembly xml to combine all the dependencies into lib and provide a startup script along with README and other documentation.

        I tried to use the moduleset and tried to create a sample project. so far i have been unsuccessful. Partly due to my limited knowledge of advanced maven knowledge.

        Let me know if the above seems like a wrong approach to creating a template for rapid app development.

        Adil Fulara.

        PS: How do I subscribe to update from you on this page ? I didnt get any email regarding your follow up comment.

        • Petri Jan 22, 2014 @ 23:06

          Hi Adil,

          I got a pretty good idea about your requirements. I will try to create a similar project structure and write a blog post about it.

          At the moment it is not possible to get an email notification when someone answers to your comment. I will contact you by using your email address tomorrow.

          • Adil Fulara Jan 23, 2014 @ 8:15

            Awesome Petri..!!

            I have made it a routine to check your blog regularly. Your articles ate clear, precise and to the poi
            point. I always recommend my friends to check your tutorials too.

            Feel free to share your project on github and let me know if i can assist. After all its all a learning process and good to know where I made mistakes.

            Adil Fulara.

  • vince Jan 31, 2014 @ 0:03

    This is very nice and clear. I want to go one step further though. I have the ProjectArtifact with a name like ${artifactid}-{version}.jar, but on the archive I want this to be just ${artifcatid}.jar. Any idea how to do this?

    • Petri Feb 1, 2014 @ 20:49

      I haven't personally tried this but you could try to use the outputFileNameMapping element as suggested here.

  • kumar Feb 10, 2014 @ 13:50

    Hi Petri,
    how can i run the wicket programs with out using maven and eclipse like IDEs.Please help.

    • Petri Feb 10, 2014 @ 20:48

      Hi Kumar,

      If you have the war file of the application, you can deploy it to a servlet container. If you have to create the war file, you have to use a some kind of build tool (Ant, Gradle, or Maven).

  • Ivaylo Mar 19, 2014 @ 15:54

    Many thanks!!!

    • Petri Mar 19, 2014 @ 16:01

      You are welcome!

  • BergIT Apr 5, 2014 @ 8:20

    Thank you for you explain, but you didn't add in the begin of tuto what artifactID we should choose when we create new Maven Project

    • Petri Apr 6, 2014 @ 11:19

      There are no universal rules for selecting the artifactId of a Maven project. Just pick something which describes the project in question or follow the guidelines of your employer (if it is a work project).

  • kris Jun 5, 2014 @ 1:53

    very useful article and neat pom files. I hacked(?) it to generate zip file for multi module project. Wondering if you can extend this article to multi module setup (github code works for single module)

    • Petri Jun 5, 2014 @ 18:08

      Thank you for your comment. I added your blog post idea to my Trello board, and I will write the blog post in the future.

  • Julian Oct 3, 2014 @ 14:20

    Thank you for this nice tutorial. It was really helpful.

    One question:

    Why is it preferable to create a zip containing the libs and runnable scripts instead of creating a simple large jar-file with all dependencies included and which can be executed simply by double-clicking?

    Thank you

    • Petri Oct 3, 2014 @ 21:46

      Hi Julian,

      If you are creating a binary distribution for an application, I think that you can use the approach that makes sense to you (the single jar approach might be a better choice).

      On the other hand, if you are creating a binary distribution for a library or a framework, packaging its dependencies into a single jar doesn't make any sense because you must not decide how the users of your library (or framework) should manage their dependencies.

      • Julian Oct 3, 2014 @ 22:52

        Thank you very much for your answer. Now i get the point :)

        • Petri Oct 4, 2014 @ 16:50

          You are welcome!

  • Tom Oct 8, 2014 @ 16:19

    As others have already mentioned, awesome tutorial. Very thorough.

    • Petri Oct 8, 2014 @ 21:04

      Thank you for your kind words. I really appreciate them.

  • Anirban Nov 9, 2014 @ 6:26

    Nice one, helped me !:)

    • Petri Nov 9, 2014 @ 20:34

      Thanks! I am happy to hear that this blog post was useful to you.

  • Prateej Gupta Jan 16, 2015 @ 0:12

    This was immensely helpful.
    Precise and to-the-point tutorial!
    Thanks a lot!

    • Petri Jan 16, 2015 @ 23:23

      You are welcome! I am happy to hear that this tutorial was useful to you.

  • Dizzi Jan 16, 2015 @ 1:13

    Thank you. You've gave me at least few hours of sleep.

    • Petri Jan 16, 2015 @ 23:24

      You are welcome. I am happy to hear that this blog post helped you to get some sleep.

  • Alex Mar 17, 2015 @ 19:23

    In your example is packed in maven-assembly-plugin.jar. If I will want to change logging settings for binary distribution it requires unzipping, changing and zipping file back.
    Is it possible to place in 'maven-assembly-plugin/conf' directory and add additional entry to manifest 'Class-Path' attribute with maven?

  • Daniel Apr 16, 2015 @ 16:38

    I only needed to add this executions stuff to the assembly-plugins configuration in pom.xml to get exactly what I wanted with your help:





    • Petri Apr 16, 2015 @ 17:04

      Unfortunately Wordpress strips XML elements from comments :( Anyway, It is good to hear that you were able to solve your problem!

  • Isaac Oct 28, 2015 @ 3:39

    And... the question is ... how do I make me sure that my "classpath of my "example application" is added to the created manifest file." ? Can you explain that? Thank you. I am using Eclipse.

    • Petri Oct 29, 2015 @ 17:42

      Check out the section titled: 'Creating the Jar File'. If you look at the configuration of the Maven Jar plugin, you notice that you can do this by setting the value of the addClasspath element to true.

  • cdg Feb 8, 2016 @ 2:51

    2016 and this is still relevant. Chapeau and thanks for the info. :-)

    • Petri Feb 8, 2016 @ 9:29

      You are welcome!

  • Vishal Sep 2, 2016 @ 21:37


    You are awesome! The simple way of explaining complex things and actually make it working in real is a distinct property that not every blogger has in my opinion.

    • Petri Sep 5, 2016 @ 21:14

      Thank you for your kind words. I really appreciate them.

  • S Boot May 5, 2017 @ 18:56

    It is nice blog with good understanding.
    I am facing below issue.
    I have created jar called domain.jar (which contains only .class files) using assembley plugin and now I push this to nexus.
    I am trying to use this dependency jar in my other application with classifier and I am able to do that.
    Now the issue, while downloding domain.jar it comes with extra jars which is not required.
    I also mention false in descriptor file.

  • Daniele Jul 7, 2017 @ 10:42

    Works, Thanks! I have 2 class main in my project, can i create 1 runnable binary distibution with 2 jars?

    • Petri Jul 10, 2017 @ 9:37


      If you want to create two jar files from one POM file, you have to add two executions to the configuration of the Maven Jar plugin (take a look at this post). After you have created these jar files, it should be fairly easy to add them to the binary distribution by using the Maven Assembly plugin.

Leave a Reply