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

A fat JAR is a single JAR file that contains the compiled classes of an application together with all of its dependencies, so the application runs on any machine that has Java installed. In Maven, the Maven Assembly Plugin (maven-assembly-plugin) builds a fat JAR with its predefined descriptor jar-with-dependencies. The same plugin also packages an application in other formats, such as zip, tar, tar.gz and war.

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 a fat JAR, we add the maven-assembly-plugin plugin to the pom.xml file.

2.1. Pre-defined Goal and Descriptors

The assembly plugin has the following two goals.

  • help displays help information on the 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. A descriptor defines what goes into the package and in which format. We can create our own descriptors for custom packaging, and the plugin also provides the following predefined 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 the project and its 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 use the descriptor jar-with-dependencies to create a single package of all the compiled resources. We also set the class MainClass as a manifest entry, so its main() method runs when we run the JAR file from the command line.

Adding the maven-assembly-plugin dependency makes the JAR file larger, because the JAR then includes the plugin JAR and its dependencies. Add the plugin dependency only when the build needs it.

<!-- 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 produces the following two JAR files in the /target folder.

  • executable-jar-demo-1.0-SNAPSHOT.jar is a thin JAR that does not include its dependencies, so the JVM searches for the dependencies in the classpath.
  • executable-jar-demo-1.0-SNAPSHOT-jar-with-dependencies.jar is the fat JAR and includes all required classes and dependencies. We can run this JAR file on any system where Java is installed.

3.2. Custom Packaging

The name of the fat JAR contains the assembly id (jar-with-dependencies) by default. To remove it, we set the option appendAssemblyId to false.

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

With this option, the plugin produces a single artifact named executable-jar-demo-1.0-SNAPSHOT.jar.

4. Demo

To run the fat JAR, we execute it with the command java -jar from the terminal. In our example, the application prints the log message in the console.

5. Conclusion

The Maven Assembly Plugin packages an application and all of its dependencies into one executable JAR file with the descriptor jar-with-dependencies. The option appendAssemblyId controls the name of the generated file.

Happy Learning !!

Sourcecode on Github

Leave a Comment

  1. For my case when i am trying to create fat jar, its also including jsp and js and images.

    • Add exclusions under <configuration> tag.

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

  2. 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 ?

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

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

    • 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!.

Comments are closed.

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.