Creating an Executable JAR with Dependencies Using Maven

Creating an Executable JAR with Dependencies Using Maven
Creating an Executable JAR with Dependencies Using Maven
Maven

Packaging Maven Projects into a Single Executable JAR

When working with Java projects, it's often necessary to package your application into a single executable JAR file for easy distribution. Maven, a powerful build automation tool, allows developers to include all necessary dependencies within this single output JAR.

This article will guide you through the steps needed to configure your Maven project to include all dependency JARs into your final executable JAR. By following these instructions, you'll simplify the deployment process and ensure your application runs smoothly across different environments.

Command Description
<plugin> Defines a Maven plugin to use during the build process. Plugins can execute specific tasks such as compiling code or packaging the project.
<groupId> Specifies the group identifier for the Maven project, usually a reverse domain name.
<artifactId> Defines the artifact's identifier, which is the project's name.
<version> Indicates the project's current version.
<build> Contains the build configuration for the project, including plugins and resources.
<descriptorRef> References a predefined descriptor for the Maven Assembly Plugin to use, such as "jar-with-dependencies".
<mainClass> Specifies the main class to be executed when the JAR file is run.
<execution> Defines an execution block within a plugin, specifying tasks to be performed at different build phases.
mvn clean package Command to clean the project and package it into a JAR file, including all dependencies.
java -jar target/...jar Command to run the generated JAR file, specifying the path to the JAR.

Creating and Running an Executable JAR with Maven

The scripts provided above demonstrate how to configure a Maven project to package all its dependencies into a single executable JAR file. The first script is a Maven pom.xml file, which contains the project's configuration. Within this file, the <plugin> tag is used to define the Maven Assembly Plugin. This plugin is crucial for creating an executable JAR that includes all dependencies. The <descriptorRefs> tag within the plugin configuration specifies the use of the jar-with-dependencies descriptor, which ensures that all the project’s dependencies are packaged into the final JAR file. The <mainClass> tag inside the <manifest> section is essential as it tells Maven which class contains the main method to run when the JAR is executed.

The <execution> block inside the plugin configuration is where the action happens. It specifies that the plugin's goal single should be executed during the package phase of the build lifecycle. This is what triggers the creation of the JAR file with dependencies. The second script is a simple command line instruction: mvn clean package. This command cleans the project (removing previous build artifacts), compiles the source code, runs tests, and packages the project into a JAR file. The final JAR file will be located in the target directory of the project and named according to the artifactId and version specified in the pom.xml.

Creating an Executable JAR File with Dependencies Using Maven

Maven Configuration Script

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.example.MainClass</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Running the Maven Command to Package the JAR

Command Line Instructions

mvn clean package
# This command will compile the code, run the tests, and create the JAR file
# The JAR file will include all dependencies specified in the pom.xml
# It will be located in the target directory of the project
# The final JAR file will be named my-app-1.0-SNAPSHOT-jar-with-dependencies.jar

# To run the JAR file, use the following command:
java -jar target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar
# Ensure that the mainClass specified in the pom.xml is correct
# This will start your application with all dependencies included

Advanced Maven Techniques for Packaging Dependencies

Beyond the basic configuration for creating an executable JAR with Maven, there are additional techniques that can enhance your build process. One such technique involves using the shade plugin instead of the assembly plugin. The Maven Shade Plugin offers more advanced features for creating uber-JARs (JARs with dependencies included). It allows you to rename packages to avoid classpath conflicts and provides better handling for duplicate classes and resources. Additionally, it offers fine-grained control over which dependencies are included in the final JAR.

Another important aspect is managing the size of your JAR file. Large JAR files can be cumbersome and slow to transfer or load. The maven-shade-plugin can help with this by allowing you to exclude unnecessary files and classes, thus reducing the size of the final JAR. You can also configure the plugin to minimize the JAR by removing non-essential information such as unused classes or redundant resources. These advanced configurations can be particularly useful when working on large projects with numerous dependencies.

Common Questions and Solutions for Maven Executable JARs

  1. How do I specify the main class in my JAR?
  2. You can specify the main class using the <mainClass> tag within the <manifest> section of the Maven plugin configuration.
  3. How can I exclude specific dependencies from the final JAR?
  4. Use the excludes tag within the plugin configuration to specify dependencies that should not be included in the final JAR.
  5. What is an uber-JAR?
  6. An uber-JAR is a JAR file that contains not only your compiled code but also all of its dependencies.
  7. How can I avoid classpath conflicts in my JAR?
  8. The maven-shade-plugin allows you to rename packages within dependencies to avoid conflicts.
  9. How do I handle duplicate classes in dependencies?
  10. Configure the maven-shade-plugin to manage duplicate classes and resources by specifying how duplicates should be handled in the final JAR.
  11. Can I include only specific files from a dependency?
  12. Yes, you can configure the maven-assembly-plugin or maven-shade-plugin to include only specific files from a dependency.
  13. How do I run the packaged JAR?
  14. Use the java -jar command followed by the path to your JAR file.
  15. How can I verify the contents of my JAR file?
  16. You can use the jar -tf command to list the contents of the JAR file.
  17. What if my JAR file is too large?
  18. Use the maven-shade-plugin to exclude unnecessary files and minimize the JAR size.

Concluding Thoughts on Maven Executable JARs

Creating an executable JAR with dependencies using Maven simplifies the deployment process for Java applications. By properly configuring the pom.xml file and utilizing plugins like the Maven Assembly Plugin or Maven Shade Plugin, developers can package all necessary dependencies into a single JAR file. This approach ensures that the application can run seamlessly in various environments, making distribution and execution straightforward. Following these steps will help you manage your project's dependencies effectively and create reliable, executable JAR files.