Search code examples
javamavenjar

Maven Shade Without Unpacking


let me tell you from the beginning

I'm trying to learn picocli so created a project via maven, added dependencies, wrote some code, now I wanna see its output I have two ways (i think) use maven exec plugin or create an executable jar (uber jar) and run it through java -jar (since I added .jar to windows PATHEXT, ASSOC and FTYPE i can run without java -jar)
second is more pleasant to me so I tried to create an uber jar via maven shade plugin
log info from the command line via mvn clean package and content of the final uber jar brought me this question:

why shade plugin unpack every jar into the final uber? this makes some overlapping in META-INF/MANIFEST.MF and module-info.class (even if it doesn't make any bugs is it not better to not have anything missing)
is it not better to have all jar files + project specific jar without unpacking in the root of final uber jar plus a META-INF/MANIFEST.MF that point to the main class? isn't more cleaner ?, something like below

enter image description here

for sure there was a reason behind it (packaging extracted jars)? what are the pros and cons of packaging unextracted jars (like the picture above)?

and finally is there any ready-to-use plugin for packaging uber jar without unpacking dependencies (i know is it possible via configuring assembly plugins)


Solution

  • The biggest pro of using an uber JAR is that you don't need any custom class loader. The structure inside the JAR file is just like that of any other JAR file. The biggest con is one you already found - if multiple JAR files provide the same file, you need to handle that. The default is to pick one (first? last?), and all others are discarded. You can configure the plugin to merge them instead, but for some files that will be more difficult.

    There are alternatives.

    • In the past I've used onejar, but that hasn't been updated for over 10 years. I found a fork but that had its last commit in 2015.
    • If you create a Spring Boot application the default is to create a different type of JAR file.
    • Quarkus has similar options (it can also use uber JAR).

    These alternatives bundle the JAR files inside a JAR file. It can do this by adding some custom classes that perform custom class loading. While you can use this to create applications, you cannot use these JAR files as libraries in other projects.