Spring Data Reactive Redis examples

Issue: BAEL-1868
This commit is contained in:
Shreyash 2018-10-14 11:34:09 +05:30 committed by Josh Cummings
parent 3c71e5e677
commit c9f2162f98
12 changed files with 318 additions and 43 deletions

View File

@ -7,17 +7,61 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<parent> <parent>
<artifactId>parent-boot-2</artifactId>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>parent-spring-5</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-spring-5</relativePath> <relativePath>../../parent-boot-2</relativePath>
</parent> </parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-data-redis</artifactId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
<version>${spring-data-redis}</version> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -33,42 +77,12 @@
<type>jar</type> <type>jar</type>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.lordofthejars</groupId> <groupId>com.lordofthejars</groupId>
<artifactId>nosqlunit-redis</artifactId> <artifactId>nosqlunit-redis</artifactId>
<version>${nosqlunit.version}</version> <version>${nosqlunit.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${spring-data-commons.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.kstyrc</groupId> <groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId> <artifactId>embedded-redis</artifactId>
@ -77,12 +91,13 @@
</dependencies> </dependencies>
<properties> <properties>
<spring-data-redis>2.0.3.RELEASE</spring-data-redis>
<cglib.version>3.2.4</cglib.version> <cglib.version>3.2.4</cglib.version>
<jedis.version>2.9.0</jedis.version> <jedis.version>2.9.0</jedis.version>
<nosqlunit.version>0.10.0</nosqlunit.version> <nosqlunit.version>0.10.0</nosqlunit.version>
<spring-data-commons.version>2.0.3.RELEASE</spring-data-commons.version> <spring-data-commons.version>2.0.3.RELEASE</spring-data-commons.version>
<embedded-redis.version>0.6</embedded-redis.version> <embedded-redis.version>0.6</embedded-redis.version>
<junit.platform.version>1.0.0</junit.platform.version>
<junit.jupiter.version>5.0.2</junit.jupiter.version>
</properties> </properties>
</project> </project>

View File

@ -0,0 +1,13 @@
package com.baeldung.spring.data.reactive.redis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringRedisReactiveApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRedisReactiveApplication.class, args);
}
}

View File

