Make jar with pom dependency in Gradle - java

I want to make an executable jar in Gradle:
task fatJar(type: Jar) {
manifest {
attributes (
'Main-Class': 'com.mycompany.json_validator.Main'
)
}
baseName 'json-validator'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
But i have an error from Gradle "Could not expand ZIP ..... archive is not a ZIP archive". I have this error on dependency, which is not .jar, it is pom.
compile group: 'org.glassfish.jersey', name: 'jersey-bom', version: '2.17', ext: 'pom'
How can i make an executable jar with it?

This appears to be the same issue described here: Gradle trying to unzip a pom typed dependency
The answer there describes what is happening and a possible remedy.
Alternatively, it should execute if you remove , ext: 'pom' from your dependency though I don't know if this is what you are going for.

Related

Gradle Build Jar with Local Dependencies

I am building a jar file using gradle. I have local jar files as dependencies. Those jars have additional local dependencies stored in the same directory. I used the following build.gradle file
plugins { id 'application' }
repositories {
flatDir{ dirs 'lib'
}
dependencies {
implementation name: 'localjar1'
implementation name: 'localjar2'
}
application { mainClass = 'mypackage.MyApp' }
jar {
from { configurations.runtimeClasspath.collect {it.isDirectory ? : zipTree(it) } }
manifest { attributes 'Main-Class': 'mypackage.MyApp' }
}
I built the jar using gradle jar, but when I try to run the jar:
java -jar myapp\build\libs\myapp.jar
I get the following error:
Unable to initialize main class mypackage.MyApp
Caused by java.lang.NoClassDefFoundError: com/localpackage/SomeClass
How do bring that dependency in correctly?
I also tried to include the entire local library as a dependency
implementation fileTree(dir: 'lib', include: '*jar')
But when I do this I get the error: java.lang.ClassNotFoundException: mypackage.MyApp
What else should I try?
** Note: I can run the application using gradle run

Gradle - FatJar - Could not find or load main class

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.
Example:
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
exclude 'META-INF/*.RSA'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
}
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'
}
}
Adding
exclude 'META-INF/*.RSA'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
Fixed my issue.

Building executable jar with Gradle and NetBeans

I have searching to solve this problem for two days and I did not find solution. Firstly I wanted to build fat-jar, then I gave up on that it looked more complicated so I started building normal executable jar. I am building some program inside NetBeans 8.2 with Gradle plugin(http://plugins.netbeans.org/plugin/44510/gradle-support)
My project structure is like this:
Project Structure
I am relatively new to Gradle I am using it less then one month. My build.gradle looks like this:
repositories {
mavenCentral()
}
dependencies {
// TODO: Add dependencies here ..
// // http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
// testCompile group: 'junit', name: 'junit', version: '4.10'
// https://mvnrepository.com/artifact/org.apache.poi/poi
compile group: 'org.apache.poi', name: 'poi', version: '3.16'
// https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml
compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.16'
// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.6'
}
apply plugin: 'java'
mainClassName = "paket.Glavna"
jar {
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes("Main-Class": "Glavna" )
}
}
Now, I cant get it working to make executable jar. I think i have traced problem that there isnt path to main class in jar but I dont know why it isnt adding it. Error i get is:
Error: Could not find or load main class DnevniIzvestajG-1.0.jar
jar runs with (inside Glavna class is main):
java -cp projectname.jar paket.Glavna
Also I have tried running
manifest-addition
but taht also didnt add link to main class.
Try adding a package to the class with main() method.
jar {
archiveName = 'Glavna.jar'
manifest {attributes 'Main-Class': 'paket.Glavna'}
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {}
}
Building a fat jar like this is not preferable, try the Application plugin
I use below way to add all dependencies in .jar of gradle project.
build.gradle :-
jar {
manifest {
attributes(
'Main-Class': 'com.main.MainClass'
)
}
duplicatesStrategy = DuplicatesStrategy.INCLUDE
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}

Successful Gradle project build produces NoClassDefFoundError at runtime

