shadowJar is not including dependent jars, instead including classes in my Helidon Gradle project

Viewed 427

I have a Helidon MP project and followed the steps provided here to build a fat jar

https://blogs.oracle.com/developers/post/migrating-a-helidon-se-application-to-gradle

gradlew shadowJar builds successfully with all the dependencies extracted as classes instead of including the dependent jar as is. Due to this, I'm getting the following exception.

Exception in thread "main" org.jboss.weld.exceptions.IllegalArgumentException: WELD-001325: No instance of an extension class io.helidon.microprofile.server.ServerCdiExtension registered with the deployment at org.jboss.weld.manager.BeanManagerImpl.getExtension(BeanManagerImpl.java:1445) at org.jboss.weld.util.ForwardingBeanManager.getExtension(ForwardingBeanManager.java:239) at io.helidon.microprofile.server.Server$Builder.(Server.java:154) at io.helidon.microprofile.server.Server.builder(Server.java:91) at com.ananth.osef.Main.startServer(Main.java:28) at com.ananth.osef.Main.main(Main.java:23)

How do I build the shadow jar that includes the individual jars instead of extracted classes?

I'm using gradle 5.6.3 and shadow 5.2.0

2 Answers

I don't know Gradle very well and I don't know shadow, but making a fat jar is often a bad approach since, as you've discovered, meaningfully located resource files can get merged or overwritten or omitted (as is probably happening above with a META-INF/beans.xml resource), regardless of which build tools you're using.

If your Helidon SE program is destined for Docker and/or Kubernetes, you'd be better served by following the deployment strategy found in one of Helidon's quickstart examples, which takes advantage of container layers and doesn't run into the issue you are citing above.

If this is is a shadow question ("How do I use shadow to make a fat jar of jars?") I'll let someone better qualified answer that.

Extensions are defined in files under META-INF/services/.... The problem when shadowing (or shading) is, that these files exist in different artefacts but only one is present in the final jar. To fix this, you have to merge the files.

Luckily, there is a handy Gradle Shadow transformer doing exactly that: https://imperceptiblethoughts.com/shadow/configuration/merging/#merging-service-descriptor-files

shadowJar {
  mergeServiceFiles()
}

I had the same problem when using the Maven Shade plugin and used this resource transformer: https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#ServicesResourceTransformer

<transformers>
  <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
Related