Building Spring Boot Applications With Maven and Kotlin

Last Updated:  May 21, 2021 | Published: December 5, 2019

With this blog post, you'll get an overview of how to get started with Kotlin and Maven for building Spring Boot applications. I've already covered the usage of Kotlin for Java EE applications and want to provide the same guide for Spring Boot. The demo application communicates with an external system, exposes data via a REST API, and stores data in an embedded H2. We're going to use Spring Boot 2.5.0 and Kotlin 1.5.0.

TL;DR:

  • Spring provides first-class support for Kotlin
  • Write concise applications with Kotlin and be more productive
  • When working with JPA, don't use Kotlin data classes

Maven Project Setup for Spring Boot and Kotlin

After bootstrapping a new Spring Boot and Maven project using Kotlin at start.spring.io,  the pom.xml for this application setup looks like the following:

Apart from the well-known Spring Boot dependencies, we use three Kotlin-specific dependencies.

First, kotlin-stdlib-jdk8 is the basic standard library from Kotlin, and it provides living essentials for working with Kotlin. Second, jackson-module-kotlin adds support for our Jackson ObjectMapper to serialize and deserialize Kotlin classes properly. Last but not least, kotlin-reflect is mandatory as of Spring 5 to enable reflection features for Kotlin.

Moreover, we have to add the kotlin-maven-plugin to our project and instruct Maven to find the Kotlin source files. We configure this within the build section of the pom.xml:

To make use of Kotlin's null-safety feature for the Java-based Spring Framework, we add the compiler argument -Xjsr305=strict. The reason for this is described here:

Although Java does not allow one to express null-safety in its type-system, Spring Framework provides null-safety of the whole Spring Framework API via tooling-friendly annotations declared in the org.springframework.lang package. By default, types from Java APIs used in Kotlin are recognized as platform types for which null-checks are relaxed. Kotlin support for JSR 305 annotations + Spring nullability annotations provide null-safety for the whole Spring Framework API to Kotlin developers, with the advantage of dealing with null related issues at compile time.

This feature can be enabled by adding the -Xjsr305 compiler flag with the strict options.

Furthermore, to have a no-args constructor for our JPA entities, we have to add the jpa plugin. Similar to this, the all-open plugin is required to make use of lazy fetching with JPA.

As a general best practice, we can include ktlint to be aligned with the Kotlin formatting conventions. As part of the Maven validate phase the maven-ant-run plugin will check the formatting of our sources and fail the build if there's malformatted code.

Kotlin Spring Boot Application Walkthrough

Next, let's have a look at the demo application.

As already mentioned, the application exposes data using a REST API. There are two endpoints, one for returning data fetched from a remote API and the other for returning data from the embedded H2 database:

Compared to Java, this endpoint looks quite similar. The main difference is the way we define the primary constructor. With Kotlin, we do this right after the class name as part of the class header.

Furthermore, we can write the controller methods as one-liner as they contain one expression.

The injected WebClient within the constructor of the ApiController class is configured as the following:

It points to a remote API that returns fake data for different domains (e.g., todos, user, comments).

Important Notes When Using JPA with Kotlin

As already described in the Maven project setup section, we need the jpa and all-open plugin for Kotlin to properly use JPA.

You might wonder why I don't use Kotlin's data classes for the JPA entity. As JPA is not designed to work with immutable classes, which we get while using data classes with val properties, we have to use mutable classes.

Creating a JpaRepository from Spring Data is similar to Java:

Given this repository, we can initialize the embedded H2 database with some persons on application startup:

Writing Test for Spring Boot Applications With Kotlin

As mentioned in the Kotlin Coding Conventions, we can use method names with spaces enclosed in backticks. This is a rather small feature but improves the quality of our tests. With Java, we either use camel case or underscores within our test method name to express what it tests.

In contrast, if we are using JUnit 5, something similar is now available for Java applications. We can use the @DisplayName above our test method to describe the tested behavior.

Nevertheless, writing unit and integration tests with Kotlin for our Spring Boot application is similar to Java. To demonstrate this, let's have a look at these short and concise integration tests:

PS: For the second test, we might want to mock the remote call using WireMock.

Final Thoughts on Using Kotlin With Spring Boot

After using Kotlin for almost two years now for several applications in production, these are my final thoughts:

  • Kotlin is a first-class citizen for Spring
  • Once you use JPA, make sure to understand the difference between Java and Kotlin
  • Maven plugins are available for using Spring Boot with Kotlin (also for Gradle)
  • Kotlin is a great language to be even more productive
  • More support and dedicated Kotlin modules are coming
  • Kotlin is simple to adopt as a Java developer

If you are looking for an excellent introduction to Kotlin dedicated to former Java Developers, have a look at this Udemy course.

For those of you who are using Java EE, I've also published a guide on using Kotlin alongside Java EE. As always, the source code is available on GitHub.

Have fun building your next Spring Boot application with Kotlin and Maven,

Philip

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Sign up for Our Mailing List And Get

the Testing Java Applications ($9) Cheat Sheet for Free

Testing Java Applications Cheat Sheet Cover
>