Search code examples
spring-bootkotlinspring-webfluxproject-reactorkotlinx.coroutines

Which CoroutineScope to use for Spring Boot WebFlux endpoint


In a Spring Boot WebFlux application we have a number of endpoints (REST and GraphQL) which return a Mono or Flux of something. The code that these endpoints call is all non-blocking, but rather than using reactor we'd like to write all this non-blocking code using Kotlin coroutines. We can use a method such as kotlinx.coroutines.reactor.mono() to wrap our coroutines in a Mono (and the corresponding flux() method for Flux results).

In order to call these methods, though, we first need a CoroutineScope to wrap the whole request (and to handle things like cancelling any child coroutines which our main "entry point" coroutine starts). There seem to be several options here. For example, we could construct a new CoroutineScope and choose a dispatcher, e.g. CoroutineScope(Dispatchers.Default).mono {.... Or we could construct our own class which represents the whole HTTP request, and have that implement CoroutineScope, as shown here for an Android Activity.

Implicit within this question is the choice of what thread (or thread pool) the work should be executed on. We could create a thread pool ourselves, but Spring Boot WebFlux has already created its own thread pool for handling HTTP requests in a non-blocking environment, so maybe it's better to try to stay in the current thread (or in that thread pool)? If that is the best way to go, is there a way to get at that thread pool and get the coroutine to run on that?


Solution

  • Since in Spring WebFlux, HTTP exchanges are not tide to a specific thread, GlobalScope.mono(Dispatchers.Unconfined) is probably the best option.

    Notice that Dispatchers.Unconfined is an experimental API, as well as Coroutines channel API that will be deeply impacted by lazy iterable streams. So I would advise you to wait Spring official support for Coroutines for any production code.