What Is the Maven-Shade-Plugin Used For, and Why Would You Want to Relocate Java Packages

What is the maven-shade-plugin used for, and why would you want to relocate Java packages?

Uber JAR, in short, is a JAR containing everything.

Normally in Maven, we rely on dependency management. An artifact contains only the classes/resources of itself. Maven will be responsible to find out all artifacts (JARs etc) that the project depending on when the project is built.

An uber-jar is something that takes all dependencies, and extracts the content of the dependencies and puts them with the classes/resources of the project itself, in one big JAR. By having such an uber-jar, it is easy for execution, because you will need only one big JAR instead of tons of small JARs to run your app. It also eases distribution in some cases.

Just a side-note: avoid using uber-jar as a Maven dependency, as it is ruining the dependency resolution feature of Maven. Normally we create an uber-jar only for the final artifact for actual deployment or for manual distribution, but not for putting to Maven repository.


Update: I have just discovered I haven't answered one part of the question : "What's the point of renaming the packages of the dependencies?". Here are some brief updates that will hopefully help people having similar questions.

Creating an uber-jar for ease of deployment is one use case of the shade plugin. There are also other common use cases which involve package renaming.

For example, I am developing Foo library, which depends on a specific version (e.g. 1.0) of Bar library. Assuming I cannot make use of other version of Bar lib (because API change, or other technical issues, etc). If I simply declare Bar:1.0 as Foo's dependency in Maven, it is possible to fall into a problem: A Qux project is depending on Foo, and also Bar:2.0 (and it cannot use Bar:1.0 because Qux needs to use new feature in Bar:2.0). Here is the dilemma: should Qux use Bar:1.0 (which Qux's code will not work) or Bar:2.0 (which Foo's code will not work)?

In order to solve this problem, developer of Foo can choose to use shade plugin to rename its usage of Bar, so that all classes in Bar:1.0 jar are embedded in Foo jar, and the package of the embedded Bar classes is changed from com.bar to com.foo.bar. By doing so, Qux can safely depends on Bar:2.0 because now Foo is no longer depending on Bar, and it is using its own copy of the "altered" Bar located in another package.

Sample Image

Downsides of using Shade plugin relocation feature

The main issue is that it can fail in cases where the package name is directly defined (not just imported). For example, if you are using reflection and instantiating the a class by its name (including the package name) it will generate the wrong one. Similar problems can occur when the the package is defined in a manifest (there is a transformer for that). See the plugin info for more information.

Another place where this could be an issue is with a third party dependency which uses the same dependency. Consider for example package A which is provided. If package A depends on the relocated package it will in the run time use the provided instance instead of the relocated one. This can lead to unforeseen effects.

An additional issue is that in some cases, the package may contain some initialized/static information (e.g. it downloads some info once or has some big static table). In these cases it is important to understand that there are now TWO completely separate instances of the package.

Excluding dependencies from javafx maven plugin

You can put this dependency in profile in your pom.xm file.
And active when needed.



Related Topics



Leave a reply



Submit