Using Gradle to build a jar with dependencies
I posted a solution in JIRA against Gradle:
// Include dependent libraries in archive.
mainClassName = "com.company.application.Main"
jar {
manifest {
attributes "Main-Class": "$mainClassName"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Note that mainClassName
must appear BEFORE jar {
.
The answer by @felix almost brought me there. I had two issues:
- With Gradle 1.5, the manifest tag was not recognised inside the fatJar task, so the Main-Class attribute could not directly be set
- the jar had conflicting external META-INF files.
The following setup resolves this
jar {
manifest {
attributes(
'Main-Class': 'my.project.main',
)
}
}
task fatJar(type: Jar) {
manifest.from jar.manifest
classifier = 'all'
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
with jar
}
To add this to the standard assemble or build task, add:
artifacts {
archives fatJar
}
Edit: thanks to @mjaggard: in recent versions of Gradle, change configurations.runtime
to configurations.runtimeClasspath
If you want the jar
task to behave normally and also have an additional fatJar
task, use the following:
task fatJar(type: Jar) {
classifier = 'all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
The important part is with jar
. Without it, the classes of this project are not included.
This works fine for me.
My Main class:
package com.curso.online.gradle;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
public class Main {
public static void main(String[] args) {
Logger logger = Logger.getLogger(Main.class);
logger.debug("Starting demo");
String s = "Some Value";
if (!StringUtils.isEmpty(s)) {
System.out.println("Welcome ");
}
logger.debug("End of demo");
}
}
And it is the content of my file build.gradle:
apply plugin: 'java'
apply plugin: 'eclipse'
repositories {
mavenCentral()
}
dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
testCompile group: 'junit', name: 'junit', version: '4.+'
compile 'org.apache.commons:commons-lang3:3.0'
compile 'log4j:log4j:1.2.16'
}
task fatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.curso.online.gradle.Main'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
And I write the following in my console:
java -jar ProyectoEclipseTest-all.jar
And the output is great:
log4j:WARN No appenders could be found for logger (com.curso.online.gradle.Main)
.
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more in
fo.
Welcome
Since use of compile to list dependencies is now deprecated and all should switch to implementation the solution to build a Jar with all dependencies should use the example from this website.
https://docs.gradle.org/current/userguide/working_with_files.html#sec:creating_uber_jar_example
Specifically this command:
configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it)
Here is full gradle section: [1]: https://docs.gradle.org/current/userguide/working_with_files.html#sec:creating_uber_jar_example
task uberJar(type: Jar) {
archiveClassifier = 'uber'
from sourceSets.main.output
dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
}}