I have somewhat of a terminology problem. If I emb...
# community-support
m
I have somewhat of a terminology problem. If I embed and relocate dependencies, am I making a "shadow" jar or a "shadowed" jar?
I guess proper terminology is "a jar with 'shadowed' bundling"?
Because the jar itself is not "shadowed", right? The dependencies are...
Am I overthinking this? 😅
g
I’ve usually seen it called a shaded jar, I guess that comes from the Maven plugin with the same name
👀 1
v
I think the jar itself is "shadowed", because when you unpack it, you get your own classes and the classes of your dependencies. Over here, we call it either a shaded jar or a fat jar. But if you're talking from a gradle variant/attribute perspective, then it would be "shadowed" bundling: https://docs.gradle.org/current/javadoc/org/gradle/api/attributes/Bundling.html
m
Shade: https://www.merriam-webster.com/dictionary/shade#dictionary-entry-2
Copy code
to hide partly by or as if by a shadow
to shelter or screen by intercepting radiated light or heat
Shadow: https://www.merriam-webster.com/dictionary/shadow#dictionary-entry-2
Copy code
to cast a shadow upon
to accompany and observe especially in a professional setting
So I guess the process of "embeding + relocating" is more "shading" (hiding) than "shadowing"
Over here, we call it either a shaded jar or a fat jar.
fat jar doesn't say anything about relocation. You can make a fat jar by embedding all the jars. I prefer "shaded jar"
that comes from the Maven plugin with the same name
Ah good catch! Maven is "Maven Shade Plugin", Gradle is "Gradle Shadow Plugin"
v
fat jar doesn't say anything about relocation. You can make a fat jar by embedding all the jars. I prefer "shaded jar"
For me that difference is "bad practice fat jar" (repacked dependencies) vs. "good practice fat jar" (spring boot jar way) 🙂
m
If you're shipping a binary, there's no real need to relocate, I don't see a non-relocated fat jar as always a bad practice
v
I do. 🙂 Repacking jars into your jar is imho an abuse of a detail in the Java specification. And I did not yet see a valid use-case for them, except transitive bad-practice like the older Minecraft framworks requiring you to have all in one jar. Besides being forced to do it, you do not have any real advantages but major disadvantages and problems. For some JARs it is not possible to repack them and preserving functionality, like for example a security provider. Those jars have to be signed by an Oracle-sanctioned certificate or they do not work. Repacking signed jars needs to leave out some files or it breaks the repacked result jar. Some frameworks or similar need files that are path-wise identical in several jar files, much like service loader files. Some of these files can be merged, like the service loader files if your repacking mechanism supports merging that file type. But it does not support all cases and some of those file even cannot be merged. ... So imho it is always better, more reliable, and more future-proof to not create fat jars if you can avoid it in any way. And when combining that fat jar with other jars on the same classpath, using relocation should always be done if you really need such bad-practice fat jars, or you can get really strange problems. While on the other hand, relocation of course also does not necessarily always work flawlessly.
m
I just have one counter example which is shipping a CLI jar. I know you can ship distribution zip, etc... but I kind of like the simplicity of
java -jar cli.jar
Agree with everything else
v
You can use distribution zip, yes, I prefer being able to do
./cli
. Especially when in the future you might need additional things like determining the current directory to be able to have some configuration file, or also if
java
is not in the
PATH
but
JAVA_HOME
is properly defined, or when using
jlink
to generate a minimal JRE and ship it together with the distribution, ... All that is quite hard or impossible to do when using
java -jar cli.jar
, or at that point the users have to re-adjust how they call the CLI. 🙂 Theoretically, you can still use
java -jar cli.jar
when you use
Class-Path
attributes in the manifest, of course you would still ship an archive that needs to be unpacked first. And if it just for the simplicity of using
java -jar cli.jar
, you could as well use the good-practice fat jar, i.e. the way Spring Boot JARs work, by packing the full JARs as-are into your JAR and having a classloader that loads the classes from there.
m
Fair enough 👍