Main Tutorials

Gradle – Create a Jar file with dependencies

In this tutorial, we will show you how to use Gradle build tool to create a single Jar file with dependencies.

Tools used :

  1. Gradle 2.0
  2. JDK 1.7
  3. Logback 1.1.2

1. Project Directory

Create following project folder structure :

gradle-hello-folder

By default, Gradle is using the standard Maven project structure.

  1. ${Project}/src/main/java/
  2. ${Project}/src/main/resources/
  3. ${Project}/src/test/java/

2. Java Files

A single Java file to print out the current date time, and logs the message with logback.

DateUtils.java

package com.mkyong;

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DateUtils{
	
	private static final Logger logger = LoggerFactory.getLogger(DateUtils.class);
	
	public static void main(String[] args) {
		
		logger.debug("[MAIN] Current Date : {}", getCurrentDate());
		System.out.println(getCurrentDate());
	}
	
	private static Date getCurrentDate(){
		return new Date();
	}
	
}
logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
	  <layout class="ch.qos.logback.classic.PatternLayout">

		<Pattern>
			%-5level %logger{36} - %msg%n
		</Pattern>

	  </layout>
	</appender>

	<root level="debug">
	  <appender-ref ref="STDOUT" />
	</root>

</configuration>

3. build.gradle

A build.gradle sample to create a Jar file along with its logback dependencies.

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'

version = '1.0'
sourceCompatibility = 1.7
targetCompatibility = 1.7

