Keywords: Maven Assembly Plugin | Dependency Packaging | Single JAR File | Java Build Tool | Project Deployment
Abstract: This technical article provides a comprehensive guide on using Maven Assembly Plugin to package project dependencies into a single JAR file. Covering Maven 2.0.9 and above configurations, it explains the jar-with-dependencies descriptor mechanism and offers complete pom.xml examples. The article also discusses executable JAR configuration, command-line execution, and build lifecycle integration, helping developers overcome dependency management challenges.
Fundamental Principles of Maven Dependency Packaging
In Java project development, packaging dependencies into a single JAR file is a common requirement. By default, Maven generates JAR files containing only the project's compiled classes, while dependencies remain as separate JARs in the local repository. This separated deployment approach can be inconvenient in certain scenarios, particularly when distributing applications to end users.
The Maven Assembly Plugin addresses this by extracting dependency JAR files and repackaging their class files into the target JAR. This mechanism differs from simple JAR nesting (JAR files containing other JAR files) by organizing all class files under a unified classpath.
Core Configuration Implementation
Below is the basic configuration example for using Maven Assembly Plugin:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
In this configuration, the descriptorRef element specifies the use of the predefined "jar-with-dependencies" descriptor. This descriptor defines how dependencies are extracted and repackaged into the final JAR file. The execution section ensures automatic execution during Maven's package phase.
Executable JAR Configuration
For creating executable JAR files, additional main class configuration is required:
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.example.MainClass</mainClass>
</manifest>
</archive>
</configuration>
By specifying the fully qualified class name containing the main method through the <mainClass> element, Maven sets the Main-Class attribute in the generated MANIFEST.MF file, enabling direct execution via the java -jar command.
Command Line Execution Method
Beyond pom.xml configuration, packaging can also be triggered directly via command line:
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
This approach suits temporary packaging needs or quick validation without modifying project configuration. However, note that the assembly:assembly goal should be restricted to command line use, with the single goal recommended for formal build processes.
Build Lifecycle Integration
To integrate dependency packaging into standard Maven build workflows, use the single goal bound to the package phase:
<execution>
<id>create-executable-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
This configuration ensures automatic generation of dependency-included JAR files during each mvn package execution, achieving build process automation.
Impact of Dependency Scope
Maven dependency scope significantly affects packaging results. Only compile scope dependencies are included in the final JAR, while provided, test, and other scopes are excluded. For local JAR files, use the mvn install:install-file command to install them into the local repository first, then reference them with compile scope.
Advanced Configuration Options
The Maven Assembly Plugin offers rich configuration options for diverse packaging needs:
- Dependency Exclusion: Specific dependencies can be excluded using the
<excludes>element - File Filtering: Supports including or excluding specific files based on patterns
- Resource Handling: Configurable processing of resource files from dependency JARs
- Output Filename: Customizable naming rules for generated JAR files
Comparison with Alternative Plugins
Beyond the Assembly Plugin, the Maven ecosystem includes other dependency packaging solutions like the Maven Shade Plugin. The Shade Plugin provides advanced features including package renaming to avoid classpath conflicts and duplicate class handling. For complex projects, appropriate plugin selection should be based on specific requirements.
Practical Recommendations
When applying dependency packaging in real projects, consider these factors:
- JAR File Size: JAR files containing all dependencies can become large, affecting distribution and loading performance
- License Compatibility: Ensure third-party library licenses are compatible with the project
- Version Conflicts: Be aware that different dependencies might introduce conflicting library versions
- Testing Validation: Conduct thorough testing after packaging to ensure all functionality works correctly
By properly configuring the Maven Assembly Plugin, developers can easily create single JAR files containing all dependencies, significantly simplifying Java application deployment and distribution. This packaging approach is particularly suitable for standalone command-line tools, desktop applications, and similar scenarios.