In an earlier post I mentioned that my latest work project encountered some surprises when trying to bundle an application and all of its dependencies into one big jar.
Last week a colleague tried using a different Gradle plugin to generate the jar more quickly, as that had been a noticeable bottleneck in the build process. He encountered more problems and reverted back to fatjar.
This week I stumbled across the shadowJar Gradle plugin. From all of the description and sample configuration it looked like nearly a drop in replacement for the fatjar plugin.
Some colleagues agreed that it looked quite promising and tried it out. It worked fine on one of our applications, but resulted in runtime failures on the other one so they abandoned this build optimisation activity.
After a little compare and contrast I found that the size of the files in META-INF/services differed. The jar generated with the fatjar plugin had some larger files than the jar generated with the shadowJar plugin.
Tracing back through the project dependencies indicated that the missing content was from the Jersey client artifacts. It soon became apparent that the duplicate file names across two jars wasn't intended for one to be a substitutable implementation of the other, so I looked into merging.
Sure enough, by default the fatjar plugin merges the contents of service files when generating the jar, but shadowJar does not.
A single line configuration update resulted in shadowJar producing a working jar - with a complete definition of the services.