Spring Boot and Kotlin

Posted on Jan 1, 2016

I’ve recently had the pleasure of trying out Kotlin for a few projects at work. It’s a promising JVM language from JetBrains that includes a lot of functional elements and a strong type system. I’m told it’s a combination of the best features of Scala and Groovy.

Does it work with Spring?

JetBrains promises 100% interoperability with Java, but it’s not immediately obvious how to get all the pieces working together. In this post I will outline some gotchas when building a Spring Boot “Hello World”. For the impatient, there’s a fully working example at the end.

Running bootRun from Gradle

The bootRun task requires a public static void main(String[] args) method on the @SpringBootApplication annotated class. Kotlin does not have static class methods, but companion objects work just as well:

@SpringBootApplication
open class App {

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            SpringApplication.run(App::class.java, *args)
        }
    }

}

Note that the class must also be marked open and include the @JvmStatic annotation on the companion object.

Dependency Injection (autowiring)

Generally speaking, dependency injection can be done via fields, constructor, and setters.

Field injection is relatively straightforward. The one caveat is to use the lateinit keyword, as Kotlin does not allow late initialization by default.

class SampleController {
   @Autowired
   lateinit var sampleService: SampleService
 }

Constructor-based injection is done via Kotlin’s primary constructors. Note the addition of constructor in the class header:

class SampleController @Autowired constructor(val sampleService: SampleService) {
}

Setter-based injection can be done, but I wasn’t able to make it work with custom setters, which makes it a little useless anyway. Here’s the Kotlin syntax:

class SampleController {
    lateinit var sampleService: SampleService
       @Autowired set
}

Logger initialization

Logger initialization (such as SLF4J) is usually done with LoggerFactory#getLogger(Class<?> clazz). To get the Java class for your Kotlin class, you’d need to use ::class.java:

val logger = LoggerFactory.getLogger(SampleController::class.java)

Jackson deserialization

Spring Boot uses Jackson to serialize and deserialize Java objects into Json and back. Serialization works as expected, but in order to get deserialization to work, you’d need to include the Jackson Kotlin Module. In addition to adding its dependencies in build.gradle, you would also need to add the KotlinModule as a @Bean:

@SpringBootApplication
open class App {

  @Bean
  open fun kotlinModule() = KotlinModule()

}

All together now

To see everything working together, please check out the example on GitHub at https://github.com/nadavc/nadavc-blog-code/tree/master/kotlin-boot

Great Kotlin resources