Building a Reactive Architecture with Spring WebFlux and Reactive Redis
Reactive Architecture around Redis with Spring Boot
In this article, I will talk about how to design a reactive application with Spring WebFlux
and Reactive Redis
.
Introduction to Redis
Redis is an open-source, in-memory data structure store used as a database, cache, message broker, and streaming engine. It provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis also provides high availability via Redis Sentinel and automatic partitioning with the Redis Cluster.
What is Reactive Redis?
Spring Boot provides a reactive programming approach to interact with the Redis database, which is called Reactive Redis. This is achieved by offering a reactive version ofRedisConnectionFactory
, known asReactiveRedisConnectionFactory
, which returns a ReactiveConnection.
You can refer to my other articles related to reactive architecture using reactive Redis down below.
Spring Boot application setup with Reactive Redis
Project Technical Stack
- Spring Boot 3.2.0
- Java 21
- Redis
- Docker
Starting Up Redis Server
We will use Docker to start a Redis instance. Simply execute the following command:
docker run --name my-redis -p 6379:6379 -d redis
We will then set up the application with Spring Initializer with the following dependencies in the pom.xml
file.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>2.3.0</version>
</dependency>
Setting Up Configurations
Configure the application.yml
file for the SpringBoot application as follows. We will define the configurations related to Redis in it.
redis:
host: localhost
port: 6379
Reactive Redis Configuration
Create a @Configuration
class RedisConfig
to enable reactive support for Redis.
@Configuration
public class RedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private int port;
@Bean
@Primary
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
@Bean
public ReactiveRedisOperations<String, Product> reactiveRedisOperations(ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
Jackson2JsonRedisSerializer<Product> serializer = new Jackson2JsonRedisSerializer<>(Product.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, Product> builder =
RedisSerializationContext.newSerializationContext(new StringRedisSerializer());
RedisSerializationContext<String, Product> context = builder.value(serializer).build();
return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory, context);
}
}
LettuceConnectionFactory
implements both the RedisConnectionFactory
and ReactiveRedisConnectionFactory
interfaces. When we declare a bean of LettuceConnectionFactory
, we will be registering both RedisConnectionFactory
and ReactiveRedisConnectionFactory
as Spring beans.
ReactiveRedisOperations
is an interface that specifies a basic set of Redis operations, implemented by the ReactiveRedisTemplate
.
Jackson2JsonRedisSerializer
is a RedisSerializer which is used to bind typed beans or untyped Hash
Map instances.
Product Class
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@RedisHash("PRODUCT:REDIS")
public class Product {
private String id;
private String name;
}
Product Service Class
CreateProductService
class and use ReactiveRedisOperations
to access the Redis database.
@Service
@RequiredArgsConstructor
public class ProductService {
private final ReactiveRedisOperations<String, Product> reactiveRedisOperations;
private static final String REDIS_KEY = "PRODUCT:REDIS";
public Flux<Product> findAll() {
return this.reactiveRedisOperations.opsForList().range(REDIS_KEY, 0, -1);
}
public Mono<Product> findById(final String id) {
return this.findAll().filter(p -> p.getId().equals(id)).next();
}
public Mono<Long> save(final Product product) {
final String id = UUID.randomUUID().toString().substring(0, 8);
product.setId(id);
return this.reactiveRedisOperations.opsForList().rightPush(REDIS_KEY, product);
}
public Mono<Boolean> deleteAll() {
return this.reactiveRedisOperations.opsForList().delete(REDIS_KEY);
}
}
Product Controller Class
@RestController
@RequestMapping("/product")
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
@GetMapping
public Flux<Product> findAll(){
return this.productService.findAll();
}
@GetMapping(path = "/{id}")
public Mono<Product> findById(@PathVariable final String id) {
return this.productService.findById(id);
}
@PostMapping
public Mono<Long> save(final Product product){
return this.productService.save(product);
}
@DeleteMapping
public Mono<Boolean> deleteAll() {
return this.productService.deleteAll();
}
}
Testing the Application
We will use Spring Doc Open API to test the Rest Endpoints.
Get all Products
Add a New Product
Get Product by Id
Delete all Products
Summary
In this article, we have covered:
- Introduction to Redis
- What is Reactive Redis?
- How to start a Redis Server with Docker
- Reactive Redis Spring Boot Integration.
- Testing the Rest Endpoints using Spring Doc Open API
Please feel free to share your feedback.
Visit to find more of my articles on Medium.
Thanks for reading.
Stackademic
Thank you for reading until the end. Before you go:
- Please consider clapping and following the writer! 👏
- Follow us on Twitter(X), LinkedIn, and YouTube.
- Visit Stackademic.com to find out more about how we are democratizing free programming education around the world.