Kotlin coroutines and Spring 5

Tue, May 2, 2017

This article is a next one in the series which is focused on practical application of Kotlin experimental language feature - coroutines. This example shows how to use coroutines with Spring 5 Reactive Web Framework to write linear, concurrent and non-blocking code for Spring web applications.

Quick intro

As we found out previously, coroutines is the powerful mechanism which allows to write concurrent, non-blocking code without loosing in readability and keeping the source code “sequential”. Kotlin coroutines are nicely integrated with existing non-blocking frameworks from Java ecosystem, like RxJava and Reactive Streams (which is planned to be a part of upcoming Java 9).

Spring 5 is the next major version of Spring Framework, which introduces a whole lot of improvements and new features. One of them which we are mostly interested at the moment is Reactive Web Framework, or WebFlux. It is based on implementation of Reactive Streams API by the project called Project Reactor.

And it turns out, that Kotlin and Spring WebFlux are playing very well together. Kotlin coroutines can be smoothly integrated with reactive types and Spring WebFlux uses that API for non-blocking I/O.

Reactive types

Let’s start with a short introduction to summarize the knowledge of reactive types in Spring 5 you got from the official intro. We should start with Reactive Streams library which introduces fundamental class to describe publisher/subscriber interaction - Publisher<T> which is very similar to Observable from RxJs and RxJava. This is a very basic interface which only defines one operation - subscription and can provide potentially unbounded number of elements to its consumers. Project Reactor adds two implementations of Publisher - Mono which implies a single value and Flux - stream of values. Using any of these types as a return value of a function assumes that function will return immediately (without blocking current thread) and the result (Flux or Mono) will be available to subscribers later.

Important to note that Flux doesn’t mean infinite stream, as you might expect from generator. It could be a finite sequence of elements with values published to the subscribers on arrival.

Blocking code

Let’s talk about Spring now. To start with an example, consider the following controller method. Class declaration and application code are omitted, please see the full source code if you’d like to.

This controller method takes personId as a parameter, finds a person with given ID in Mongo repository, or throws NoSuchElementException. Then, method used person’s email to find a last login date in the audit repository. Finally, number of received messages is fetched from the third repository.

This is a classic blocking code, every time we call a method on a repository object, the execution thread is blocked until the result is received. To make it concurrent we can easily switch it to WebFlux and utilize reactive types we’ve been discussing earlier.

Make it reactive

To do this, we just need to change return type of the controller method to be one of the reactive types (Mono or Flux,) and Spring will take care about the rest. However due to non-linear nature of execution of reactive code we need to introduce a whole lot of callbacks within map or flatMap function. Anyway, let’s try and see how reactive method may look like.

Important to note that repositories we are using are not classic CrudRepository, but ReactiveCrudRepository instances. As you can guess instead of returning Person from findById method, reactive repository returns Mono<Person> hence map and flatMap methods.

switchIfEmpty here is just to handle non-existing person and throw NoSuchElementException when reactive repository returns empty Mono (i.e. no values).

The code above does all the same as the first version. So now we have non-blocking code however we lose in readability and need to deal with callback chained via map and flatMap methods combination.

Kotlinize it!

You might think - it would be nice to keep non-blocking reactive nature of our code, but keep it linear and readable as in classic example. Well, thanks to Kotlin coroutines it is possible.

Noticed differences with the first example? Our function now wrapped into mono(Unconfined) method call. This is our gateway from Reactor type (Mono) to Kotlin’s coroutines. The mono(...) function is a coroutine builder, similar to launch and async we’ve seen in Kotlinx coroutine examples. As any coroutine builder it specifies context to use. Unconfined means coroutine will start in the calling thread but then can be multiplexed by a scheduler to other threads as well. The function also returns a value, although it doesn’t have return keyword, because the whole function is now lambda and Kotlin doesn’t need return in lambdas. Thanks to type inference, Kotlin also manages to infer return type based on type of the return value. So signature of our function is actually this:

fungetMessages(@PathVariable personId: String): Mono<String>

So now we have a coroutine function that returns a Mono<String> and more importantly is we can now call suspendable functions from our controller method. Remember the functions that do no block the current thread? That is it!

Current version of kotlinx.coroutines.reactor is not yet compatible with latest release of Project Reactor (3.1 Bismuth M1) which is required by Spring Data Reactive Mongo. So we cannot use official build from JetBrains. Instead, sample project includes custom build of kotlinx.coroutines.reactor updated to Project Reactor 3.1. Please note, this version is not intended for anything more than experimenting in the scope of this article!

Right, so now we can call suspendable function but we still need to somehow turn Mono<Person> (returned by our reactive repository) to a such function. Luckily there are a few extension functions for a base Publisher<T> class (from Reactive Streams) in kotlinx.coroutinex.reactive package which extend any Publisher and thus Mono and Flux values with a set of new methods called await*. In our case we are using awaitSingle() which yields control over current thread back to scheduler until target Publisher returns a value.

And that is pretty much it, having a combination of mono method to produce a reactive type and awaitSingle to consume it in non-blocking manner we can build complex non-blocking function and keep code clean and linear.

Conclusion

To use reactive types which are building blocks of Spring 5 reactive web framework (WebFlux) with Kotlin coroutines there is a set of functions provided by kotlinx.coroutines.reactive/reactor libraries. These functions help to easily build (using mono/flux coroutine builders) a reactive value and also subscribe to a reactive result in non-blocking manner using await* extension functions.

Disclaimer

Coroutines is still an experimental feature of Kotlin and cannot be used in production code. Versions of Spring (RC1), Spring Boot (M1) and Project Reactor (Bismuth M1) are also not finalized yet, please follow the announcements from Spring team.