I know that question was asked a lot and has many answers, but i still get it and I don't understand why...
I am trying to generate a .jar
from a projet with dependencies with gradle.
I have a class src/main/java/Launcher.java
, in which I have my main
method.
there is my build.gradle
plugins {
id 'java'
id 'application'
}
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
mainClassName = 'Launcher'
repositories {
mavenCentral()
}
dependencies {
compile 'commons-io:commons-io:2.1'
compile 'io.vertx:vertx-core:3.4.0'
compile 'io.vertx:vertx-web:3.4.0'
compile 'com.google.code.gson:gson:1.7.2'
compile "com.auth0:java-jwt:3.1.0"
compile 'org.mongodb:mongo-java-driver:3.4.1'
compile 'com.google.guava:guava:24.1-jre'
compile 'commons-io:commons-io:2.6'
}
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
I use $>gradle assemble
to generate my jar
then $>java -jar path/to/my/.jar
And i get the error "could not find or load main class Launcher"...
I dont understand why, when I look in the .jar, I have Launcher class and in META-INF I have my manifest
Sorry for still asking this question in 2018 but i'm loosing my mind trying to figure out what's wrong. I hope somone will have the answer !
I reproduced your issue locally.
Just add exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
to the jar task.
This will exclude the signatures of interfering dependencies.
You are running into the the one major problem when building a FAT JAR:
One of your source JARs is signed and merging it into one fat jar destroys the signature.
It looks like Java recognizes that there are unsigned classes and ignores everything but the signed classes. As all classes that do not belong to the signed library are unsigned (like your Launcher
class) they are ignored and therefore can#T be loaded.
In your case it looks like that the dependency org.bouncycastle:bcprov-jdk15on:1.55
of com.auth0:java-jwt:3.1.0
is the signed jar file. Because my sample project correctly executes Launcher
when I uncomment this dependency.
Bouncy castle is a crypto provider that requires a valid signature otherwise it will not run from my experience. Therefore it is impossible to create a fat jar for your project that just contains all classes.
You can try to create a fat jar with everything except Bouncycastle and ship Bouncycastle JAR seperatly.
Or a fat jar that contains all the required JAR files inside (JAR inside JAR) and that uses a special class loader that is able to load classes from within such a JAR inside a JAR. See for example: https://stackoverflow.com/a/33420518/150978
Try to exclude .SF .DSA .RSA files, example below, Nipun
Hope this works out for you
task customFatJar(type: Jar) {
baseName = 'XXXXX'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
with jar
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
manifest {
attributes 'Main-Class': 'com.nipun.MyMainClass'
}
}