Creating Jar with Dependencies using Maven Assembly Plugin

Learn to use the Maven assembly plugin for creating executable Jar files with dependencies, its various goals, descriptors using an example.

Maven assembly plugin output

Learn to use Maven assembly plugin to package an application as an executable fat Jar that includes all the dependencies to make the application run on any machine. Note that we can use the assembly plugin for packaging the application in other formats, such as zip, tar, tar.gz and even war files.

We can control inclusions or exclusions using this plugin. For more controlled packaging, use Maven Shade plugin.

1. A Simple Application

Let us create a simple Java application that prints a log message into the console. To keep things simple, we have included only Log4j2, SLF4J2 and JUnit 5 dependencies.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MainClass
{
    private static Logger LOGGER = LoggerFactory.getLogger(MainClass.class);
    public static void main( String[] args )
    {
        LOGGER.info( "Hello World! from Inside a Jar..." );
    }
}

2. Including Maven Assembly Plugin

To package this application, as fat jar, include maven-assembly-plugin plugin in pom.xml file.

2.1. Pre-defined Goal and Descriptors

The assembly plugin has two goals:

  • help: displays help information on maven-assembly-plugin.
  • single: packages an application bundle or distribution using the assembly descriptor.

The plugin relies on the provided descriptors for controlling the execution and packaging of the project. Though we can create our own descriptors for custom packaging, it provides the following default descriptors:

  • bin: Creates a binary JAR produced by running ‘mvn package‘ plus any README, LICENSE, and NOTICE files available in the project root directory.
  • jar-with-dependencies: creates a JAR that contains the binary output of your project, along its the unpacked dependencies.
  • src: packages the contents of the project’s /src directory structure.
  • project: produces an assembly containing the entire project, minus any build output in /target directory.

2.2. POM Changes

We are using the descriptor jar-with-dependencies for creating a single package for all the compiled resources. Additionally, we have provided the MainClass classpath as a Manifest entry. Its main() method will be executed when we execute this jar file from the command line.

Including the maven-assembly-plugin dependency will result in a larger Jar file because it will include the plugin Jar file as well as its dependencies, additionally. Consider adding the plugin dependency only when you need to use it during the build process for providing specific functionalities to your build lifecycle.

<!-- Optional dependency inclusion -->

<dependencies>
  <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.4.2</version>
        <type>maven-plugin</type>
    </dependency>
</dependencies>

<!-- Required plugin declaration -->

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
          <descriptorRefs>
              <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
              <manifest>
                <mainClass>com.howtodoinjava.app.MainClass</mainClass>
              </manifest>
          </archive>
      </configuration>
      <executions>
          <execution>
              <id>make-assembly</id>
              <phase>package</phase>
              <goals>
                <goal>single</goal>
              </goals>
          </execution>
      </executions>
    </plugin>
  </plugins>
</build>

3. Packaging as Executable Jar

3.1. Default Packaging

Run the maven package command in the project’s root folder to compile and package the project as a fat jar.

$ mvn clean package

The command will produce two jar files in the /target folder:

  • executable-jar-demo-1.0-SNAPSHOT.jar: This is a thin jar that does not include its dependencies. If you use this jar, it will search for the dependencies in the classpath.
  • executable-jar-demo-1.0-SNAPSHOT-jar-with-dependencies.jar: This is a fat jar and includes all required classes and dependencies. We can run this jar file in any system where Java is installed.

3.2. Custom Packaging

The generated file name contains the assembly id, which may be desired at times. We can set it to false.

<configuration>
  <appendAssemblyId>false</appendAssemblyId>
  ...
  ...
</configuration>

Now the plugin will produce a single artifact with name executable-jar-demo-1.0-SNAPSHOT.jar.

4. Demo

To run the fat jar, run it with 'java -jar' from the terminal. It will execute the application. In our case, it will print the log message in the console.

5. Conclusion

In this tutorial, we learned to use the Maven assembly plugin for creating executable Jar files with dependencies. we learned to configure various options provided by the plugin to control the build processing and output artifacts.

Happy Learning !!

Sourcecode on Github

Leave a Comment

    • Add exclusions under <configuration> tag.

      <excludes>
      <exclude>**/*.jsp</exclude>
      <exclude>**/*.js</exclude>
      <exclude>**/*.jpg</exclude>
      <!– Add more exclusions if needed –>
      </excludes>

      Reply
  1. If you add the dependency

      <dependency>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.4.2</version>
            <type>maven-plugin</type>
        </dependency>
    

    the fat jar generated is very very fat. It seems it includes all the code for the maven-plugin. But if I just put the version number of the maven-assembly plugin element in the plugin element like this

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>3.4.2</version>
          <configuration>
              <descriptorRefs>
    

    the fat jar contains only the code of my application and the code of the java libraries my applications depends on.

    Isn’t it better to do it this way ?

    Reply
    • Yes, you are correct. When you add the Maven Assembly Plugin as a dependency in your project, it gets included in the generated JAR along with all its dependencies, which can result in a larger JAR file. On the other hand, specifying the plugin directly in the build section of your POM file avoids including the plugin and its dependencies in the final JAR.

      Reply
  2. Following these instructions doesn’t create the fat jar for me. Nor do any of the other instructions on the internet relating to make-assembly even if I literally cut and paste the entire mvn pom file and change the names to match my project. Always just creates a single “thin” jar.

    To create the fat jar I have to do:

    mvn assembly:single

    Reply
    • Actually what did the trick for me was when I found out that I had put the <plugin> within <pluginManagement> which is wrong, it should go into <plugins>, after that it worked like a charm!.

      Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.