//create a single Jar with all dependencies
task fatJar(type: Jar) {
	manifest {
        attributes 'Implementation-Title': 'Gradle Jar File Example',  
        	'Implementation-Version': version,
        	'Main-Class': 'com.mkyong.DateUtils'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

//Get dependencies from Maven central repository
repositories {
    mavenCentral()
}

//Project dependencies
dependencies {
	compile 'ch.qos.logback:logback-classic:1.1.2'
}

4. Create a Jar File

Clean the project.


$ gradle clean 

Run the Gradle fatJar task.


$ gradle fatJar 

:compileJava
:processResources
:classes
:fatJar

BUILD SUCCESSFUL

Total time: 6.4 secs

The Jar is created under the $project/build/libs/ folder.

gradle-build-folder

5. Run It

Run it – java -jar hello-all-1.0.jar.


$Project\build\libs> java -jar hello-all-1.0.jar
16:22:13,249 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
16:22:13,249 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
//...

DEBUG com.mkyong.DateUtils - [MAIN] Current Date : Wed Aug 27 16:22:13 SGT 2014
Wed Aug 27 16:22:13 SGT 2014

Done.

Download Source Code

Download It – gradle-create-single-jar.zip (1.4 KB)

References

  1. Gradle : Jar Task
  2. Wikipedia : Gradle

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
31 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Pritesh Mhatre
3 years ago

Compile configuration is deprecated for long now, kindly update:

from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }

???
7 years ago

It’s really useful for me, thanks

najeeb
4 years ago
Reply to  ???

do you have an example for that

Dirk Hoffmann
4 years ago

For me this did work better:


jar {
manifest {
attributes "Main-Class": application.mainClassName
}

from {
// filters only existing and non-empty dirs
sourceSets.main.runtimeClasspath
.filter { (it.isDirectory() && it.listFiles().length > 0) || it.isFile() }
.collect { it.isDirectory() ? it : zipTree(it) }

}
}

Caspar
9 years ago

Doesn’t work. I get “no main manifest attribute, in gradle-create-single-jar-all-1.0.jar” with the uploaded example.

Ruslan Ibragimov
9 years ago

I think this is much better:http://www.gradle.org/docs/current/userguide/application_plugin.html
just add this lines to build.gradle:

apply plugin: ‘application’
mainClassName = “com.mkyong.DateUtils”

and then run gradle task:

$ gradle distZip

It’s better, because:
1. This is plugin and your build.gradle much cleaner.
2. This distribute only runtime deps, not compile and test.
3. This will be maintained by plugin contributers.

Jason Zwolak
7 years ago

Yes, but it isn’t a jar. I know a jar file is just a zip file… but the distZip task creates a zip file without a manifest and other jar related things. So, it’s not the same.

Kim Laplume
9 years ago

This! So much cleaner!
Thank you for the tip

Guest
5 years ago

After hours of google searching, you were the saving grace! Thank you so much

Guason
5 years ago

I use the shadowjar!!!

shadowJar {
configurations = [project.configurations.compile]
classifier = null
baseName = ‘MyNewJARFileName’
version = null
}

Leo
5 years ago

Is there a way to store all the dependencies in one folder in jar, e.g. /libs ?

Daniel Weibel
5 years ago
Reply to  Leo
Matt
6 years ago

java.lang.StackOverflowError (no error message)

Luisito
11 months ago

You only need the application plugin and setting up the path build

jar {
from {
configurations.runtimeClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
}
}

Luisito
11 months ago
Reply to  Luisito

This is also a problem from gradle itself to not making a native way (or some plugin or tasks) to handle this.

Thread: https://discuss.gradle.org/t/include-transitive-dependencies-in-jar/38926

Rachid Laborantin
1 year ago

Thanks guys, it solved my problems. You saved my nightmare

Suryajit
1 year ago

Hi mkyong, I’m working on a Test Project which has code under “main” folder and tests under “test” folder. I need to create a single executable jar which contains code from both main and test folders including the necessary dependencies.

The have posted the question on Stackoverflow too with my build.gradle file
StackoverFlow_Link

trisha
2 years ago

i kept getting this error when i run the jar file. do you know how to solve it?

Error: Could not find or load main class

task subscribe_jar(type: Jar) {

   baseName = 'mqttSubscriber'

   sourceSets.main.java.srcDirs = ['src']
    manifest {
        attributes 'Main-Class': 'mqtt.subscribe.MqttSubscriber'
//        attributes 'Class-Path': '. ' + configurations.runtime.collect{it.name}.join(' ')
    }

//    from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
   with jar

}
Peter Chew
1 year ago
Reply to  trisha

Hi Trisia, I have the same ‘Error: Could not find or load main class’ issue when running the compiled jar file. wonder if u have managed to solve it?

Tihamer
2 years ago

Thanks for all your hard work! I’ve been learning from you for years!
In this particular case, your solution for getting fat jars worked great for me.
I was wondering, though (as someone commented on this problem below), how would we make the fatJar task automagically happen as part of the build (or right afterwards).
Yes, I know that it is easy enough to do:
gradle clean build fatJar -info
but I would like to save myself the six characters (plus the bigger task of remembering).
Thanks!

Venkatesh
3 years ago

I get class not found error if my main class is in test folder, works fine if main class is in src/main/java. Any suggestions.

Bidehalaxmi Panda
3 years ago

Thank you so much for this.

CHRIS FOUTS
4 years ago

What if you have a LOT of dependencies, but only what to include certain ones, and NOT all of them? I’ve seen examples where that show including one of many dependencies, but not several of many (but not all) dependencies.

thomas
4 years ago

Thanks for the solution. Really helpful.

Adam M. Erickson
4 years ago

You always give just enough to force us to use our heads to figure out the rest. Thank you!

For people that are adding signed third part jars. Make sure to add this exclude line in the gradle.build file!

exclude ‘META-INF/*.RSA’, ‘META-INF/*.SF’,’META-INF/*.DSA’

`Works perfectly. Thank you Mkyong

https://stackoverflow.com/questions/37848553/error-in-executing-the-generated-jar-file/37848829

J J
4 years ago

For me at first it didn’t work. I spent ages trying to figure out why it wasn’t working and eventually I realised I was supposed to do “gradle fatJar” not “gradle build” – it does say it in the tutorial but perhaps like many others I am often in too much of a hurry for my own good. Thanks.

Guason
5 years ago

group ‘br.com.teste.teste’
version ‘1.0’

apply plugin: ‘java’
apply plugin: ‘application’

mainClassName = “br.com.teste.Main”

sourceCompatibility = 1.8
targetCompatibility = 1.8

apply plugin: ‘com.github.johnrengelman.shadow’

shadowJar {
configurations = [project.configurations.compile]
classifier = null
baseName = ‘MyTesteJARFilenameHere’
version = null
}

buildscript {
repositories {
jcenter()
}
dependencies {
classpath ‘com.github.jengelman.gradle.plugins:shadow:2.0.2’
}
}

repositories {
mavenCentral()
}

task execute(type: JavaExec) {

main = “br.com.teste.Main”
classpath = sourceSets.main.runtimeClasspath

systemProperties System.getProperties()

args System.getProperty(“exec.args”, “”).split()
}

sourceSets {
main {
java {
srcDirs = [‘src/main/java’]
}
resources {
srcDirs = [‘src/main/resources’]
}
}
test {
java {
srcDirs = [‘src/test/java’]
}
resources {
srcDirs = [‘src/test/resources’]
}
}
}

dependencies {
testCompile group: ‘junit’, name: ‘junit’, version: ‘4.12’
}

Toni
6 years ago

Great Job!

Jason Zwolak
7 years ago

mkyong, your example only works in some cases. I used it on my project with a dependency on javaee and jersey and I ended up with a jar with multiple entries with the same name… and Java doesn’t like it when running in a webstart application. But thanks anyway, I’ve gotten a ton of useful information from you blog in the past!!! When I see it in a Google search I think “ah, that’s good, I trust this guy” 😉

Java Developer
9 years ago

Thanks for the short tutorial. This seems to be way to complicated as compared to maven. Since we just need to use a assembly or onejar plugin.

Tihamer
2 years ago
Reply to  Java Developer

You are correct. Gradle is considerably more complicated than Maven, and therefore has a steeper learning curve (which I am still climbing).
OTOH, Gradle allows you to drop into Java and do custom things easier than in Maven.