Maven: Bundling Dependencies Into Executable JARs

Crafting Java applications often involves managing dependencies efficiently, especially when distributing projects. Maven, a powerful build automation tool, offers a seamless solution to package all their dependencies into a single, easy-to-distribute JAR file through the Maven Assembly Plugin.

Streamlining Dependency Bundling

The Maven Assembly Plugin streamlines the process of assembling a project’s dependencies into an executable JAR. This plugin eradicates the hassle of distributing multiple JARs by consolidating all required dependencies into a single, standalone JAR file. This packaged JAR contains not only your project’s compiled code but also every external library it relies on.

Simple Configuration for Efficient Packaging

Configuring the Maven Assembly Plugin in your project’s pom.xml file is straightforward. By defining the plugin and specifying the desired assembly, such as jar-with-dependencies, you instruct Maven to create an executable JAR bundled with all necessary dependencies. Additionally, specifying the main class in the manifest ensures the generated JAR is executable with a simple command.

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </plugin>
  </plugins>
</build>

A Concrete example: a Java Runnable which generates PDF

As proof of concept, we will show how to create a Runnable JAR file which bundles an external dependency in the JAR file. This Runnable JAR file will create a PDF file from Java.

Let’s begin with a simple Maven project which uses the following dependency to generate a PDF from Java Code:

<dependency>
  <groupId>com.github.librepdf</groupId>
  <artifactId>openpdf</artifactId>
  <version>1.3.33</version>
</dependency>

And then, here is the Java Class which leverages openpdf library to generate a PDF file from Java Strings:

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfString;
import com.lowagie.text.pdf.PdfWriter;

 

public class App {

 
    public static void main(String[] args) {

        System.out.println("Hello World");

        // step 1: creation of a document-object
        Document document = new Document();
        try {
            // step 2:
            // we create a writer that listens to the document
            // and directs a PDF-stream to a file
            final PdfWriter instance = PdfWriter.getInstance(document, new FileOutputStream("HelloWorld.pdf"));

            // step 3: we open the document
            document.open();
            instance.getInfo().put(PdfName.CREATOR, new PdfString(Document.getVersion()));
            // step 4: we add a paragraph to the document
            document.add(new Paragraph("Hello World"));
        } catch (DocumentException | IOException de) {
            System.err.println(de.getMessage());
        }

        // step 5: we close the document
        document.close();
    }
}

Building and executing the Runnable JAR file

Firslty, build the Runnbale JAR file as follows:

mvn clean compile assembly:single

as you can see by digging into the JAR file, it contains all the external dependencies you need to execute the Runnable JAR file:

Maven's Guide to Executable JARs with Dependencies

Finally, run the executable JAR file and check it produces the HelloWorld PDF file:

java -jar target/example-1.0-SNAPSHOT-jar-with-dependencies.jar 

Conclusion

In summary, the Maven Assembly Plugin serves as a pivotal tool for bundling dependencies, allowing for the creation of comprehensive, executable JARs. Its simplicity and efficiency in handling dependencies pave the way for smoother deployment and usage of Java applications across diverse environments.

Source code: https://github.com/fmarchioni/mastertheboss/tree/master/various/jar-with-dependency