Create an executable jar containing all application runtime dependencies


(Adam Murdoch) #1

Support the creation of an executable jar that includes all the runtime dependencies of the application.

Implementation ideas

One approach would be to add a new ‘executable-jar’ plugin. This would add an ‘applicationJar’ task, which builds the fat executable jar.

Extra credit

Some ideas to build on this:

  • Integrate with the application plugin, to share configuration such as the main class name and runtime classpath. * Integrate with the application plugin, to include the fat executable jar in the distribution, in place of the standard thin jar + runtime dependency jars. * Integrate with the java plugin, to allow the fat executable jar to be published instead of the standard thin jar. This would also need to mess with the generated pom.xml or ivy.xml, to remove the dependency declarations for those runtime dependencies that are packaged in the fat jar (this is an advanced move).

(Stig Kleppe-Jørgensen) #2

I have started implementing this using One-JAR as the classpath “solver”. Now I’m just wondering if you have thought about naming standards for plugins with more than one word. I have used gradle-‘name’-plugin before, but I am not sure about gradle-executable-jar-plugin.


(Stig Kleppe-Jørgensen) #3

I’ve put the plugin on GitHub (gradle-executable-jar-plugin) and have a couple of releases that are used internally.


(Jon Lachelt) #4

Stig, when I attempt to use this I get this error:

java.lang.NoClassDefFoundError:

org.gradle.api.internal.artifacts.repositories.CommonsHttpClientResolver

What am I doing wrong?

Also, don’t I need to tell it which class to use for the application? I don’t see that in your example build.gradle file.

NOTE: I’m new to gradle.


(Stig Kleppe-Jørgensen) #5

Hmm…it seems Gradle 1.0-milestone-7 has removed this internal class. Thanks for finding this!

Have also changed documentation to reflect needing a mainClass property.


(Stig Kleppe-Jørgensen) #6

I’m not sure how to fix this yet, so have added an issue for it


(Harsh Kumar) #7

Is this still open or has someone already done it. If not was thinking of doing it.


(Luke Daley) #8

It hasn’t been done yet.


(Stig Kleppe-Jørgensen) #9

The plugin mentioned earlier by me is usable for generating executable jar files that can be run with:

java -jar name-of-jar.jar

Maybe build on that?


(seandanielgillespie) #10

Any particular reason you didn’t submit this to gradle repository?


(Stig Kleppe-Jørgensen) #11

Hmm…you mean the wiki? Just me being forgetful, really :slight_smile:


(John Engelman) #12

There is also Shadow plugin which is a port of Maven’s Shade plugin. We wrote and use it to produce self-contained and executable jars - https://github.com/johnrengelman/shadow/


(Björn Kautler) #13

Just my 2ct: I wouldn’t allow or at least not promote publishing a fat JAR on Maven or Ivy repositories, as this contradicts the sense of those systems, managing the transitive dependencies. JUnit e. g. had made this mistake which they corrected by now. They published a fat JAR with hamcrest-core bundled. This gives e. g. problems if you use something else that has hamcrest as a dependency as there is no conflict resolution possible but both classes land on the classpath and depending on which JAR is first on the classpath determines where the classes come from. Because of this and similar problems it not a good idea to publish a fat JAR that bundles anything besides the own classes on a system like Maven or Ivy repositories.


(John Engelman) #14

I believe the request is simply for a plugin that can create a self-contained distribution for your application. How/If you deploy that to a repository is up to the end user. But there are many uses cases for distributing an application via a jar file where you don’t have the ability to resolve a Maven or Ivy dependency graph on the client side.


(Björn Kautler) #15

Quote from the original post: “Integrate with the java plugin, to allow the fat executable jar to be published instead of the standard thin jar. This would also need to mess with the generated pom.xml or ivy.xml, to remove the dependency declarations for those runtime dependencies that are packaged in the fat jar.”

A plugin to create a fat jar is great and as Gradle is very open and flexible you can of course always achieve pushing a fat jar to a repository. This is even possible already, just with mor effort needed. I just think that this should not be actively advertised, as it is a very bad practice and can cause serious problems.


(Scott Palmer) #16

The application plugin should support this directly. I would like to have it keep the application Jar separate from the dependencies. I currently make my own “bundle” task to create a jar with a manifest including the main class and the classpath with “lib/” prepended to all the dependency jars. This way I have one main jar and all the dependencies in a “lib” folder.

I would like the application plugin to do this automatically. I find it very strange that it doesn’t already create a simple executable jar instead of the overly complex launch scripts that it currently does. Some launch scripts would still be helpful. I like the added touch for OS X to set the app name for example, but those scripts would simpler if the jar was a standard executable jar.

Cheers,

Scott


(dave) #17

‘distJar’ does seem like something the application plugin should include along side distTar and distZip. Are there any plans to do so?


(Stig Kleppe-Jørgensen) #18

How would such a jar work? If you mean to just bundle the dependencies inside the main jar, it is not really usable for much out of the box.