Kotlin Basics: Create Executable Kotlin JARs, using Gradle

  • Add a starting function
  • Configure your build to call this function when you execute your JAR.

Setting up Kotlin dependencies

apply plugin: 'java'
apply plugin: 'kotlin'

//… other stuff, you typically find in a Gradle build file

dependencies {
// other dependencies …
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

buildscript {
ext.kotlin_version = '1.0.2'
//...
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin/'
test.java.srcDirs += 'src/test/kotlin/'
}
grade clean build

Write your first Kotlin program

Unlike Java, Kotlin is friendlier with functions that reside outside of any class scope. You can create a Main class hosting a main() function, or you can create a top-level main() without necessarily wrapping it in a class. Perhaps, you wouldn’t be able to find any difference in a such a brief examaple, but I find the possibility to create top-level functions helpful in reducing boilerplate code.

fun main(args : Array<String>) { 
println("Hello, world!")
}

Configure your Gradle build to create an executable JAR

The main function we just added, is enough to test setting up an executable JAR, which one should then be able to call simply by executing:

java -jar <MY_PROJECT_NAME>.jar
no main manifest attribute <PATH_TO_MY_PROJECT_JAR>.jar
jar {
manifest {
attributes 'Main-Class': 'com.myname.myprojectname.Main'
}
}
jar {
manifest {
attributes 'Main-Class': 'com.myname.myprojectname.MainKt'
}
}
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at com.preslavrachev.imdbparser.MainKt.main(Main.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
jar {
manifest {
attributes 'Main-Class': 'com.preslavrachev.imdbparser.MainKt'
}

// This line of code recursively collects and copies all of a project's files
// and adds them to the JAR itself. One can extend this task, to skip certain
// files or particular types at will
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

Further Links

--

--

I am a genuinely curious individual on a mission to help digital creators and startups realize their vision. Follow my journey: https://preslav.me

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Preslav Rachev

Preslav Rachev

1.1K Followers

I am a genuinely curious individual on a mission to help digital creators and startups realize their vision. Follow my journey: https://preslav.me