I'm using Java 17 with maven 3.9.9. My maven project libfoo
is used as a library by other end-user applications say myapp.jar
.
libfoo
has no choice but to depend on a bar:bar-core:1.2.3
whose code is out of my control (e.g. a proprietary client SDK), and 1.2.3
is the latest version. That artifact from hell is known to brings legacy transitive dependencies e.g.
logback
and jackson-databind
(evil) andcommon-zoo:common-zoo:0.0.1
(evil), with myapp.jar
itself depends on common-zoo:common-zoo:5.9.0
(good)My question is that, is there any technique I can use, to seal all the evilness within libfoo.jar
itself as implementation details of libfoo, such that
myapp
sees libfoo
as a single uber jar with 0 transitive dependencymyapp.jar
is not awared of evil classes on its runtime classpath, and links only to dependencies declared in its own pom, e.g. common-zoo:5.9.0
.Known problems with shade+relocate:
bar-core
is known to use Class.forName('com..XXX')
, thus relocating class with maven-shade-plugin breaks the code.Not unless you do class loader magic.
Creating a library uber jar with external dependencies is usually a bad idea because you will have two versions of the same class on the classpath (from your uber jar, taken from common-zoo:common-zoo:0.0.1
, and the one from common-zoo:5.9.0
) and it is essentially random which version gets loaded and used.
The way around it is shading, but you said that breaks the code.
You can, though, set specific dependencies to scope runtime
, meaning that they are not on the compile classpath for myapp.jar. But this only works if myapp.jar does not try to use a different (newer) version of the same library.