Why another plugin to repack dependencies?
Repackaging a jar or war archive with all its dependencies to become a single archive is a common task when operating software on the JVM.
Historically, there have been many different ways to accomplish this. For Apache Maven, there are a number of plugins, such as:
- Maven Shade Plugin - The “classic” way to repackage dependencies
- Maven Assembly Plugin - Layout classes and dependencies using flexible assemblies
- Inline plugin - Easily create components that have external dependencies but should not “bleed” these dependencies into other code
- JarJar plugin - repackage dependencies inside a project artifact to avoid classpath conflicts
- Spring Boot Maven Plugin - The Spring Boot Maven Plugin […] allows you to package executable jar or war archives
Most of those approaches rewrite the class files and “flatten” all entries in the various classpath dependencies into a single jar. This is problematic for many reasons:
- Code may inspect class names and rely on specific, hard-coded package or class names, so repackaging breaks this
- Classpath artifacts are signed and can not be repackaged
- Entries may occur multiple times (especially in the
META-INF
directory) and flattening them either overrides them or logic must exist to combine them
The most promising way to repackage code is the Spring-Boot plugin, which
- packages the contents of the original jar unchanged into a special directory (
BOOT-INF/classes
) or keeps it as-is (META-INF
content) - packages dependencies into
BOOT-INF/lib
- adds custom startup code (
JarLauncher
) that creates the necessary classloaders and optionally unpacks dependencies that need special treatment. - adds only a few entries to the manifest file.
Unfortunately, the spring boot plugin itself is (for understandable reasons) geared towards use with the spring-boot ecosystem. Using it for non-spring applications requires some additional tweaking (and expects the spring libraries being packaged with the code even if they are not in use).
This plugin is a stripped down version of the wrapper code around the
Repackager
functionality found in the spring-boot-loader-tools. It
can be used with any JVM project that has a main class; especially it
can be used as a replacement for using the Apache maven-shade-plugin
when creating standalone jar applications.