Building a native ktor application with GraalVM
Tags: kotlin, webdev
Published: 2019-04-11 00:10:26

---
title: Building a native ktor application with GraalVM
published: true
description: How to build a native web app using ktor and GraalVM     
tags: kotlin, webdev
---

The source code for this post can be found on this [github repo](https://github.com/viniciusccarvalho/ktor-native)

# Introduction



On my last post: [Building a native cli with kotlin and graalvm](https://dev.to/viniciusccarvalho/building-a-native-cli-with-kotlin-and-graalvm-55ee), I've demonstrated how to build native cli application using graalvm. On this post we will build a web application using [ktor.io](https://ktor.io) and the [GraalVM](https://graalvm.org).

# Requirements

* [GraalVM](https://graalvm.org) installed and $GRAALVM_BIN pointing to the binary folder of your install

# Building it

Ktor supports several server options (Netty, Jetty, CIO). Netty is my favorite option for java applications, but it can be quite painful trying to get netty to work with GraalVM as explained [here](https://medium.com/graalvm/instant-netty-startup-using-graalvm-native-image-generation-ed6f14ff7692)

So I tried the CIO server (leverages only kotlin code, and coroutines). I then found out that GraalVM does not support the bytecode generated by coroutines.

Fortunately after some googling I bumped into [kraal](https://github.com/HewlettPackard/kraal) which seems to solve the problem.


The example will use the Gradle Kotlin DSL, just create a new Gradle project on intellij and mark "use Kotlin DSL"

From there modify your build.gradle.kts to look like this:

```kotlin
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.3.21"
    id("com.hpe.kraal") version "0.0.15" // kraal version - for makeRelease.sh
}

group = "io.igx.kotlin"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    implementation(kotlin("stdlib-jdk8"))
    implementation("org.slf4j:slf4j-simple:1.7.26")
    implementation("io.ktor:ktor-server-cio:1.1.3")
    implementation("io.ktor:ktor-gson:1.1.3")
}

tasks.withType<KotlinCompile>().configureEach {
    kotlinOptions {
        jvmTarget = "1.8"
        // need use-experimental for Ktor CIO
        freeCompilerArgs += listOf("-Xuse-experimental=kotlin.Experimental", "-progressive")
        // disable -Werror with: ./gradlew -PwarningsAsErrors=false
        allWarningsAsErrors = project.findProperty("warningsAsErrors") != "false"
    }
}


val fatjar by tasks.creating(Jar::class) {

    from(kraal.outputZipTrees) {
        exclude("META-INF/*.SF")
        exclude("META-INF/*.DSA")
        exclude("META-INF/*.RSA")
    }

    manifest {
        attributes("Main-Class" to "io.igx.kotlin.ApplicationKt")
    }

    destinationDirectory.set(project.buildDir.resolve("fatjar"))
    archiveFileName.set("ktor-native.jar")
}

tasks.named("assemble").configure {
    dependsOn(fatjar)
}

```

As usual, just edit the group/Main-Class to match your own packaging structure.

Let's make sure our app outputs some JSON based on a domain class:

```kotlin
data class Driver(val id: Int, val firstName: String, val lastName: String, val nationality: String)

```

Your `Application` should look like this one:

```kotlin
fun main(args: Array<String>) {
    val server = embeddedServer(CIO, 8080, module = Application::module)
    server.start(wait = true)
}

fun Application.module() {
    install(CallLogging)
    install(ContentNegotiation) {
        gson {
            setPrettyPrinting()
        }
    }
    routing {
       get("/drivers"){
           call.respond(Driver(102, "Ayrton", "Senna", "Brazilian"))
       }
    }
}

```

#Testing

run `./gradlew clean build` and then `java -jar build/fatjar/ktor-native.jar` and your app should be app and running:

```
[DefaultDispatcher-worker-1] INFO ktor.application - No ktor.deployment.watch patterns specified, automatic reload is not active
[DefaultDispatcher-worker-1] INFO ktor.application - Responding at http://0.0.0.0:8080
```

Hit `http://0.0.0.0:8080/drivers`

```json
{
"id": 102,
"firstName": "Ayrton",
"lastName": "Senna",
"nationality": "Brazilian"
}
```

# Native image

As with our previous post, run the `native-image` command:

```
$GRAALVM_BIN/native-image  --report-unsupported-elements-at-runtime --jar build/fatjar/ktor-native.jar ktor-native --enable-url-protocols=http --no-server
```

run `./ktor-native`, hit `http://0.0.0.0:8080/drivers` and you will get:

```json
{}
```

![Say Whaaat?](http://api.ning.com/files/iHTeMy8PBD0esxtcJ8dNEjiNZqKEUP-vf9pg5*vyP1JWZ-RmSMcNDTkQ7-rHCvbYbM8AGTY1-iQAarBw3mSrddaandhna1-x/saywhatanchorman.jpg)

# Reflection issues

So, GraalVM needs a little help handling reflection as explained [here](https://github.com/oracle/graal/blob/master/substratevm/REFLECTION.md).

Add the following file to the root of your project (reflection.json)

```json

[
   {
    "name" : "io.igx.kotlin.model.Driver",
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true,
    "allDeclaredMethods" : true,
    "allPublicMethods" : true,
     "fields" : [
       { "name" : "id" },
       { "name" : "firstName" },
       { "name" : "lastName" },
       { "name" : "nationality" }
     ]
   },

  {
  "name" : "java.lang.Integer",
  "methods" : [{ "name" : "parseInt", "parameterTypes" : ["java.lang.String"]}]
}, {
  "name" : "java.lang.Long",
  "methods" : [{ "name" : "parseLong", "parameterTypes" : ["java.lang.String"]}]
}, {
  "name" : "java.lang.Boolean",
  "methods" : [{ "name" : "parseBoolean", "parameterTypes" : ["java.lang.String"]}]
}, {
  "name" : "java.lang.Byte",
  "methods" : [{ "name" : "parseByte", "parameterTypes" : ["java.lang.String"]}]
}, {
  "name" : "java.lang.Short",
  "methods" : [{ "name" : "parseShort", "parameterTypes" : ["java.lang.String"]}]
}, {
  "name" : "java.lang.Float",
  "methods" : [{ "name" : "parseFloat", "parameterTypes" : ["java.lang.String"]}]
}, {
  "name" : "java.lang.Double",
  "methods" : [{ "name" : "parseDouble", "parameterTypes" : ["java.lang.String"]}]
}
]

```

Run the `native-image` command again, but this time add the **-H:ReflectionConfigurationFilesflag**

```
~/java/graalvm-ce-1.0.0-rc13/Contents/Home/bin/native-image  --report-unsupported-elements-at-runtime -H:ReflectionConfigurationFiles=reflection.json  -jar build/fatjar/example.jar ktor-native --enable-url-protocols=http --no-server
```

Try it again and you will see the original results of your Driver JSON payload.

#Final Thoughts

Dealing with reflection on GraalVM can be a bit challenging, luckily to us, several people on the industry like the folks at RedHat are trying to come up with frameworks such as [quarkus.io](https://quarkus.io) to overcome this limitation.

I have no doubt that IDEs will soon catch up and be able to inspect the code and generate those reflection files for us.

Meanwhile enjoy your blazing fast ktor server running as a native image on your server.

Happy Coding!