@ -0,0 +1,56 @@
package com.baeldung.spring.data.reactive.redis.config;
import com.baeldung.spring.data.reactive.redis.model.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.ReactiveKeyCommands;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.ReactiveStringCommands;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.PreDestroy;
@Configuration
public class RedisConfig {
@Autowired
RedisConnectionFactory factory;
@Bean
public ReactiveRedisTemplate<String, Employee> reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<>(Employee.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, Employee> builder = RedisSerializationContext.newSerializationContext(new StringRedisSerializer());
RedisSerializationContext<String, Employee> context = builder.value(serializer)
.build();
return new ReactiveRedisTemplate<>(factory, context);
}
@Bean
public ReactiveRedisTemplate<String, String> reactiveRedisTemplateString(ReactiveRedisConnectionFactory connectionFactory) {
return new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext.string());
}
@Bean
public ReactiveKeyCommands keyCommands(final ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection()
.keyCommands();
}
@Bean
public ReactiveStringCommands stringCommands(final ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
return reactiveRedisConnectionFactory.getReactiveConnection()
.stringCommands();
}
@PreDestroy
public void cleanRedis() {
factory.getConnection()
.flushDb();
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.spring.data.reactive.redis.model;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Employee implements Serializable {
private static final long serialVersionUID = 1603714798906422731L;
private String id;
private String name;
private String department;
}

View File

@ -1,6 +1,8 @@
package com.baeldung.spring.data.redis.config; package com.baeldung.spring.data.redis.config;
import org.springframework.beans.factory.annotation.Value; import com.baeldung.spring.data.redis.queue.MessagePublisher;
import com.baeldung.spring.data.redis.queue.RedisMessagePublisher;
import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -13,10 +15,6 @@ import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.GenericToStringSerializer; import org.springframework.data.redis.serializer.GenericToStringSerializer;
import com.baeldung.spring.data.redis.queue.MessagePublisher;
import com.baeldung.spring.data.redis.queue.RedisMessagePublisher;
import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
@Configuration @Configuration
@ComponentScan("com.baeldung.spring.data.redis") @ComponentScan("com.baeldung.spring.data.redis")
@EnableRedisRepositories(basePackages = "com.baeldung.spring.data.redis.repo") @EnableRedisRepositories(basePackages = "com.baeldung.spring.data.redis.repo")

View File

@ -0,0 +1,51 @@
package com.baeldung.spring.data.reactive.redis.template;
import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.ReactiveKeyCommands;
import org.springframework.data.redis.connection.ReactiveStringCommands;
import org.springframework.data.redis.connection.ReactiveStringCommands.SetCommand;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.nio.ByteBuffer;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisReactiveApplication.class)
public class RedisKeyCommandsIntegrationTest {
@Autowired
private ReactiveKeyCommands keyCommands;
@Autowired
private ReactiveStringCommands stringCommands;
@Test
public void givenFluxOfKeys_whenPerformOperations_thenPerformOperations() {
Flux<String> keys = Flux.just("key1", "key2", "key3", "key4");
Flux<SetCommand> generator = keys.map(String::getBytes)
.map(ByteBuffer::wrap)
.map(key -> SetCommand.set(key)
.value(key));
StepVerifier.create(stringCommands.set(generator))
.expectNextCount(4L)
.verifyComplete();
Mono<Long> keyCount = keyCommands.keys(ByteBuffer.wrap("key*".getBytes()))
.flatMapMany(Flux::fromIterable)
.count();
StepVerifier.create(keyCount)
.expectNext(4L)
.verifyComplete();
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.spring.data.reactive.redis.template;
import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ReactiveListOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisReactiveApplication.class)
public class RedisTemplateListOpsIntegrationTest {
private static final String LIST_NAME = "demo_list";
@Autowired
private ReactiveRedisTemplate<String, String> redisTemplate;
private ReactiveListOperations<String, String> reactiveListOps;
@Before
public void setup() {
reactiveListOps = redisTemplate.opsForList();
}
@Test
public void givenListAndValues_whenLeftPushAndLeftPop_thenLeftPushAndLeftPop() {
Mono<Long> lPush = reactiveListOps.leftPushAll(LIST_NAME, "first", "second")
.log("Pushed");
StepVerifier.create(lPush)
.expectNext(2L)
.verifyComplete();
Mono<String> lPop = reactiveListOps.leftPop(LIST_NAME)
.log("Popped");
StepVerifier.create(lPop)
.expectNext("second")
.verifyComplete();
}
}

View File

@ -0,0 +1,71 @@
package com.baeldung.spring.data.reactive.redis.template;
import com.baeldung.spring.data.reactive.redis.SpringRedisReactiveApplication;
import com.baeldung.spring.data.reactive.redis.model.Employee;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.ReactiveValueOperations;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.Duration;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisReactiveApplication.class)
public class RedisTemplateValueOpsIntegrationTest {
@Autowired
private ReactiveRedisTemplate<String, Employee> redisTemplate;
private ReactiveValueOperations<String, Employee> reactiveValueOps;
@Before
public void setup() {
reactiveValueOps = redisTemplate.opsForValue();
}
@Test
public void givenEmployee_whenSet_thenSet() {
Mono<Boolean> result = reactiveValueOps.set("123", new Employee("123", "Bill", "Accounts"));
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
}
@Test
public void givenEmployeeId_whenGet_thenReturnsEmployee() {
Mono<Employee> fetchedEmployee = reactiveValueOps.get("123");
StepVerifier.create(fetchedEmployee)
.expectNext(new Employee("123", "Bill", "Accounts"))
.verifyComplete();
}
@Test
public void givenEmployee_whenSetWithExpiry_thenSetsWithExpiryTime() throws InterruptedException {
Mono<Boolean> result = reactiveValueOps.set("129", new Employee("129", "John", "Programming"), Duration.ofSeconds(1));
Mono<Employee> fetchedEmployee = reactiveValueOps.get("129");
StepVerifier.create(result)
.expectNext(true)
.verifyComplete();
Thread.sleep(2000L);
StepVerifier.create(fetchedEmployee)
.expectNextCount(0L)
.verifyComplete();
}
}

View File

@ -31,7 +31,7 @@ public class RedisMessageListenerIntegrationTest {
@BeforeClass @BeforeClass
public static void startRedisServer() throws IOException { public static void startRedisServer() throws IOException {
redisServer = new redis.embedded.RedisServer(6379); redisServer = new redis.embedded.RedisServer(6380);
redisServer.start(); redisServer.start();
} }

View File

@ -32,7 +32,7 @@ public class StudentRepositoryIntegrationTest {
@BeforeClass @BeforeClass
public static void startRedisServer() throws IOException { public static void startRedisServer() throws IOException {
redisServer = new redis.embedded.RedisServer(6379); redisServer = new redis.embedded.RedisServer(6380);
redisServer.start(); redisServer.start();
} }

View File

@ -451,6 +451,7 @@
<module>spring-5</module> <module>spring-5</module>
<module>spring-5-data-reactive</module> <module>spring-5-data-reactive</module>
<module>spring-5-reactive</module> <module>spring-5-reactive</module>
<module>spring-data-5-reactive/spring-5-data-reactive-redis</module>
<module>spring-5-reactive-security</module> <module>spring-5-reactive-security</module>
<module>spring-5-reactive-client</module> <module>spring-5-reactive-client</module>
<module>spring-5-mvc</module> <module>spring-5-mvc</module>