Building an uberjar with Gradle
Asked Answered
C

4

43

I want to build an uberjar (AKA fatjar) that includes all the transitive dependencies of the project. What lines do I need to add to build.gradle?

This is what I currently have:

task uberjar(type: Jar) {
    from files(sourceSets.main.output.classesDir)

    manifest {
        attributes 'Implementation-Title': 'Foobar',
                'Implementation-Version': version,
                'Built-By': System.getProperty('user.name'),
                'Built-Date': new Date(),
                'Built-JDK': System.getProperty('java.version'),
                'Main-Class': mainClassName
    }
}
Cocainism answered 11/6, 2012 at 19:22 Comment(2)
You may want to try using the application plug-in instead.Hardden
This will work as long as you do not have any dependencies. But once your project has dependencies those won't get bundled into the uberjar.Raynata
B
38

Have you tried the fatjar example in the gradle cookbook?

What you're looking for is the shadow plugin for gradle

Beg answered 11/6, 2012 at 19:29 Comment(6)
Thank you for the pointer. It helped. Though I hit another issue which was solved by a bit of googling. I'll add another answer expanding on that.Cocainism
It looks like the cookbook now requires a login. As this is exactly what I am looking for, could you paste the recipe in here please?Thematic
@tarzan three years later, and I'd now use the shadow plugin github.com/johnrengelman/shadowBeg
this is very simple and worked the first time (after trying many other "answers": #23739176Sylvie
Things change in 3 years. And I'd still use the shadow plugin ;-)Beg
shadowjar isn't very well-maintained. See github.com/johnrengelman/shadow/issues/476 and other critical issues that have gone unfixed for months.Equalizer
C
42

I replaced the task uberjar(.. with the following:

jar {
    from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {
        exclude "META-INF/*.SF"
        exclude "META-INF/*.DSA"
        exclude "META-INF/*.RSA"
    }

    manifest {
        attributes 'Implementation-Title': 'Foobar',
                'Implementation-Version': version,
                'Built-By': System.getProperty('user.name'),
                'Built-Date': new Date(),
                'Built-JDK': System.getProperty('java.version'),
                'Main-Class': mainClassName
    }
}

The exclusions are needed because in their absence you will hit this issue.

Cocainism answered 11/6, 2012 at 20:5 Comment(5)
I think it should use configurations.runtime to include all runtime dependenciesJaala
i needed to add with jar below manifest to get the files in java/main/resources in the uberjarStroud
That worked for me! Without the exclude part it was killing me with SecurityException and with this fix it works!Discrepancy
Best to even use the sourceSets.getByName('main').runtimeClasspathKentledge
anybody know what this would look like in kotlin (for the build.gradle,kts file) ?Aftershaft
B
38

Have you tried the fatjar example in the gradle cookbook?

What you're looking for is the shadow plugin for gradle

Beg answered 11/6, 2012 at 19:29 Comment(6)
Thank you for the pointer. It helped. Though I hit another issue which was solved by a bit of googling. I'll add another answer expanding on that.Cocainism
It looks like the cookbook now requires a login. As this is exactly what I am looking for, could you paste the recipe in here please?Thematic
@tarzan three years later, and I'd now use the shadow plugin github.com/johnrengelman/shadowBeg
this is very simple and worked the first time (after trying many other "answers": #23739176Sylvie
Things change in 3 years. And I'd still use the shadow plugin ;-)Beg
shadowjar isn't very well-maintained. See github.com/johnrengelman/shadow/issues/476 and other critical issues that have gone unfixed for months.Equalizer
I
8

Simply add this to your java module's build.gradle.

mainClassName = "my.main.Class"

jar {
  manifest { 
    attributes "Main-Class": "$mainClassName"
  }  

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

This will result in [module_name]/build/libs/[module_name].jar file.

Incompliant answered 26/11, 2016 at 4:45 Comment(5)
but what is that code? What does configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } do?Nievelt
@SamRedway configurations.compile.collect collects stuff from compile The ternary lets it pull in both folders and zip-files (like jars) as if they were also foldersYanirayank
I haven't tried the other versions posted here, but this one works nicely and is nice and simple.Pattani
This answer excludes any runtime or runtimeOnly declared dependencies, which will cause the application to break at runtime.Kentledge
@Kentledge You can replace compile with runtimeClasspath as specified in this answer.Permanent
V
5

I found this project very useful. Using it as a reference, my Gradle uberjar task would be

task uberjar(type: Jar, dependsOn: [':compileJava', ':processResources']) {
    from files(sourceSets.main.output.classesDir)
    from configurations.runtime.asFileTree.files.collect { zipTree(it) }

    manifest {
        attributes 'Main-Class': 'SomeClass'
    }
}
Ventilate answered 24/9, 2014 at 16:34 Comment(4)
i get Invalid signature file digest for Manifest main attributes when i try thisAbm
you need exclude "META-INF/*.SF" exclude "META-INF/*.DSA" exclude "META-INF/*.RSA" like missingfaktor's answerAbm
Does not seem to work with Gradle 5.3.1: "Could not get unknown property 'classesDir' for main classes of type org.gradle.api.internal.tasks.DefaultSourceSetOutput."Molal
it gives me java.lang.UnsupportedOperationExceptionCatacaustic

© 2022 - 2024 — McMap. All rights reserved.