I am using Gradle to build my Java project in Eclipse. gradle.build is as follows
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.flowpowered', name: 'flow-nbt', version: '1.0.0'
compile group: 'org.reflections', name: 'reflections', version: '0.9.10'
}
All libraries are functioning properly when run through Eclipse. But sometimes it is useful to work on the command line. When run on the command line, the runtime error Exception in thread "main" java.lang.NoClassDefFoundError: com/flowpowered/nbt/regionfile/SimpleRegionFileReader occurs, even though the build is successful and the code contains imports from those libraries. I have tried cleans and rebuilds, along with gradlew build --refresh-dependencies, but I still encounter the same runtime error.
I would assume that the libraries are just never actually imported? Or that they are not being stored where the java project thinks they are? I'm unfamiliar with Gradle, so any advice on this is welcome.
Based on the posted build.gradle file you are not packaging the application as an executable JAR.
First apply the application plugin. But this will not be enough as you won't be able to run the executable as a single JAR without all of its dependencies. Apply the shadow plugin too.
These two plugins will give you access to the following tasks:
run: execute the application from gradle's command line.
runShadow: execute the application but with all dependencies packaged in a single JAR, alongside your compiled classes and resources.
shadowJar: create a single "fat JAR" with compiled classes and all dependencies.
Thus your build.gradle may look like this
plugins {
id 'java'
id 'application'
id 'com.github.johnrengelman.shadow' version '1.2.4'
}
mainClassName = 'com.acme.YourMainClassName'
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.flowpowered', name: 'flow-nbt', version: '1.0.0'
compile group: 'org.reflections', name: 'reflections', version: '0.9.10'
}
Plugin documentation:
https://github.com/johnrengelman/shadow
https://docs.gradle.org/3.4/userguide/application_plugin.html#useApplicationPlugin
Another solution without using any plugins and still end up with a runnable fat jar
jar {
archiveName = 'NameOfYourApp.jar'
manifest {
attributes 'Main-Class': 'uk.co.cdl.Main',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' '),
'Implementation-Version': project.version
}
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {
include/exclude anything if need to if not take the curlys off
}
}

Removing Jar Signatures in Gradle Build

We are having an issue with a war built from gradle failing to load in tomcat because of a Security Exception specific to a signed Jar. The stack trace is not showing what jar is causing the problem and to get this thing running I'm wondering if I can exclude the signatures in the build when the war is getting built but don't know how to do that with Gradle. In maven I believe it would be a <filter><exclude> tag but not sure if this type of thing is available in Gradle. Any input would be appreciated, the Exception being thrown is below.
Caused by: java.lang.SecurityException: Invalid signature file digest for
To find out if a jar file is signed, you can unzip the jar file using any zip utility tool. If the jar is signed it will contain files like *.RSA, *.SF or *.DSA under META-INF folder.
To exclude these signature files in gradle build , I did the following in my build.gradle. If you are using any other plugin to create the jar than you should check that plugins documentation for more details.
jar {
from { (configurations.runtime).collect { it.isDirectory() ? it : zipTree(it) } } {
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}
manifest {
attributes("Main-Class": "com.nk.social.shareit.streams.AppMain")
}}
My entire build.gradle file is as listed below:-
apply plugin: 'scala'
dependencies {
compile group: 'org.apache.kafka', name: 'kafka-streams', version: '0.11.0.1'
compile 'org.scala-lang:scala-library:2.12.2'
compile 'com.sksamuel.elastic4s:elastic4s-core_2.12:5.4.2'
compile 'com.sksamuel.elastic4s:elastic4s-http_2.12:5.4.2'
compile 'org.apache.lucene:lucene-core:6.5.1'
compile 'joda-time:joda-time:2.9.9'
testCompile group: 'org.scalatest', name: 'scalatest_2.12', version: '3.0.4'
}
jar {
from { (configurations.runtime).collect { it.isDirectory() ? it : zipTree(it) } } {
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}
manifest {
attributes("Main-Class": "com.nk.social.shareit.streams.AppMain")
}
}
Hope this helps.
With the jar, for example given in this thread I have a problem building a fat jar.
The main motivation is that the build process will skip also some dependecens.
A solution found is the following one, it contains only a small change
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'io.vincenzopalazzo.lightning.App'
)
}
from(configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }) {
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}
}

Categories