Explain Codes LogoExplain Codes Logo

Including dependencies in a jar with Maven

java
maven-plugins
dependency-management
jar-packaging
Alex KataevbyAlex Kataev·Oct 17, 2024
TLDR

To include all dependencies into an "executable JAR", utilize the Maven Assembly Plugin. Configure this plugin in your pom.xml file:

<plugin> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <archive> <manifest> <mainClass>fully.qualified.MainClass</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin>

Now, activating mvn clean package creates a jar named *-jar-with-dependencies.jar in the target directory that holds all dependencies and correctly identifies the main class.

Deep dive into Maven plugins

Maven assembly plugin: One JAR to rule them all

The maven-assembly-plugin complements your packaging needs by aggregating project output along with its dependencies.

To define a main class in the jar manifest and evade the ScaryMainClassNotFound monster, use this configuration:

<configuration> <archive> <manifest> <mainClass>your.package.MainApp</mainClass> </manifest> </archive> </configuration>

Remember: when dealing with Ring Bearers... err... multiple main classes or modules, a well-defined manifest is precious (LOTR fans here?)

Maven shade plugin: Master of disguise

The maven-shade-plugin can take alias management to another level - it can repack classes and resolve package conflicts. Think Agent 007 of the JAR world.

To add this secret agent to your pack, add these lines similarly:

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <!-- Just same old, same old as assembly plugin --> </executions> <configuration> <!-- Specifics for shade such as fancy disguises (relocations) --> </configuration> </plugin>

Customization: Make it yours

Resources, certificates, config files – sometimes a project needs more than just classes, and you need to pack them all. Both plugins can cover them via the <includes>.

Binding the assembly goal to package is essential for a seamless build process (who likes hiccups, anyway?) Perfect your mvn assembly:single command line spells for better development!

In-depth understanding of assembly

Managing dependency classpath

In certain scenarios, your jar might run in different environments needing dynamically loaded resources. The maven-dependency-plugin copies dependencies to target/lib. Tweak maven-jar-plugin to reference these dependencies in your class path as:

<plugin> <artifactId>maven-jar-plugin</artifactId> <configuration> <classpathPrefix>lib/</classpathPrefix> </configuration> </plugin>

Repackaging: Level up with Maven's repackaging plugins

For complex builds or microservice architectures, Spring Boot offers its own plugins and auto-configuration logic to simplify deployments.

Packaging pitfalls: Common issues

Duplicate classes and jar signing can be problematic. Duplicates can lead to runtime conflicts; signed jars might not execute as expected when repackaged. But fear not, dear reader, careful use of <excludes> in your assemblies or shades can combat these common foes.