Skip to content

Kotlin integration#

The module mutiny-kotlin provides an integration with Kotlin for use with coroutines and convenient language features.

There are extension methods available for converting between Mutiny and Kotlin (coroutine) types. For implementation details please have also a look to these methods’ documentation.

Dependency coordinates#

The coroutine extension functions are shipped in the package io.smallrye.mutiny.coroutines.

1
2
3
4
import io.smallrye.mutiny.coroutines.asFlow
import io.smallrye.mutiny.coroutines.asMulti
import io.smallrye.mutiny.coroutines.asUni
import io.smallrye.mutiny.coroutines.awaitSuspending

You need to add the following dependency to your project:

<dependency>
    <groupId>io.smallrye.reactive</groupId>
    <artifactId>mutiny-kotlin</artifactId>
    <version>2.5.1</version>
</dependency>
implementation("io.smallrye.reactive:mutiny-kotlin:2.5.1")
implementation "io.smallrye.reactive:mutiny-kotlin:2.5.1"

Awaiting a Uni in coroutines#

Within a coroutine or suspend function you can easily await Uni events in a suspended way:

1
2
3
4
5
6
7
val uni: Uni<String> = Uni.createFrom().item("Mutiny ❤ Kotlin")
try {
    // Available within suspend function and CoroutineScope
    val item: String = uni.awaitSuspending()
} catch (failure: Throwable) {
    // onFailure event happened
}

Processing a Multi as Flow#

The coroutine Flow type matches Multi semantically, even though it isn’t a feature complete reactive streams implementation. You can process a Multi as Flow as follows:

val multi: Multi<String> = Multi.createFrom().items("Mutiny", "❤", "Kotlin")
val flow: Flow<String> = multi.asFlow()

Note

There’s no flow control availabe for Kotlin’s Flow. Published items are buffered for consumption using a coroutine Channel. The buffer size and overflow strategy of that Channel can be configured using optional arguments: Multi.asFlow(bufferCapacity = Channel.UNLIMITED, bufferOverflowStrategy = BufferOverflow.SUSPEND), for more details please consult the method documentation.

Providing a Deferred value as Uni#

The other way around is also possible, let a Deferred become a Uni:

val deferred: Deferred<String> = GlobalScope.async { "Kotlin ❤ Mutiny" }
val uni: Uni<String> = deferred.asUni()

Creating a Multi from a Flow#

Finally, creating a Multi from a Flow is also possible:

val flow: Flow<String> = flowOf("Kotlin", "❤", "Mutiny")
val multi: Multi<String> = flow.asMulti()

Language convenience#

Unit instead of Void (null) value#

Kotlin has a special value type Unit similar to Java’s Void. While regular Uni<Void> holds a null item, you can get a Unit by using the extension function replaceWithUnit():

1
2
3
// import io.smallrye.mutiny.replaceWithUnit
val unitUni : Uni<Unit> = uni.replaceWithUnit()
assert(unitUni.await().indefinitely() === Unit)

Uni builder#

Building a Uni from Kotlin code can easily be achieved using the following builders available as regular or coroutine variant:

// import io.smallrye.mutiny.uni
val uni: Uni<String> = uni { "λ 🚧" }
1
2
3
4
// import io.smallrye.mutiny.coroutines.uni
coroutineScope {
    val uni: Uni<String> = uni { "λ 🚧" }
}