42

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
    }
}
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • 3
    You may want to try using the [application plug-in](http://www.gradle.org/docs/current/userguide/application_plugin.html) instead. – Scott Feb 04 '14 at 21:15
  • 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. – Stefan Neuhaus Mar 15 '17 at 21:02

4 Answers4

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.

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
37

Have you tried the fatjar example in the gradle cookbook?

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

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • 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. – missingfaktor Jun 11 '12 at 20:02
  • 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? – oarsome Apr 07 '15 at 03:42
  • 1
    @tarzan three years later, and I'd now use the shadow plugin https://github.com/johnrengelman/shadow – tim_yates Apr 07 '15 at 06:03
  • this is very simple and worked the first time (after trying many other "answers": http://stackoverflow.com/questions/23738676/how-to-specify-main-class-when-using-fatjar-plugin-in-gradle-build – Hugo Zaragoza Apr 29 '15 at 21:56
  • Things change in 3 years. And I'd still use the shadow plugin ;-) – tim_yates Apr 29 '15 at 21:58
  • shadowjar isn't very well-maintained. See https://github.com/johnrengelman/shadow/issues/476 and other critical issues that have gone unfixed for months. – Gili Jun 27 '19 at 17:28
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.

Bao Le
  • 16,643
  • 9
  • 65
  • 68
  • but what is that code? What does configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } do? – Sam Redway Apr 21 '17 at 20:41
  • 1
    @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 folders – pal Jul 03 '17 at 17:10
  • I haven't tried the other versions posted here, but this one works nicely and is nice and simple. – chris Jul 18 '17 at 15:52
  • This answer excludes any `runtime` or `runtimeOnly` declared dependencies, which will cause the application to break at runtime. – mkobit Jul 31 '18 at 15:16
  • 1
    @mkobit You can replace `compile` with `runtimeClasspath` as specified in [this answer](https://stackoverflow.com/questions/49278063/how-do-i-create-an-executable-fat-jar-with-gradle-with-implementation-dependenci/49284432#49284432). – Franklin Yu Mar 01 '19 at 14:58
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'
    }
}
boechat107
  • 1,654
  • 14
  • 24