gradle: exclude a dependency in making fatJar - gradle

There are lots of repeated answers on how to exclude an individual file from a fatJar. Typically, the file is excluded are in META-INF and they are excluded either because of a filename conflict, or because it is a signature copied from a dependency libarar Jar file which isn't valid for the newly created Jar file.
Example for maven:
How can I tell which signed jar is causing maven-shade-plugin to fail?
Example for gradle:
Removing Jar Signatures in Gradle Build
These solutions, however, only removed the offending file individually.
How can we make a fatJar with a specific dependency library (not individual files in that library) excluded?
For example, in question 36226033, it's easy to exclude the signature copied over from BouncyCastle, but is there a way to exclude the dependency library bcprov-jdk15on-*.jar entirely, so that the user must have the library available in order to execute the generated fat Jar?
This is proven not working:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'com.alphawallet.scripttool.Main'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
exclude('**/bcprov-jdk15on-1.62.jar')
with jar
}
With exclude('**/bcprov-jdk15on-1.62.jar'), the content of that jar file is still copied over to the fat jar generated.
Thanks. The motivation is to ship my Java application to systems that provides their own security library BouncyCastle (e.g. Debian Linux), instead of embeding an unsigned copy of that security library.

I don't know how excludes and includes works, but I would expect that these configurations work on a class file level, because that what the jar is working on.
It's not working on jars.
I would go for this solution:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'com.alphawallet.scripttool.Main'
}
baseName = project.name + '-all'
configurations.compile.findAll { file ->
// file is of type java.io.File
// when true, jar file is unziped and added
file.name != "bcprov-jdk15on-1.62.jar"
}.sort { it.name }
.collect { file ->
logger.info("Including file: ${file.name}")
file.isDirectory() ? file : zipTree(file)
}
with jar
}

Related

Unable to run jar file. (Error: Could not find or load main class co.pissarra.Mainkt)

I was trying to create a small webserver using spark and kotlin.
But I am stuck at the step where I should be able to create a jar of the project and run it from the command line. But I get the following error on running java -jar pissarra-core-all-1.0-SNAPSHOT.jar
Error: Could not find or load main class co.pissarra.Mainkt
I tried using intellij idea's artifact creation without success, and moved on to creating jar using build.gradle. Following is the code for the same
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Version': version,
'Main-Class': 'co.pissarra.Mainkt'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
After running ./gradlew clean followed by ./gradlew fatJar, I am able to create jar file in build/libs/ directory. This jar also gives the same error.
On extracting the jar file, I am able to see the directory structure co/pissarra/ with the Mainkt.class file inside it. Also it has the META-INF directory with MANIFEST.MF file whose content are as follows
Manifest-Version: 1.0
Implementation-Version: 1.0-SNAPSHOT
Main-Class: co.pissarra.Mainkt
Since stackoverflow does not allows to upload files, you can find the jar file here. You can also build the jar file from the github project here.
Check your MANIFEST file. The class name should be "MainKt" and not "Mainkt"

Shadow Jar doesn't include dependencies into fat jar

I am new to Gradle and to shadow jar (Gradle version of Maven's Shade plugin). I am building a fat jar, in which I want to merge service files (that's why I am using shadow jar in the first place).
According to the documentation shadowJar task inherits from gradle Jar task. So, one would assume that it will work exactly as a jar task.
Here is the snippet of the jar task:
jar {
zip64 true
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
}
As a result, it produces a fat jar with all the dependencies exploded, what is anticipated. When I change task name from jar to shadowJar, like below:
shadowJar {
zip64 true
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
}
I get a jar file that contains only files from the current project, dependencies are excluded. Why is this happening?
You don't need to define the from... part. The plugin will include all dependencies automatically.

gradle to bundle nested jar dependencies into module output jar

How to make gradle to included some dependencies into module resulted jar as jar? i.e. to make jar with nested jar's e.g. in lib folder ?
This is not Android project, and this should be done for many modules in multi-module project, so fatJar, uberJar, shadowJar alike solutions seem not to fit.
You just need to add an additional from directive to include dependencies in your jar:
task jarJar(type: Jar) {
baseName = project.name + '-jarjar'
from { configurations.compile }
with jar
}

Why does my jar file not not contain any class files?

I'm trying to add a task (gen or gen2) to my build.gradle that does exactly the same as the Jar-task:
version = "0.0.1"
apply plugin: 'java'
task('gen', type: Jar) {
}
task gen2(type: Jar)
Running
gradle jar
generates a JAR-file that contains .class-files, while running
gradle gen
or
gradle gen2
generate a JAR-file that does NOT contain any .class-files.
Whats wrong with my class definition?
To build a jar with all the classes from main, as a default jar task would, do this:
task gen2(type: Jar){
baseName = 'gen2Jar'
from sourceSets.main.output
}
You can also do from(sourceSets.main.output){ include "package" } to customize what packages are included.
Alternatively, to copy settings from the default jar task:
task gen(type: Jar){
baseName = 'genJar'
with jar
}
Infact you can have both of these in the same build.gradle. Running gradle jar builds default jar. gradle gen builds genJar.jar and gradle gen2 builds gen2Jar.jar, all of which contain all the classes from java.main

Override file in Gradle build dependency jar

I would like to output a jar which internally contains my dependency jar but overrides a particular file in the dependency jar with my own. I am using gradle build. Can someone help me with this? The task which build jar for me:
jar {
archiveName "JarName-${version}.jar"
dependsOn configurations.runtime
from {
(configurations.runtime - configurations.provided).collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
Well I actually stopped duplicating the file by including the following strategy:
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
It seems like my changes becomes a part of the output jar before they are being overridden by the file in my dependency jar. So, restricting duplicacy helped in resolving the issue.

Resources