1

I'm tinkering with a simple "hello world" project in Kotlin & Gradle (see below). I've added the "fat jar" collection stuff to bring in the Kotlin dependency, but when I try to run java -jar build/libs/hello-1.0-SNAPSHOT.jar I get the java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics error because the dependencies aren't available at runtime.

I've solved that problem by changing implementation to compile, which makes everything work fine. But from what I understand, we shouldn't be using compile anymore, and neither api nor implementation makes the "fat jar" collection process work, and as I look at the other options for dependencies I'm not sure which to use.

Question: what's the "right" thing to do in a case like this?

// build.gradle
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.41'
}

group 'com.example.test'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    // if I change "implementation" to "compile", running the jar works
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}

jar {
    manifest {
        attributes "Main-Class": "ApplicationKt"
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}
// Application.kt
fun main(args: Array<String>) {
    println("hello world")
}
Hugh
  • 1,133
  • 1
  • 12
  • 27
  • https://stackoverflow.com/questions/44493378/whats-the-difference-between-implementation-and-compile-in-gradle – Doc Jul 27 '19 at 13:09
  • 2
    Keep `implementation`, but switch to `configurations.compileClasspath.collect` – JB Nizet Jul 27 '19 at 13:15
  • Thanks @JBNizet! Would you please submit this as an answer so I can accept it? – Hugh Jul 27 '19 at 13:40

1 Answers1

2

The compile dependency is deprecated. You should use implementation to declare your implementation dependencies, and compileClasspath to get all the compilation dependencies.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255