kotlingradleuberjarfatjar

Building a self-executable JAR with Gradle and Kotlin


I've written a simple Kotlin source file in order to get started, and a Gradle script file. But I can't figure out how to add the main function to the manifest, so that the JAR could be self-executable.

Here is my build.gradle script :

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.9.66'
    }
}
apply plugin: "kotlin"
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:0.9.66'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.loloof64.kotlin.exps.ExpsPackage'
    }
}

Here is my com.loloof64.kotlin.exps.Multideclarations.kt:

package com.loloof64.kotlin.exps

class Person(val firstName: String, val lastName: String) {
    fun component1(): String {
        return firstName
    }
    fun component2(): String {
        return lastName
    }
}

fun main(args: Array < String > ) {
    val(first, last) = Person("Laurent", "Bernabé")
    println("First name : $first - Last name : $last")
}

When I launch the JAR from terminal (java -jar MYJar.jar) I get the following stack trace, saying that the Kotlin reflection library classes are missing, and indeed they have not been added to the JAR. It seems that I am missing the kotlin-compiler artifact classes from the final JAR, and also the kotlin-stdlib sources, but I don't know how to adapt the Gradle build.

$> java -jar build/libs/kotlin_exps.jar 

Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/reflect/jvm/internal/InternalPackage
    at com.loloof64.kotlin.exps.ExpsPackage.<clinit>(MultiDeclarations.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.reflect.jvm.internal.InternalPackage
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

I am using Kotlin 0.9.66 and Gradle 2.1.


Solution

  • I've found the workaround (thanks to MkYong website)

    1. The gradle script needed the kotlin-compiler artifact as a dependency
    2. The gradle script needed a way to collect all kotlin files and put them into the jar.

    So i get with the following gradle script :

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
           classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.1-2'
        }
    }
    
    apply plugin: "kotlin"
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.1-2'
    }
    
    jar {
        manifest {
            attributes 'Main-Class': 'com.loloof64.kotlin.exps.MultideclarationsKT'
        }
    
        // NEW LINE HERE !!!
        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    }