Spring Boot and Kotlin, Implementation

I’ve mentioned I used Kotlin to implement a Spring Boot service, here are the bits and pieces needed to make this work.  To briefly recap, I had to quickly implemented a service as a proof of concept so went with Kotlin’s Spring Boot integration. It proved to be really easy and as I’ve continued work with the service I’ve been more and more happy the choice.

The Build Bits

I use gradle as the build tool, so lets start with whats needed there.

buildscript {
ext {
springBootVersion = spring_boot_version
kotlin_version = kotlin_version
}
repositories {
jcenter()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version",
"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version",
"org.jetbrains.kotlin:kotlin-allopen:$kotlin_version",
"org.jetbrains.kotlinx:kotlinx-gradle-serialization-plugin:$serialization_version"
}
}
apply plugin: 'kotlin'
apply plugin: "kotlin-spring"
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'kotlinx-serialization'
sourceCompatibility = jvm_version
version = '1.2.0'
compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = jvm_version
}
}
kotlin { experimental { coroutines 'enable' } }
compileTestKotlin {
kotlinOptions.jvmTarget = jvm_version
}
repositories {
jcenter()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8',
'org.jetbrains.kotlin:kotlin-reflect',
"org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version",
"com.fasterxml.jackson.module:jackson-module-kotlin"
testCompile 'org.springframework.boot:spring-boot-starter-test',
"org.junit.jupiter:junit-jupiter-engine:$jupiter_version",
"org.junit.platform:junit-platform-runner:$junit_platform_version",
"org.assertj:assertj-core:$assertj_version"
}
test {
useJUnitPlatform()
}

There’s a lot required, yes, but no particular magic. To make Spring Boot work you need the collection of plugins and dependencies above.  Some of these are a little creepy, in particular the kotlin-allopen dependency used to circumvent some of Kotlin’s clean code features to allow for Spring Boot’s inelegant hijinks.

What does this get you?  With that build.gradle you’ll be able to develop in Kotlin, use Spring annotations, and run familiar build tasks like gradle bootRun. Additionally, gradle bootRepackage will create a single jar file, including all the Kotlin dependencies, that lets you run the service with java -jar as expected.

Heres my gradle.properties with the versions I used as an up to date and compatible suite:

assertj_version=3.10.0
junit_platform_version=1.2.0
jupiter_version=5.2.0
jvm_version=1.8
kotlin_version=1.2.50
serialization_version=0.5.1
spring_boot_version=2.0.3.RELEASE

The Noteworthy Code

The Application class in Kotlin:

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class Application
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
view raw Application.kt hosted with ❤ by GitHub

Very straight forward. With that in place you’ve now got the best of both worlds.  You can write all your code in Kotlin, but annotate it with Spring annotations, for example a For example, a controller might look like:

import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
@Controller
class StatusMapController {
@GetMapping("/status")
fun statusMap(model: Model, @RequestParam(defaultValue = "prod") env: String): String {
// ....
return "status"
}
}