2

So I'm translating example code of how to create a fat jar with Gradle from GroovyDSL to KotlinDSL (I'm using Gradle 5.3.1). I got the GroovyDSL code here:

jar {
    manifest {
        attributes "Main-Class": "com.baeldung.fatjar.Application"
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

This is how far I've come: UPDATE: (latest version with feedback from JB Nizet)

jar {
    manifest {
        attributes("Main-Class" to "io.ktor.server.netty.EngineMain")
    }
    val compileConfig: Configuration = configurations.compile.get()
    from {
        compileConfig.
    }
}

The problem is that there isn't a collect-method on compileConfig which is a Configuration

The invocation of "from" is also a mystery to me. I'm fairly certain that the method originates in AbstractCopyTask. There are three versions of it: one takes a Object... sourcePaths while the other two have two parameters Object sourcepath and a Closure/Action but the Groovy version invokes it with only a single closure! My best guess is that the closure is automatically evaluated and the result coerced into an Object... invoking the first version of the method.

UPDATE: (latest version with feedback from JB Nizet)

If you want to test your ideas on how to solve this, here you can find this jar-task-configuration on a HelloWorld-Ktor project.

jar {
    manifest {
        attributes("Main-Class" to "io.ktor.server.netty.EngineMain")
    }
    from({
        val compileConfig = configurations.compile.get()
        logger.info("#files to iterate over: ${compileConfig.count()}")
        compileConfig.map { file -> 
            if (file.isDirectory) file else zipTree(file)
        }
    })
}

This compiles but doesn't produce a fat jar (via "gradle clean build"). If one looks at the output with info (via gradle clean build -x test --info), one finds the answer: no files are actually processed!

> Task :jar
#files to iterate over: 0
#files to iterate over: 0
Task ':jar' is not up-to-date because:
  Output property 'archiveFile' file /Users/SSchrod/progs/data-integration-salesforce-auto-cancellationkt/build/libs/data-integration-salesforce-auto-cancellation-0.1.51-SNAPSHOT.jar has been removed.
#files to iterate over: 0
:jar (Thread[Execution worker for ':',5,main]) completed. Took 0.068 secs.
:assemble (Thread[Execution worker for ':',5,main]) started.

With the code seemingly correctly translated to Kotlin, maybe the rest of my build-script is the problem? The original tutorial contained a call to the java-plugin in its build.gradle

apply plugin: 'java'

repositories {
    mavenCentral()
}

, which isn't present in my build.gradle.kts:

plugins {
    id("org.jetbrains.kotlin.jvm") version "1.3.20"
    id("pl.allegro.tech.build.axion-release") version "1.9.4"
    id("com.palantir.docker") version "0.21.0"
    id("com.github.johnrengelman.shadow") version "5.0.0"
}

repositories {
    mavenCentral()
    jcenter()
}

but adding it didn't seem to make a difference.

StephanS
  • 843
  • 1
  • 8
  • 20
  • Groovy collect() == Kotlin map(). `compileConfig.map { if (it.isDirectory()) it else zipTree(it) }` – JB Nizet Apr 08 '19 at 16:27
  • What you pass to from in your groovy example is a closure. See https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#files-java.lang.Object...-: the argument can be a closure. – JB Nizet Apr 08 '19 at 16:33
  • @JBNizet good spot with the collect->map! I didn't notice it because it doesn't show up in the JavaDoc. (The reason - of course - being that map is an extension function on Iterable and not part of the original Interface). To bad that the project still isn't producing a fat jar though :'( – StephanS Apr 09 '19 at 10:44
  • See My answer in another post: https://stackoverflow.com/a/69508845/3792198 This question is duplicated. – Thiago Oct 09 '21 at 16:57

1 Answers1

3

So I got a solution with the shadowJar plugin now:

plugins {
    kotlin("jvm") version "1.3.21"
    application
    id("com.github.johnrengelman.shadow") version "5.0.0"
}

application {
    mainClassName = "uk.co.which.stephan.server.ServerKt"
}

// repositories/dependencies/etc

tasks {
    withType<KotlinCompile> {
        kotlinOptions.jvmTarget = "1.8"
    }

    shadowJar {
        // defaults to project.name
        //archiveBaseName.set("${project.name}-fat")

        // defaults to all, so removing this overrides the normal, non-fat jar
        archiveClassifier.set("")
    }
}

the complete solution is available in the gradle.build.kts file of the solution/shadowJar branch of my HelloWorld-Ktor project.

StephanS
  • 843
  • 1
  • 8
  • 20