I am trying to create two 'fatJars' using ShadowJar plugin as part of the same build file. I am trying to run the shadowJar task twice inside the build by declaring two tasks of ShadowJar type
So far, I have defined two tasks like so:
task shadowjar_one (type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar)
task shadowjar_two (type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar)
and now trying to create my jars like so:
shadowjar_one {
mergeServiceFiles()
exclude 'somefile.txt'
archiveName = 'jar1.jar'
appendManifest {
attributes 'Main-Class': 'some.package.someClass'
}
}
shadowjar_two {
mergeServiceFiles()
exclude 'someOtherfile.txt'
archiveName = 'jar2.jar'
appendManifest {
attributes 'Main-Class': 'some.package.someOtherClass'
}
}
The problem I am facing is that the jars are created, but they do not contain any of the other dependencies (packages, files etc) from 'other' jars. The jars only contain the META-INF and current project's package directories.
Any idea what could be the issue?
Note: I am expecting two slightly different jar files to be produced. Both must have the same project codebase with differences in the Main-Class attribute of manifest (and a couple of other small differences)
Many Thanks!
The author gave a very good solution (in that it is both short and working) here:
https://github.com/johnrengelman/shadow/issues/108
I'm actually using a tweak to that solution, appearing at the bottom of that page (I've added remarks to explain it a little):
task bootstrapNodeJar(type: ShadowJar) {
group = "shadow" // Not a must have, but it's always good to have a group, you can chose whichever - this is the one shadowJar belongs to
description = "Builds a Bitsquare bootstrap node executable jar" // Same as the above
manifest.attributes 'Main-Class': 'io.bitsquare.app.cli.BootstrapNodeMain' // The main attraction! Be sure to update this line
classifier = 'bootstrapNode' // General jar task property - see more about it in the Gradle manual
from(project.convention.getPlugin(JavaPluginConvention).sourceSets.main.output) // Leave as is
configurations = [project.configurations.runtime] // Same as the above
exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA') // This one is actually really important!
// Here you can add other Jar properties like destinationDir, for example
}
Shadow plugin author here - I was just made aware of this question here. What you are encountering is the fact that the Shadow plugin creates and configures a shadowJar
task using a set of defined conventions for that task.
When you are creating your own tasks using that type, you'll need to manually define a number of those configuration options since there is no way for the plugin to know what your intent is with those tasks.
You can reference the configuration that is being applied to the built in task here: https://github.com/johnrengelman/shadow/blob/master/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy#L38-L63
A workaround that I've used is to have a single shadowJar task, but pass parameters. In your case, something like:
shadowJar {
mergeServiceFiles()
exclude System.properties.getProperty('exclude')
archiveName = System.properties.getProperty('archiveName')
appendManifest {
attributes 'Main-Class': System.properties.getProperty('mainClass')
}
}
Then, when starting your application:
gradlew shadowJar -Dexclude=... -DarchiveName=... -DmainClass=...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With