Skip to content
Bluetape4k docs1.11

Spring Data MongoDB Coroutine Support

Latest stable Based on Bluetape4k release 1.11.0

bluetape4k-spring-boot-mongodb adapts Spring Data MongoDB’s ReactiveMongoOperations to Kotlin coroutines. Operations that can produce multiple documents return Flow<T>; operations with one result become suspending functions. The module also provides concise Kotlin extensions for composing Criteria, Query, and Update objects.

It does not create a MongoDB client or connection pool. It uses the ReactiveMongoDatabaseFactory and MongoConverter configured by Spring Boot, while the MongoDB driver owns connections, the wire protocol, and server errors. Its auto-configuration is a small fallback that supplies ReactiveMongoTemplate only when no ReactiveMongoOperations bean exists.

  • Decide whether Spring Data mapping and ReactiveMongoOperations are the application’s persistence boundary.
  • Distinguish an optional lookup, where zero documents means null, from a required lookup, where zero documents is an error.
  • Choose where a multi-result or multi-insert Flow will be collected.
  • Keep the different write semantics of save, updateFirst, updateMulti, and upsert explicit.
  • Let Spring Boot and the driver own transactions, retryable writes, concerns, pool settings, and timeouts.

If the application wants the MongoDB Kotlin driver without Spring Data, start with bluetape4k-mongodb.

Consumers manage only the bluetape4k-dependencies BOM version rather than aligning individual Spring and MongoDB driver versions.

dependencies {
implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:<version>"))
implementation("io.github.bluetape4k:bluetape4k-spring-boot-mongodb")
}

The artifact exposes the Spring Data MongoDB Reactive starter, coroutine/Reactor integration, and bluetape4k-spring-boot-core.

Inject the ReactiveMongoOperations supplied by Spring Boot and let the repository choose the query and result shape.

@Repository
class UserRepository(
private val operations: ReactiveMongoOperations,
) {
fun findAdults(city: String): Flow<User> =
operations.findAsFlow(
queryOf("age".criteria() gte 20, "city".criteria() eq city)
.sortAscBy("name")
)
suspend fun findById(id: String): User? =
operations.findByIdOrNullSuspending(id)
suspend fun insert(user: User): User =
operations.insertSuspending(user)
}

The Flow returned by findAdults subscribes to the Spring Data publisher when collected. Preserve that boundary through a WebFlux controller or coroutine service instead of inserting block() or runBlocking.

TaskAPIResult and boundary
Read multiple documentsfindAsFlow, findAllAsFlowFlow<T>; zero results is an empty Flow
Optional single lookupfindOneOrNullSuspending, findByIdOrNullSuspendingzero results is null
Required single lookupfindOneSuspending, findByIdSuspendingzero results throws NoSuchElementException
Count and existencecountSuspending, existsSuspendingLong and Boolean
Insert and saveinsertSuspending, insertAllAsFlow, saveSuspendingsaved entity or Flow<T>
Conditional update and upsertupdateFirstSuspending, updateMultiSuspending, upsertSuspendingUpdateResult
Atomic modify and removefindAndModifySuspending, findAndRemoveSuspendingnull when no document matches
Aggregate, distinct, and tailaggregateAsFlow, findDistinctAsFlow, tailAsFlowFlow<T>
Collection managementcollectionExistsSuspending, createCollectionSuspending, dropCollectionSuspendingBoolean or Unit

The chapters explain execution timing, result cardinality, and the Spring Boot/driver boundary before listing APIs. Each example links to its 1.11.0 source and tests.

  1. Auto-configuration and ownership boundaries — identify the fallback bean conditions and configuration owned by Spring Boot and the driver.
  2. Coroutine reads and cardinality — distinguish Flow, optional single results, and required single results.
  3. Writes and atomic operations — interpret insert, save, update, upsert, and find-and-modify results.
  4. Criteria, Query, and Update DSL — compose filters, ordering, pagination, and updates with Kotlin syntax.
  5. Aggregation, collections, and streaming — use aggregation, distinct queries, capped collections, and tailable cursors.
  6. Testing, operations, and ecosystem — connect Testcontainers evidence, operational signals, and the native-driver path.

For first use, read chapters 1 through 4 in order. Start with chapter 5 for aggregation or tailable cursors, and chapter 6 for an adoption review or test plan.

A repository should receive ReactiveMongoOperations and decide the query and cardinality. A service should own transactions and retries that span repository calls. Inspect UpdateResult.matchedCount, modifiedCount, and DeleteResult.deletedCount to distinguish no match from an actual change.

