javagradlejargradle-taskuberjar

Gradle fat jar does not contain libraries


I have created a simple Gradle Java project. The build.gradle file looks like this:

plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.0'
}

test {
    useJUnitPlatform()
}

task customFatJar(type: Jar) {
    archiveBaseName = 'fat-jar'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

I am creating the fat jar according to https://www.baeldung.com/gradle-fat-jar.

However, the resulting jar does not contain the commons-lang3 library. It only contains the project's class files.

Why isn't my library included in the fat jar?


Solution

  • The guide from Baeldung is outdated. I suggest following the guide in the official user guide instead: https://docs.gradle.org/current/userguide/building_java_projects.html#sec:java_packaging

    They are currently suggesting this:

    task uberJar(type: Jar) {
        archiveClassifier = 'uber'
    
        from sourceSets.main.output
    
        dependsOn configurations.runtimeClasspath
        from {
            configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
        }
    }
    

    You can customize the name like you already did, if you don't like using properties like archiveClassifier.

    If you are interested in why the Baeldung version doesn't work for you, it is because they collect dependencies from the deprecated configuration called compile. You are using the newer implementation instead, so compile is empty. However, instead of simply changing compile to implementation, it is recommended to use runtimeClasspath (like in the user guide) as this will correctly handle dependencies that are scoped to only the compile phase or as runtime only. While you don't have any of those now, you may in the future.