Building Distinct Executable JARs for Multiple Java Main Classes
When a single codebase contains multiple standalone applications, each with its own entry point, the build process must generate separate executable artifacts. Consider a project containing both a command-line utility and a network service.
Define the entry points in separate packages to maintain clear bonudaries:
package com.myapp.cli;
public class DataImporter {
public static void main(String[] arguments) {
System.out.println("Initializing data import sequence");
}
}
package com.myapp.api;
public class RestGateway {
public static void main(String[] arguments) {
System.out.println("Starting HTTP gateway on port 8080");
}
}
Configure the maven-shade-plugin to create multiple shaded JARs during the package phase. Each execution generates an independent artifact with its own manifest pointing to the correct main class:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<id>package-importer</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>importer</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.myapp.cli.DataImporter</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
<execution>
<id>package-gateway</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>gateway</shadedClassifierName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.myapp.api.RestGateway</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Execute the build to generate all artifacts:
mvn clean package
This porduces three JAR files in target/: the original unshaded JAR, plus two executable varients with classifiers importer and gateway. Run either application using:
java -jar target/myapp-1.0.0-importer.jar
java -jar target/myapp-1.0.0-gateway.jar