How to Build Fast Reactive APIs with Spring WebFlux and Azure CosmosDB

Azure Cosmos DB offers single-digit millisecond response times and instant scalability that make it an excellent choice for modern application development. Spring WebFlux, a part of Spring Framework 5.0, enables developers to create powerful non-blocking reactive applications that handle heavy loads with ease.

This tutorial shows you how to build quick reactive REST APIs through Spring WebFlux and Azure Cosmos DB integration. You’ll create a production-grade application with complete CRUD operations using Spring Boot 2.7.1 and Java 17. The guide also covers reactive data stream implementation, performance optimization techniques, and error handling strategies in your Spring WebFlux application.

The tutorial helps you master the creation of standalone, high-performance reactive applications that discover the full potential of Spring WebFlux and Azure Cosmos DB together.

Setting Up Reactive Spring WebFlux Project

The setup of a reactive Spring WebFlux project needs proper configuration of your development environment and Azure Cosmos DB infrastructure to work correctly.

Project Dependencies and Configuration

Your reactive Spring WebFlux application needs spring-boot-starter-webflux dependency as its foundation. On top of that, it needs the Azure Cosmos DB dependency through azure-spring-data-cosmos in your pom.xml file. These are the core dependencies you’ll need:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-spring-data-cosmos</artifactId>
</dependency>

Azure Cosmos DB Account Setup

You’ll need to set up your Azure Cosmos DB account’s connection properties in:application.properties

spring.cloud.azure.cosmos.endpoint=${your-cosmos-db-uri}
spring.cloud.azure.cosmos.key=${your-cosmos-db-key}
spring.cloud.azure.cosmos.database=${your-database-name}
spring.cloud.azure.cosmos.populate-query-metrics=true

Database Schema Design

Azure Cosmos DB’s schema-less nature gives you flexibility in designing your database schema. Your choice of partition key will substantially affect performance. Read-heavy containers need fields that optimize frequent queries. Write-heavy containers work better with fields that have varied data.

The domain classes should use the @Container annotation to specify container names and @PartitionKey to define partition strategies. Your reactive repository interface must extend ReactiveCosmosRepository to enable non-blocking operations.

The best performance comes from implementing connection pooling and setting request timeouts based on your application’s needs. This approach helps your application use Azure Cosmos DB’s distributed capabilities while following reactive principles.

Building Reactive Data Models

Building reactive data models needs a well-laid-out approach that focuses on non-blocking operations and quick data handling.

Implementing Reactive Repository Layer

Reactive data access has its foundations in the repository layer. You can create an interface that extends ReactiveCrudRepository to make non-blocking CRUD operations possible. The repository interface works with reactive types like Mono and Flux to handle single and multiple results:

public interface ReactivePersonRepository extends ReactiveCrudRepository<Person, String> {
    Flux<Person> findByLastname(Mono<String> lastname);
    Mono<Person> findByFirstname AndLastname(String firstname, String lastname);
}

Creating Domain Models with Spring WebFlux

Spring WebFlux’s domain models use Project Reactor’s types to manage asynchronous data flows. These models make shared resource use better by processing more concurrent users with fewer microservice instances. You can create domain classes with appropriate annotations:

@Document(collection = "users")
public class User {
    @Id
    private String id;
    private String name;
    @Version
    private String _etag;
}

Handling Reactive Data Streams

Reactive data streams process information asynchronously with Project Reactor’s Flux and Mono types. The Flux type works as a reactive sequence of 0 to N items while Mono manages 0 or 1 item sequences. This integrated approach will give better resilience between decoupled components through back-pressure support.

Setting Up Connection Pooling

Peak performance depends on optimized connection pooling. Azure Cosmos DB Java SDK v4 uses Direct mode as the best choice for most workloads. You can set up connection pooling by creating a DirectConnectionConfig instance:

DirectConnectionConfig config = new DirectConnectionConfig()
    .setMaxConnectionsPerEndpoint(130)
    .setIdleEndpointTimeout(Duration.ofMinutes(1));

A single instance per AppDomain helps manage connections better and improves SDK client performance.

Implementing CRUD Operations

Spring WebFlux needs a well-planned strategy to handle reactive streams and asynchronous data flow for CRUD operations implementation.

GET Endpoints with Flux and Mono

The Spring WebFlux framework lets you work with HTTP GET operations using reactive types Flux and Mono. You can create endpoints that give back Mono for single resources while using Flux for collections:

@GetMapping
Flux<User> getAll() {
    return repository.findAll();
}
@GetMapping("/{id}")
Mono<User> getUser(@PathVariable("id") String id) {
return repository.findById(id);
}

POST/PUT Operations with WebFlux

Spring WebFlux handles request bodies as reactive streams to create and update resources. Your POST and PUT operations should follow this pattern:

@PostMapping
Mono<User> addUser(@RequestBody User user) {
return repository.save(user);
}
@PutMapping("/{id}")
Mono<User> updateUser(@PathVariable("id") String id, @RequestBody User user) {
return repository.findById(id)
.flatMap(existingUser -> {
user.setId(id);
return repository.save(user);
});
}

Reactive Error Handling Patterns

Your application needs error handling at both functional and global levels. The functional error handling works best with these key operators:

  • onErrorReturn(): Gives a default value during errors
  • onErrorResume(): Creates alternative execution paths
  • switchIfEmpty(): Manages empty results with custom responses
return repository.findById(id)
.onErrorResume(error -> {
System.err.println("Error: " + error.getMessage());
return Mono.empty();
})
.switchIfEmpty(Mono.error(new ResourceNotFoundException()));

Spring WebFlux supports RFC 9457 for standardized error responses. Your application can extend ResponseEntityExceptionHandler to create consistent error handling. This approach will give proper status codes and error messages for different scenarios while keeping your application’s reactive nature intact

Performance Optimization Techniques

Spring WebFlux applications need proper attention to request handling, connection management, and data caching strategies to work at their best.

Configuring Request/Response Timeouts

Your applications will stay responsive when you set up proper timeout configurations. The HttpClient instance helps you configure response timeouts:

HttpClient client = HttpClient.create()
.responseTimeout(Duration.ofSeconds(1))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)

The system works with these timeout types:

  • Response timeout: Sets how long to wait for responses
  • Connection timeout: Controls the time to establish client-server connections
  • Read/Write timeout: Manages how long data transfer operations can take

Connection Pool Tuning

Connection pool settings are vital to performance. The Direct mode architecture uses up to 10 channels per database replica and each channel has a 30-request deep buffer. Here’s how to set up connection pooling:

DirectConnectionConfig config = new DirectConnectionConfig()
.setMaxConnectionsPerEndpoint(130)
.setIdleEndpointTimeout(Duration.ofHours(1))
.setMaxRequestsPerConnection(30)

You’ll save resources by setting the right idle connection timeouts. Traffic patterns that are sporadic need longer idle endpoint timeouts – about 6-12 hours. This helps reduce connection setup overhead.

Implementing Caching Strategy

A good caching strategy will substantially cut down database load. Spring WebFlux naturally blends with Caffeine Cache to give you high-performance in-memory caching. Here’s a basic caching setup:

@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCacheNames(Arrays.asList("users", "transactions"));
return cacheManager;
}

Your caching can use different approaches like cache-aside and read-through patterns. Best results come from caching data that’s accessed often. Make sure to use eviction policies that match your application’s access patterns.

Conclusion

Spring WebFlux and Azure Cosmos DB make a powerful team to build high-performance reactive APIs. This piece walks you through everything in creating production-ready reactive applications. You’ll learn from simple setup to advanced optimization techniques.

Here are the most important areas we cover:

  • Project configuration and Azure Cosmos DB integration
  • Reactive data modeling with Flux and Mono
  • Non-blocking CRUD operations implementation
  • Performance optimization through connection pooling
  • Advanced caching strategies to improve response times

Modern applications can benefit greatly from the reactive programming model, especially when you have high throughput and low latency requirements. Spring WebFlux’s non-blocking features and Azure Cosmos DB’s distributed capabilities help applications handle concurrent requests quickly. Your system’s performance stays consistent throughout.

These patterns work best when you build expandable solutions or live data processing systems. The reactive approach helps you use resources better and makes your system more resilient under heavy loads. Cloud-native applications can really benefit from this approach.

Note that reactive applications need proper connection management, error handling, and smart caching strategies. These elements are the foundations of resilient, production-grade systems that meet modern application demands.

Read More :

Azure Cosmos DB

Azure Cosmos DB is a fully managed NoSQL database for modern app development. Single-digit millisecond response times and automatic and instant scalability guarantee speed at any scale. 

Read More Info – https://docs.microsoft.com/en-us/azure/cosmos-db/introduction

Azure Cosmos DB SQL API

Azure Cosmos DB SQL API accounts provide support for querying items using the Structured Query Language (SQL) syntax.

Read More Info – https://docs.microsoft.com/en-us/azure/cosmos-db/sql/tutorial-query-sql-api

Spring Boot

Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can “just run”. 

Read More Info – https://spring.io/projects/spring-boot

Spring WebFlux

The original web framework included in the Spring Framework, Spring Web MVC, was purpose-built for the Servlet API and Servlet containers. The reactive-stack web framework, Spring WebFlux, was added later in version 5.0. It is fully non-blocking, supports Reactive Streams back pressure, and runs on such servers as Netty, Undertow, and Servlet 3.1+ containers.

Read More Info – https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html

Leave a Reply

Your email address will not be published. Required fields are marked *