A plain Maven JAR normally contains only your project’s compiled classes and resources. To run it with java -jar, the archive needs a Main-Class manifest entry, and every runtime dependency must either be available on the classpath or packaged into an executable “fat” JAR.

Option 1: thin JAR with a main class

Configure maven-jar-plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>

Build it:

1
2
mvn clean verify
java -jar target/my-app-1.0.0.jar

This works only when the application has no external runtime dependencies or those dependencies are supplied separately.

Option 2: executable fat JAR with Shade

The Maven Shade Plugin combines application classes and dependencies:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.Main</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

The services transformer merges META-INF/services entries used by Java’s service loader. Other resource files may also require explicit merge rules.

Signed dependency errors

Shading signed JARs can leave signature metadata that no longer matches the merged archive. If runtime verification fails with a signature error, exclude signature files:

1
2
3
4
5
6
7
8
9
10
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>

Only do this when distributing the resulting artifact under appropriate dependency licenses and after understanding the security implications.

Verify the result

1
2
3
jar tf target/my-app-1.0.0.jar | head
unzip -p target/my-app-1.0.0.jar META-INF/MANIFEST.MF
java -jar target/my-app-1.0.0.jar --help

Run integration tests against the packaged JAR, not only classes inside the Maven test process. Pin plugin versions, use a fixed Java toolchain, and avoid embedding secrets or environment-specific configuration.

For Spring Boot applications, prefer spring-boot-maven-plugin; its executable archive format and launcher handle dependencies differently from a generic shaded JAR.