Keywords: Maven Build | Executable JAR | Assembly Plugin
Abstract: This article provides an in-depth analysis of common problems encountered when building executable JAR files with Maven, particularly focusing on dependency integration and main class configuration errors. Through a detailed case study, it explains the configuration differences between Maven Assembly Plugin and JAR Plugin, offers correct configuration examples, and presents debugging methodologies. The discussion also covers Java version compatibility and build lifecycle binding, helping developers avoid common pitfalls and ensure fully functional executable JAR generation.
Problem Context and Symptom Analysis
In Java project development, using Maven to build executable JAR files is a common deployment requirement. However, many developers encounter various issues during configuration, resulting in JAR files that fail to execute properly. This article examines a real-world project named "logmanager" to analyze typical problems in its build process.
Build Artifact Analysis
When executing the mvn assembly:assembly command, Maven generates two JAR files in the target directory: logmanager-0.1.0.jar and logmanager-0.1.0-jar-with-dependencies.jar. These files serve different purposes:
- Standard JAR File: The first file is generated by the Maven JAR Plugin during the
packagephase, containing only compiled class files from the current module without any dependencies. - JAR with Dependencies: The second file is produced by the Maven Assembly Plugin and should theoretically include all class files from the current module along with its dependency libraries.
Error Diagnosis and Root Causes
The user reported two distinct error messages:
- When double-clicking
logmanager-0.1.0.jar:Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit. - When double-clicking
logmanager-0.1.0-jar-with-dependencies.jar:Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar
These errors reveal two critical configuration issues:
Standard JAR File Issues
In the original configuration, the Maven JAR Plugin was configured to generate an executable JAR:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
This configuration presents two problems: First, the standard JAR doesn't include project dependencies, making it non-functional even with a main class specified. Second, the error message indicates the JAR file actually lacks the main class, possibly due to path or configuration issues during the build process.
JAR with Dependencies Issues
A more serious problem exists in the Assembly Plugin configuration. While the original configuration specified the jar-with-dependencies descriptor, it omitted the crucial archive configuration section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
This configuration generates a JAR file that contains all dependencies but whose META-INF/MANIFEST.MF file lacks the Main-Class attribute, preventing the JVM from identifying the executable entry point.
Correct Configuration Solution
Based on the problem analysis, the correct configuration requires adjusting the roles and configurations of both plugins:
Simplify JAR Plugin Configuration
Remove executable configurations from the JAR Plugin, allowing it to focus on generating standard module JARs:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<!-- Keep default configuration, do not add executable properties -->
</plugin>
Complete Assembly Plugin Configuration
Add complete archive configuration to the Assembly Plugin to ensure the generated executable JAR contains proper main class declaration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Build Lifecycle Binding
By binding the assembly:single goal to the package phase through the executions configuration, the dependency-included executable JAR will be automatically generated when executing mvn install or mvn package, eliminating the need to run the assembly:assembly command separately.
Java Version Compatibility Configuration
For projects using Java 6, proper compiler plugin configuration is necessary to ensure bytecode compatibility:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
Verification and Debugging Methods
After completing the configuration, follow these steps to verify the build results:
- Execute
mvn clean installto complete the full build process - Navigate to the
targetdirectory and test the JAR file using command line:java -jar logmanager-0.1.0-jar-with-dependencies.jar - If issues persist, examine the MANIFEST.MF file content:
jar tf logmanager-0.1.0-jar-with-dependencies.jar META-INF/MANIFEST.MF - Verify main class accessibility using classpath approach:
java -cp logmanager-0.1.0-jar-with-dependencies.jar com.gorkwobble.logmanager.LogManager
Technical Summary
Through this case study, several key technical points can be summarized:
- Plugin Responsibility Separation: JAR Plugin handles standard module JAR generation, while Assembly Plugin manages executable JAR creation with dependencies
- Manifest File Configuration: Executable JARs must have the
Main-Classattribute properly set inMETA-INF/MANIFEST.MF - Build Lifecycle Management: Properly binding plugin goals to build phases simplifies the build process
- Dependency Management: The
jar-with-dependenciesdescriptor automatically extracts and includes all dependency class files - Version Compatibility: Compiler configuration must align with the target runtime environment
With correct configuration, developers can focus on business logic development while delegating complex build and packaging tasks to Maven's automation, improving development efficiency and deployment reliability.