Kotlin + Spring Boot’s ConfigurationProperties
One minor annoyance i ran into with Spring Boot + Kotlin was that I couldn’t find good documentation on getting Intellij’s autocompletion working with Kotlin classes annotated with @ConfigurationProperties.
ConfigurationProperties can be used to bind property values from application-[profile].properties or application.yml instead of using @Value. The benefits are discussed in many places around the web.
For awhile I was just using Java for my ConfigurationProperties class, adding private fields and creating getters and setters. That works, but getting them working in Kotlin is trivial if you know what to do and results in a lot less boiler plate.
The biggest issue thing is that you need to use kapt, the Kotlin Annotation Processor. You also need to tell kapt to process resources using org.springframework.boot:spring-boot-configuration-processor
plugins apply plugin: 'kotlin-kapt' > dependencies kapt "org.springframework.boot:spring-boot-configuration-processor" compileOnly "org.springframework.boot:spring-boot-configuration-processor" > compileJava.dependsOn(processResources)
Then you can just create a plain old Kotlin class that’s annotated with @ConfigurationProperties
@ConfigurationProperties(prefix = "myapp") class DemoConfigurationProperties var url: URL? = null >
In order for Intellij to autocomplete you just need to run gradle to the point of processing resources. ./gradlew compileKotlin does the trick.
Hosted on GitHub Pages — Theme by orderedlist
info.michael-simons.eu
Last week I decided to raffle a copy of my book (see Twitter) and I wrote a small Spring Boot Command Line Runner to raffle the retweeting winner as one does (see raffle-by-retweet, feel free to reuse this).
I wrote the application in Kotlin. Notice the use of @ConfigurationProperties in my application:
The lateinit attributes are not as nice as I want them to be, but I heard support for data -classes is coming. Anyway. A super useful thing with those configuration property classes are the metadata that can be generated for your IDE of choice, see Configuration Metadata. In a Java application it’s enough to add org.springframework.boot:spring-boot-configuration-processor as compile time dependency respectively as annotationProcessor dependency in a Gradle build.
For Kotlin, you have to use the kotlin-kapt -plugin. It takes care of annotation processing in Kotlin and Spring Boots annotation processor has to be declared in its scope like this:
apply plugin: 'kotlin-kapt' dependencies { // Other dependencies omitted kapt("org.springframework.boot:spring-boot-configuration-processor") }
To make IDEA recognize the generated sources (and also use the same folders for classes as the Gradle build), you can this as well:
apply plugin: 'idea' idea { module { def kaptMain = file("$/generated/source/kapt/main") sourceDirs += kaptMain generatedSourceDirs += kaptMain outputDir file("$/classes/main") testOutputDir file("$/classes/test") } }
apply plugin: ‘idea’ idea < module < def kaptMain = file("$/generated/source/kapt/main") sourceDirs += kaptMain generatedSourceDirs += kaptMain outputDir file("$/classes/main") testOutputDir file("$/classes/test") > >
Find the full build script here.
Spring boot configuration processor kotlin
Kotlin is a statically-typed language targeting the JVM (and other platforms) which allows writing concise and elegant code while providing interoperability with existing libraries written in Java.
Spring Boot provides Kotlin support by leveraging the support in other Spring projects such as Spring Framework, Spring Data, and Reactor. See the Spring Framework Kotlin support documentation for more information.
The easiest way to start with Spring Boot and Kotlin is to follow this comprehensive tutorial. You can create new Kotlin projects via start.spring.io. Feel free to join the #spring channel of Kotlin Slack or ask a question with the spring and kotlin tags on Stack Overflow if you need support.
48.1 Requirements
Spring Boot supports Kotlin 1.2.x. To use Kotlin, org.jetbrains.kotlin:kotlin-stdlib and org.jetbrains.kotlin:kotlin-reflect must be present on the classpath. The kotlin-stdlib variants kotlin-stdlib-jdk7 and kotlin-stdlib-jdk8 can also be used.
Since Kotlin classes are final by default, you are likely to want to configure kotlin-spring plugin in order to automatically open Spring-annotated classes so that they can be proxied.
Jackson’s Kotlin module is required for serializing / deserializing JSON data in Kotlin. It is automatically registered when found on the classpath. A warning message is logged if Jackson and Kotlin are present but the Jackson Kotlin module is not.
These dependencies and plugins are provided by default if one bootstraps a Kotlin project on start.spring.io.
48.2 Null-safety
One of Kotlin’s key features is null-safety. It deals with null values at compile time rather than deferring the problem to runtime and encountering a NullPointerException . This helps to eliminate a common source of bugs without paying the cost of wrappers like Optional . Kotlin also allows using functional constructs with nullable values as described in this comprehensive guide to null-safety in Kotlin.
Although Java does not allow one to express null-safety in its type system, Spring Framework, Spring Data, and Reactor now provide null-safety of their API via tooling-friendly annotations. By default, types from Java APIs used in Kotlin are recognized as platform types for which null-checks are relaxed. Kotlin’s support for JSR 305 annotations combined with nullability annotations provide null-safety for the related Spring API in Kotlin.
The JSR 305 checks can be configured by adding the -Xjsr305 compiler flag with the following options: -Xjsr305=
Generic type arguments, varargs and array elements nullability are not yet supported. See SPR-15942 for up-to-date information. Also be aware that Spring Boot’s own API is not yet annotated.
48.3 Kotlin API
48.3.1 runApplication
Spring Boot provides an idiomatic way to run an application with runApplication(*args) as shown in the following example:
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @SpringBootApplication class MyApplication fun main(args: Array) < runApplication(*args) >
This is a drop-in replacement for SpringApplication.run(MyApplication::class.java, *args) . It also allows customization of the application as shown in the following example:
48.3.2 Extensions
Kotlin extensions provide the ability to extend existing classes with additional functionality. The Spring Boot Kotlin API makes use of these extensions to add new Kotlin specific conveniences to existing APIs.
TestRestTemplate extensions, similar to those provided by Spring Framework for RestOperations in Spring Framework, are provided. Among other things, the extensions make it possible to take advantage of Kotlin reified type parameters.
48.4 Dependency management
In order to avoid mixing different version of Kotlin dependencies on the classpath, dependency management of the following Kotlin dependencies is provided:
- kotlin-reflect
- kotlin-runtime
- kotlin-stdlib
- kotlin-stdlib-jdk7
- kotlin-stdlib-jdk8
- kotlin-stdlib-jre7
- kotlin-stdlib-jre8
With Maven, the Kotlin version can be customized via the kotlin.version property and plugin management is provided for kotlin-maven-plugin . With Gradle, the Spring Boot plugin automatically aligns the kotlin.version with the version of the Kotlin plugin.
48.5 @ConfigurationProperties
@ConfigurationProperties currently only works with lateinit or nullable var properties (the former is recommended), since immutable classes initialized by constructors are not yet supported.
@ConfigurationProperties("example.kotlin") class KotlinExampleProperties < lateinit var name: String lateinit var description: String val myService = MyService() class MyService < lateinit var apiToken: String lateinit var uri: URI >>
To generate your own metadata using the annotation processor, kapt should be configured with the spring-boot-configuration-processor dependency.
48.6 Testing
While it is possible to use JUnit 4 (the default provided by spring-boot-starter-test ) to test Kotlin code, JUnit 5 is recommended. JUnit 5 enables a test class to be instantiated once and reused for all of the class’s tests. This makes it possible to use @BeforeAll and @AfterAll annotations on non-static methods, which is a good fit for Kotlin.
To use JUnit 5, exclude junit:junit dependency from spring-boot-starter-test , add JUnit 5 dependencies, and configure the Maven or Gradle plugin accordingly. See the JUnit 5 documentation for more details. You also need to switch test instance lifecycle to «per-class».