15 November 2019, Kevin Watzal

Have you ever written an useful web application and wondered how you could deploy it very cheap? Heroku lets you deploy and manage your application and supports a wide variety of languages, frameworks and also features databases or scalability.

When you only want to host a small application, it even is free of charge for you.

Let’s be honest, there are already a lot of blog posts about Heroku and how to deploy Java or Kotlin apps, but all include Spring Boot, which is not really bad, but in my opinion, too much overhead if you only have a small application.

So let me introduce Ktor (and Kotlin if you don’t know it yet).

Ktor is an asynchronous web framework for Kotlin, which offers everything you would expect from a web-framework, but it is also easy to understand, learn and use. In other words: less code for much value.

Ktor

Let’s start with an Ktor app, which I uploaded to Github, if you wish to skip the next steps or to get the big picutre.

We start with the basic build.gradle file for Kotlin:

build.gradle
buildscript {
    ext {
        kotlin_version = '1.3.50'
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: "kotlin"

To use Ktor just add the dependency in the build.gradle file:

build.gradle
repositories {
    mavenCentral()
}

ext {
    ktor_version = "1.2.4"
}

dependencies {
    compile "io.ktor:ktor-server-netty:$ktor_version"
}

Now we can start with the code.

The most simple Ktor application looks like:

Server.kt
fun main() {
    embeddedServer(Netty, 8080) {
        routing {
            get("/") {
                call.respondText("Hello :)")
            }
        }
    }.start(wait = true)
}

We could already jump to the deployment part, but that would be a little bit too little, I guess, so I will show you just a bit more. I often work with REST APIs, so I will simply add two more endpoints. In the scenario that we want to serve blog posts. One endpoint will to show all available posts and one endpoint is for browsing to one specific post.

For this I created a small class called Post:

Post.kt
data class Post(val id: String, val title: String, val author: String)

Let us also have a small function which returns all posts:

Server.kt
fun initPosts() = listOf(
    Post("immutable-collections", "Immutable Collections In Java – Not Now, Not Ever", "nipa"),
    Post("guide-to-java12", "Definitive Guide To Java 12", "nipa"),
    Post("rest-vs-websockets", "REST vs WebSockets", "Kumar Chandrakant")
)

I mentioned REST already, which in most cases implies JSON. So the REST endpoint which returns all those posts, should convert those to JSON as well. Luckily the Jackson project already does that, so it only needs to be applied.

So the dependency will be added in gradle:

build.gradle
dependencies {
    compile "io.ktor:ktor-server-netty:$ktor_version"
    compile "io.ktor:ktor-jackson:$ktor_version"
}

And then we tell the server to use it:

Server.kt
embeddedServer(Netty, 8080) {
    install(ContentNegotiation) {
        jackson {
            enable(SerializationFeature.INDENT_OUTPUT)
        }
    }
    routing {
        get("/") {
            call.respondText("Hello :)")
        }
    }
}.start(wait = true)

Now we can simply add the new endpoint:

Server.kt
embeddedServer(Netty, port.toInt()) {
    install(ContentNegotiation) {
        jackson {
            enable(SerializationFeature.INDENT_OUTPUT)
        }
    }
    routing {
        get("/") {
            call.respondText("Hello :)")
        }
        get("/posts") {
            call.respond(initPosts())
        }
    }
}.start(wait = true)

Violà, all posts are now returned in a JsonArray. Now add the last endpoint to only navigate to one post. Since software developers often want to reduce redundancy, I will create a subroute to /posts:

First move the get call:

Server.kt
route("/posts") {
    get {
        call.respond(initPosts())
    }
}

Then add the new endpoint:

Server.kt
route("/posts") {
    get {
        call.respond(initPosts())
    }
    route("/{id}") {
        get {
            val result = initPosts().filter { it.id == call.parameters["id"] }.getOrNull(0)
            result?.let { call.respond(it) } ?: call.respond(HttpStatusCode.NotFound)
        }
    }
}

In line 7 we search for the string the user entered in the list and in line 8 we return either the post if there was one, or a HTTP 404 otherwise.

Okay, now I have shown you a (very) little bit of Ktor (and Kotlin). The next essential part is to let others use the API.

Heroku

Following this excellent guide by the Heroku Developer Site, we will set up a heroku application and make everything ready to deploy the app there.

First of all, you need to create an account.

Depending on your operating system, you need to install heroku locally to use it from the CLI. I am using Ubuntu, for others please follow the instructions here.

sudo snap install heroku --classic

So, now you should easily login from the CLI which is used to authenticate yourself to Heroku and Git(why will be explained later).

heroku login

Move to your project directory, because the next command will create your git repository on heroku and add the remote url to your local project. When you push to the repository, it will automatically deploy and publish it, at least it will try.

heroku create -b heroku/gradle <APP name>

What you see then is the subdomain (and name) of your app:

Creating app... done, ⬢ hidden-temple-15245

Before you push to heroku, you should make the jar file runnable by adding some more gradle lines:

build.gradle
jar {
    manifest {
        attributes 'Main-Class': 'your.package.ServerKt'
    }

    from {
        (configurations.compile).collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
}

After that we just need to add a Procfile containing the command which needs to be executed to start your program:

Procfile
web: java -jar build/libs/SimpleWebServer.jar

Merge

It’s showtime, let’s publish our thing.

There is a gradle plugin which really helps to deploy the application. Just add the plugin and you should be good to go:

build.gradle
plugins {
  id "com.heroku.sdk.heroku-gradle" version "1.2.4"
}

Then you can push everything to heroku with:

git push heroku

You will see some output and phases your app will go through, but you should see

remote: -----> Launching...
remote:        Released v4
remote:        https://hidden-temple-15245.herokuapp.com/ deployed to Heroku

at the end.

Let’s test

Browsing to https://hidden-temple-15245.herokuapp.com/ will return our defined greeting!

Hello :)

And the posts endpoint?

[
  {
    "id": "immutable-collections",
    "title": "Immutable Collections In Java – Not Now, Not Ever",
    "author": "nipa"
  },
  {
    "id": "guide-to-java12",
    "title": "Definitive Guide To Java 12",
    "author": "nipa"
  },
  {
    "id": "rest-vs-websockets",
    "title": "REST vs WebSockets",
    "author": "Kumar Chandrakant"
  }
]

And it also comes with https and a valid certificate!

Building a web server with Ktor is very fast and does not require much code. Deploying that web server with heroku is also very simple and fast. If you have a hobby project where you quickly want to try things out or to show what your skills, I think either one of these technologies can help you a lot.

Kotlin
Heroku