Kotlin Coroutines are instances of suspendable computations allowing to write non-blocking code imperatively. On language side, suspend functions provides an abstraction for asynchronous operations while on library side kotlinx.coroutines provides functions like async { } and types like Flow.spring-doc.cn

Spring Data modules provide support for Coroutines on the following scope:spring-doc.cn

Dependencies

Coroutines support is enabled when kotlinx-coroutines-core, kotlinx-coroutines-reactive and kotlinx-coroutines-reactor dependencies are in the classpath:spring-doc.cn

Dependencies to add in Maven pom.xml
<dependency>
	<groupId>org.jetbrains.kotlinx</groupId>
	<artifactId>kotlinx-coroutines-core</artifactId>
</dependency>

<dependency>
	<groupId>org.jetbrains.kotlinx</groupId>
	<artifactId>kotlinx-coroutines-reactive</artifactId>
</dependency>

<dependency>
	<groupId>org.jetbrains.kotlinx</groupId>
	<artifactId>kotlinx-coroutines-reactor</artifactId>
</dependency>
Supported versions 1.3.0 and above.
Supported versions 1.3.0 and above.

How Reactive translates to Coroutines?

For return values, the translation from Reactive to Coroutines APIs is the following:spring-doc.cn

  • fun handler(): Mono<Void> becomes suspend fun handler()spring-doc.cn

  • fun handler(): Mono<T> becomes suspend fun handler(): T or suspend fun handler(): T? depending on if the Mono can be empty or not (with the advantage of being more statically typed)spring-doc.cn

  • fun handler(): Flux<T> becomes fun handler(): Flow<T>spring-doc.cn

Flow is Flux equivalent in Coroutines world, suitable for hot or cold stream, finite or infinite streams, with the following main differences:spring-doc.cn

Read this blog post about Going Reactive with Spring, Coroutines and Kotlin Flow for more details, including how to run code concurrently with Coroutines.spring-doc.cn

Repositories

Here is an example of a Coroutines repository:spring-doc.cn

interface CoroutineRepository : CoroutineCrudRepository<User, String> {

    suspend fun findOne(id: String): User

    fun findByFirstname(firstname: String): Flow<User>

    suspend fun findAllByFirstname(id: String): List<User>
}

Coroutines repositories are built on reactive repositories to expose the non-blocking nature of data access through Kotlin’s Coroutines. Methods on a Coroutines repository can be backed either by a query method or a custom implementation. Invoking a custom implementation method propagates the Coroutines invocation to the actual implementation method if the custom method is suspend-able without requiring the implementation method to return a reactive type such as Mono or Flux.spring-doc.cn

Note that depending on the method declaration the coroutine context may or may not be available. To retain access to the context, either declare your method using suspend or return a type that enables context propagation such as Flow.spring-doc.cn

  • suspend fun findOne(id: String): User: Retrieve the data once and synchronously by suspending.spring-doc.cn

  • fun findByFirstname(firstname: String): Flow<User>: Retrieve a stream of data. The Flow is created eagerly while data is fetched upon Flow interaction (Flow.collect(…)).spring-doc.cn

  • fun getUser(): User: Retrieve data once blocking the thread and without context propagation. This should be avoided.spring-doc.cn

Coroutines repositories are only discovered when the repository extends the CoroutineCrudRepository interface.
Coroutines repositories are only discovered when the repository extends the CoroutineCrudRepository interface.