Kotlin coroutines are an efficient way to (re)use threads while the computation has been moved somewhere else. Coroutines are bound to the concept of Scope
: to run one, you need before to declare a scope object. This is how they implement structured concurrency. To get a scope, you use the scope-builders functions, like coroutineScope{}
or runBlocking{}
. A scope suspends (or blocks) a thread until all of its coroutines are finished.
This means that you can’t just fire-and-forget an operation if you don’t have the plain control of your main
(quite usual with frameworks). The JVM would wait for the scope to complete before continuing with anything outside of it.
In the Spring world, coroutines are supported at a framework level by Spring WebFlux, the non-blocking alternative to Spring Boot. In Spring WebFlux, controller methods can be declared suspend
.
You can write the following:
@GetMapping("/foo")
suspend fun foo: X = coroutineScope{
val x = async { restClient.getForObject<Int>("/bla1") }
val y = async { restClient.getForObject<Int>("/bla2") }
x.await() + y.await()
}
In Spring Boot, you can’t declare a controller as suspending, yet you could use runBlocking
.
@GetMapping("/foo")
fun foo(): Int = runBlocking {
val x = async { restClient.getForObject<Int>("/bla1") }
val y = async { restClient.getForObject<Int>("/bla2") }
x.await() + y.await()
}
In the last example, you benefit coroutines asynchronicity even if the thread is blocked. Threads are blocked anyway, as Spring Boot implements the one-thread-per-request model_._
Let’s figure out a situation where you would like to start a stream or launch a long-running job. You don’t want to wait for the end of the task before returning with an HTTP response. For streams, you could choose Server-Sent-Events, then accept waiting until the end of the stream, but it is not always the case. For example, this is not suited for a long-running job or if the stream should be delivered through a WebSocket.
If you use the builder functions, the coroutine scope is bound to the scope of the method. The method will not return before the completion of everything inside the scope.
#spring boot #kotlin