Spring Data MongoDB with Reactive MongoDB

Spring Data MongoDB with Reactive MongoDB

Spring Data MongoDB has been updated to leverage the reactive programming model introduced in Spring Framework 5. This was followed by support for reactive data access for NoSQL databases, such as MongoDB, Cassandra, and Redis.

With the rise in popularity of NoSQL databases, MongoDB has rapidly gained popularity in the enterprise and the Spring community.

I have published both a post and a video for setting up MongoDB within a Spring Boot application.

In this post, we’ll take a look at using the reactive programming features in Spring Framework 5 and Spring Data MongoDB.

The Maven POM

For this post, I’m using Embedded MongoDB. I want the benefit of talking to an instance loaded in memory with the same capabilities as my production environment. This makes development and testing blazing fast.

You can check my post to configure and use Embedded MongoDB in a Spring Boot application here.

The whole capability of Reactive MongoDB lies on the MongoDB driver. The official MongoDB Reactive Streams Java Driver implements the Reactive Streams API for interoperability with other reactive stream implementations. The reactive driver provides asynchronous stream processing with non-blocking back pressure for MongoDB.

pom.xml

The Domain Object

I have written a Product domain object for this post. Products have a name, description, price, and product URL.

Product.java

Spring Data MongoDB Reactive CRUD Repository

If you have worked with Spring Data in a Spring Boot application, you are familar with the repository pattern. You extend CrudRepository or its sub interface, and Spring Data MongoDB will generate the implementation for you.

Reactive repositories work the same way. You extend your repository interface from ReactiveCrudRepository, specify domain-specific query methods, and rely on Spring Data MongoDB to provide the implementations.

ReactiveProductRepository.java

As you can see, in this ReactiveProductRepository interface, the repository uses reactive types as return types.

Reactive repositories in Spring Data MongoDB can also use reactive types for parameters. The overloaded findByName() and findByNameAndImageUrl() methods are examples of this.

Configuration for Spring Data MongoDB Reactive Repositories

The configuration class is similar to a non-reactive one. Along with some infrastructural setup, we have the @EnableReactiveMongoRepositories annotation that activates support for reactive Spring Data.

The code of the ApplicationConfiguration class is this.

ApplicationConfiguration.java

This ApplicationConfiguration class extends AbstractReactiveMongoConfiguration, the base class for reactive Spring Data MongoDB configuration. The mongoClient() method is annotated with @Bean to explicitly declare a configurable MongoClient bean that represents a pool of connections for MongoDB.

Spring Data MongoDB Integration Tests

Let’s write few integration tests for the repository layer to verify that our code is using reactive MongoDB as expected.

Here is the integration test code:

ReactiveProductRepositoryIntegrationTest.java

ReactiveMongoOperations is the interface for the main reactive Template API class, ReactiveMongoTemplate. This interface defines a basic set of reactive data access operations using Project Reactor Mono and Flux reactive types.

ReactiveMongoOperations contains reactive counterpart for most of the operations available in the MongoOperations interface of the traditional blocking template API.

The setup portion of our integration test will drop any existing documents and re-create the Product collection. The setup method then inserts 4 new documents into our MongoDB collection.

We’re calling the .block() method to ensure processing completes before the next command is executed.

Just a question: have you ever tried to compare your solution with a classical non-reactive in order to understand the scalability of the last? Well, I’m struggling to make solution based on reactive Mongo repository performant as non-reactive solution but I keep on seeing better result with non-blocking.