The string-based field DSL is concise, but the compiler cannot check it against the document schema. Map external sort and field inputs through an allowlist. paginate also performs no validation for a negative page or non-positive size, so validate HTTP input before building the query.

WebFlux controller / coroutine service
bluetape4k coroutine operations + query DSL
ReactiveMongoOperations / mapping converter
ReactiveMongoDatabaseFactory / MongoDB driver
MongoDB server

The module does not replace these layers. The coroutine adapter maps Reactor publishers to Flow, awaitSingle, or awaitSingleOrNull; the DSL creates ordinary Spring Data query objects.

AutoConfiguration.imports registers ReactiveMongoAutoConfiguration. It creates a ReactiveMongoTemplate only when ReactiveMongoOperations is on the classpath and no bean of that type exists. The required ReactiveMongoDatabaseFactory and MongoConverter must already be present in the Spring context.

Spring Boot and the MongoDB driver own the URI, credentials, database, SSL, timeouts, and pool. This module has no custom @ConfigurationProperties, client builder, conversion registry, or auditing switch. Put application-specific MongoCustomConversions and auditing configuration in a separate Spring configuration.

The coroutine extensions do not translate Spring Data or driver failures into domain values. Nullable lookups turn only an absent result into null. Connection failures, duplicate keys, mapping errors, and timeouts remain exceptions. A required single lookup uses awaitSingle() and throws NoSuchElementException for an empty publisher.

Cancelling collection of a Flow cancels its subscription. Do not turn cancellation into an empty result or success. Before adding a retry, confirm that the whole operation is idempotent and that it does not duplicate driver-level retryable writes.

The module adds no metrics or health indicator. Use Spring Boot Actuator, MongoDB driver command monitoring, and pool metrics to observe server selection, pool waits, query latency, and timeouts. A slow Flow consumer can extend subscription and connection use, so observe result size and consumer throughput together.

A tailable cursor is a long-lived subscription. Verify that application shutdown and coroutine-scope cancellation reach the cursor, then place reconnect policy outside the adapter according to the tolerated duplicate and loss behavior.

Terminal window
./gradlew :bluetape4k-spring-boot-mongodb:test --no-build-cache --no-configuration-cache

The 1.11.0 integration suite uses a MongoDBServer Testcontainer and a real Spring Boot context. ReactiveMongoOperationsCoroutinesTest covers insert, save, reads, updates, upsert, delete, aggregation, and collection management. Criteria, Query, and Update DSL tests compare generated BSON structures without a MongoDB connection.

Run the Docker-backed suite serially with other Testcontainers work. Keeping the DSL unit tests separate from integration tests helps determine whether a failure comes from query construction or from the server and driver boundary.

No dedicated workshop is registered. ReactiveMongoOperationsCoroutinesTest is the broadest executable example in the module; read it with the User document to follow insert through aggregation.

Use bluetape4k-mongodb when direct control of the MongoDB Kotlin driver API and codecs matters more than Spring Data mapping. If a Spring Data repository interface is required, choose Spring Data’s reactive or coroutine repository support separately from these extensions.

This manual targets the bluetape4k-projects 1.11.0 release source. The module does not generate Spring Data repository implementations and does not configure custom conversions, auditing, a transaction manager, a MongoDB client, or a pool. Although MongoDB Kotlin sync and coroutine driver dependencies are present, its public surface focuses on ReactiveMongoOperations extensions and the query DSL.

tailAsFlow requires a capped collection. paginate is offset based, can become expensive for large pages, and does not validate its arguments. Implement sorted seek pagination in the application query for large result sets.

These diagrams are loaded directly from README assets published with the 1.11.0 release and pinned to its immutable commit. They describe this manual’s released structure and runtime flows, not later Snapshot changes. Select a preview to open the SVG at the same release commit.

Core Class Structure diagram

Release README: spring-boot/mongodb/README.md

ReactiveMongoOperations Coroutine Extension Flow diagram

Section titled “ReactiveMongoOperations Coroutine Extension Flow diagram”

ReactiveMongoOperations Coroutine Extension Flow diagram

Release README: spring-boot/mongodb/README.md

Criteria / Query / Update DSL Flow diagram

Section titled “Criteria / Query / Update DSL Flow diagram”

Criteria / Query / Update DSL Flow diagram

Release README: spring-boot/mongodb/README.md

Coroutine Conversion Sequence diagram

Release README: spring-boot/mongodb/README.md