Create Executable Kotlin JARs, using Gradle
Tags: kotlin, gradle, java, jar
Published: 2017-01-07 21:57:11

---
title: Create Executable Kotlin JARs, using Gradle
published: true
description: Kotlin is great for creating small command-line utilities, which can be packaged and distributed as normal JAR files.
cover_image: 
tags: kotlin, gradle, java, jar
---

_This article was originally posted in [my blog](http://www.preslav.me/2016/06/13/kotlin-basics-create-an-executable-kotlin-jar-using-gradle/)_

Kotlin is great for creating small command-line utilities, which can be packaged and distributed as normal JAR files. This short tutorial will show you how to:

- Set up a Gradle project that supports Kotlin
- Add a starting function
- Configure your build to call this function when you execute your JAR.

### Setting up Kotlin dependencies

```groovy
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"
}
```

You will also want your IDE (I assume you're using IntelliJ or Android Studio) to mark the directory where your Kotlin source code resides as a source directory. Since Kotlin and Java are best friends, it is perfectly fine to keep the same package structure. It is a good practice, though to keep your Kotlin code physically separate from your Java one. Thus, you'd typically have two folders under `src` - `src/main/java` for Java classes, and `src/main/kotlin` for Kotlin ones. Same for tests. Again, in your `build.gradle` file, add the following:

```groovy
sourceSets {
    main.java.srcDirs += 'src/main/kotlin/'
    test.java.srcDirs += 'src/test/kotlin/'
}
```

Using IntelliJ, you could rely not he IDE to guide you with all of this, but I wanted to show you the basics, since one may not always rely on the comfort of an IDE. To see that everything is working as it should, go to your project directory and create a new build:

```bash
grade clean build
```

If everything has been set up correctly, you should be able to see a task named `compileKotlin` which the build has executed successfully.

### 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. 

Here is the mandatory HelloWorld example. Create a file with an arbitrary name (say `Main`) and an extension `.kt`, and write simply:

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

Note that adding a package is optional, as well as ending your lines with semicolons. In order to keep consistency with my Java code though, I'd usually add both, and expect that people I work with, do the same.

### 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:

```bash
java -jar <MY_PROJECT_NAME>.jar
```

If you simply try to build your project and then execute the above command, we would get the following message:

```bash
no main manifest attribute <PATH_TO_MY_PROJECT_JAR>.jar
```

This means that we have to configure `jar` task, which Java Gradle builds go through, and tell it which the starting point of our project is. In a Java project, this would be the path to the class where our `main()` function resides:

```groovy
jar {
    manifest {
        attributes 'Main-Class': 'com.myname.myprojectname.Main'
    }
}
```

Wait a minute? We have defined our `main()` function outisde of any class scope. That's true and not entirely true at the same time. Actually, to keep things at the bytecode level consistent, and backwards-compatible with the JVM, the Kotlin compiler adds all top-level functions to respective classes. In our case, the class generated by the Kotlin compiler would have the same name the filename of the file where our function resides, plus the suffix `Kt`. This means, for example, that if our file is called `Main.kt`, the Kotlin compiler would generate a class with the name `MainKt.class` and add it to the generated JAR file. Knowing this, one could rewrite the Gradle configuration above, as follows:

```groovy
jar {
    manifest {
        attributes 'Main-Class': 'com.myname.myprojectname.MainKt'
    }
}
```

**Note:** You can specifiy the name this class should be compiled with, by adding a file-scope annotation on top of your file, even before the `package` declaration:

```kotlin
@file:JvmName("MainCls")
```

This new name can be used within the JAR manifest configuration, as shown above.

Even though we specified our main class correctly in our JAR manifest configuration, if we try to execute our main function using `jar -jar`, we will still see an error message:

```bash
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
```

Experienced Java developers will quickly recognize this type of exception. By default when Gradle (as well as Maven) packs some Java class files into a JAR file, it is assumed that this JAR file will be referenced by an application, where all of its dependencies are also accessible within the classpath of the loading application. To execute a JAR without having to specifiy the path to itse dependencies, one must tell the build system to take all of this JAR's referenced dependencies and copy them as part of the JAR itself. In the Java community, this is known as a "fat JAR". In a "fat JAR" all of the dependencies end up within the class path of the loading application, so code can be executed without problems. The only downside to creating fat JARs is of course their growing file size (which kind of explains the name), though in most situations, it is not a big concern. In order to tell Gradle to copy all of a JAR's dependencies, one should simply modify the abovementioned JAR task configuration, by adding the following piece of code: 

```groovy
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
- [Gradle – Create a Jar file with dependencies](http://www.mkyong.com/gradle/gradle-create-a-jar-file-with-dependencies/)
- [Creating runnable JAR with Gradle |Â StackOverflow](http://stackoverflow.com/questions/21721119/creating-runnable-jar-with-gradle)