Kotlin-Spring Boot: Gotchas

It’s been around 6 months since we adopted Kotlin for our backend services at the company I currently work at. We’ve been migrating an existing java spring boot service to Kotlin.

Our experience with Kotlin has been mostly great. But sometimes it does feel like Spring was retrofitted to support Kotlin.There’s the basic issues like :

  1. Spring requires classes with annotations to be open, all classes in Kotlin are closed by default. This can be resolved by adding the kotlin-spring plugin to the gradle config.
  2. Hibernate entities require a no-arg constructor, Kotlin has provided a compiler plugin kotlin-jpa to generate an additional zero-argument constructor for classes.

It is important to note that these issues have been identified and the project is generated using start.spring.io have these plugins baked into your configuration. More details on this in the Further Reading section.

Spring DTO @NotNull validation

Let us take a simple DTO to represent a HTTP request body used to create a person, where we expect name and age to be not null. We use javax’s @NotNull annotation to validate the request fields, which we have defined to not be nullable.

For the below request:

{
"age": 20,
"description": "person with no name"
}

We expect a validation error on the name field, however it passes the validators specified on the DTO.

Why?

The javax validator requires an instance of the object before it can validate it. Since the field is declared as a non-nullable, jackson-module-kotlin is providing a default value for the field based on its type. In the case of name(String) it sets it to an empty string, or 0 in case of age(Int).

Possible Workarounds

  1. Based on your use case, factor in the possibility of the value being the default value in the validation. (ie) validate against possible defaults.

This ensures that the name field has at least one character and fails validation on empty strings. Similarly for age it can be specified to have at least a value of 1.

2. Enabling the DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES for jackson-module-kotlin could help by throwing errors while constructing the object during deserialisation. These are different from validation errors and have to handled accordingly.

IMHO the former approach is preferable because apart from the fact it still throws a validation error, it allows you to specify more expressive conditions for validation making it more readable.

Spring does not have support for Coroutines

Coroutines were made stable in the release of Kotlin version 1.3. However they are still not supported by Spring out of the box.

Why?

Spring framework’s dispatchers do no support constructs generated by the Kotlin compiler for Coroutines. Kotlin compiler generates a Continuation parameter for suspended functions, for which Spring has no built-in handlers.

Possible solutions

Thanks to the efforts of Konrad, Coroutines can be used in Spring by using the spring-kotlin-coroutine. The library provides modules to support Coroutines for different applications/domains within Spring.

Or just leverage the @Async executors that come out of the box with Spring.

Spring is working on having more native support for Coroutines. Its status is tracked here. https://jira.spring.io/browse/SPR-15413

Further Reading

Hope you enjoyed reading this as much as I enjoyed writing it. 
If you think this will be of help to someone? Do not hesitate to share. If you liked it, tap the clap below so other people will see this here on Medium. Don’t forget to show some love by following the blog!

More by Gokul Chandrasekaran

Topics of interest

More Related Stories