diff --git a/src/main/asciidoc/reference/reactive-redis.adoc b/src/main/asciidoc/reference/reactive-redis.adoc index 47277eb97..557a01f38 100644 --- a/src/main/asciidoc/reference/reactive-redis.adoc +++ b/src/main/asciidoc/reference/reactive-redis.adoc @@ -7,7 +7,7 @@ This section covers reactive Redis support and how to get started. You will find [[redis:reactive:requirements]] == Redis Requirements -Spring Redis requires Redis 2.6 or above and Java SE 8.0 or above. In terms of language bindings (or connectors), Spring Data Redis integrates with http://github.com/lettuce-io/lettuce-core[Lettuce] as the only reactive Java connector. Spring Data Redis uses https://projectreactor.io/[Project Reactor] as reactive composition library. +Spring Data Redis requires Redis 2.6 or above and Java SE 8.0 or above. In terms of language bindings (or connectors), Spring Data Redis currently integrates with http://github.com/lettuce-io/lettuce-core[Lettuce] as the only reactive Java connector. https://projectreactor.io/[Project Reactor] is used as reactive composition library. [[redis:reactive:connectors]] == Connecting to Redis using a reactive driver @@ -17,13 +17,13 @@ One of the first tasks when using Redis and Spring is to connect to the store th [[redis:reactive:connectors:operation-modes]] === Redis Operation Modes -Redis can be run as Standalone server, with <> or in <> mode. +Redis can be run as standalone server, with <> or in <> mode. http://github.com/lettuce-io/lettuce-core[Lettuce] supports all above mentioned connection types. [[redis:reactive:connectors:connection]] === ReactiveRedisConnection and ReactiveRedisConnectionFactory -`ReactiveRedisConnection` provides the building block for Redis communication as it handles the communication with the Redis back-end. It also automatically translates the underlying connecting library exceptions to Spring's consistent DAO exception http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#dao-exceptions[hierarchy] so one can switch the connectors without any code changes as the operation semantics remain the same. +`ReactiveRedisConnection` provides the building block for Redis communication as it handles the communication with the Redis back-end. It also automatically translates the underlying driver exceptions to Spring's consistent DAO exception http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#dao-exceptions[hierarchy] so one can switch the connectors without any code changes as the operation semantics remain the same. Active ``ReactiveRedisConnection``s are created through `ReactiveRedisConnectionFactory`. In addition, the factories act as ``PersistenceExceptionTranslator``s, meaning once declared, they allow one to do transparent exception translation. For example, exception translation through the use of the `@Repository` annotation and AOP. For more information see the dedicated http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#orm-exception-translation[section] in Spring Framework documentation. @@ -34,45 +34,43 @@ The easiest way to work with a `ReactiveRedisConnectionFactory` is to configure [[redis:reactive:connectors:lettuce]] === Configuring Lettuce connector -https://github.com/lettuce-io/lettuce-core[Lettuce] is a http://netty.io/[netty]-based open-source connector supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package. +https://github.com/lettuce-io/lettuce-core[Lettuce] is supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package. -Its configuration is probably easy to guess: +Setting up `ReactiveRedisConnectionFactory` for Lettuce can be done as follows: [source,java] ---- @Bean -public ReactiveRedisConnectionFactory lettuceConnectionFactory() { +public ReactiveRedisConnectionFactory connectionFactory() { return new LettuceConnectionFactory("localhost", 6379); } ---- -A more sophisticated configuration could look like: +A more sophisticated configuration, including SSL and timeouts, using `LettuceClientConfigurationBuilder` might look like below: [source,java] ---- @Bean public ReactiveRedisConnectionFactory lettuceConnectionFactory() { - RedisStandaloneConfiguration standalone = new RedisStandaloneConfiguration("localhost", 6379); - LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .useSsl().and() .commandTimeout(Duration.ofSeconds(2)) .shutdownTimeout(Duration.ZERO) .build(); - return new LettuceConnectionFactory(standalone, clientConfig); + return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig); } ---- -There are also a few Lettuce-specific connection parameters that can be tweaked. See `LettuceClientConfiguration` for more details. +For more detailed client configuration tweaks have a look at `LettuceClientConfiguration`. [[redis:reactive:template]] == Working with Objects through ReactiveRedisTemplate Most users are likely to use `ReactiveRedisTemplate` and its corresponding package `org.springframework.data.redis.core` - the template is in fact the central class of the Redis module due to its rich feature set. The template offers a high-level abstraction for Redis interactions. While `ReactiveRedisConnection` offers low level methods that accept and return binary values (`ByteBuffer`), the template takes care of serialization and connection management, freeing the user from dealing with such details. -Moreover, the template provides operations views (following the grouping from Redis command http://redis.io/commands[reference]) that offer rich, generified interfaces for working against a certain type as described below: +Moreover, the template provides operation views (following the grouping from Redis command http://redis.io/commands[reference]) that offer rich, generified interfaces for working against a certain type as described below: .Operational views [width="80%",cols="<1,<2",options="header"] @@ -106,7 +104,7 @@ Moreover, the template provides operations views (following the grouping from Re Once configured, the template is thread-safe and can be reused across multiple instances. -Out of the box, `ReactiveRedisTemplate` uses a Java-based serializer for most of its operations. This means that any object written or read by the template will be serialized/deserialized through Java throug `RedisElementWriter` respective `RedisElementReader`. The serialization context is passed to the template upon construction, and the Redis module offers several implementations available in the `org.springframework.data.redis.serializer` package - see <> for more information. +Out of the box, `ReactiveRedisTemplate` uses a Java-based serializer for most of its operations. This means that any object written or read by the template will be serialized/deserialized through `RedisElementWriter` respective `RedisElementReader`. The serialization context is passed to the template upon construction, and the Redis module offers several implementations available in the `org.springframework.data.redis.serializer` package - see <> for more information. [source,java] ---- @@ -124,15 +122,36 @@ class RedisConfiguration { ---- public class Example { - // inject the actual template @Autowired private ReactiveRedisTemplate template; - public Mono addLink(String userId, URL url) { return template.opsForList().leftPush(userId, url.toExternalForm()); } } ---- +== Reactive Scripting + +Executing Redis scripts via the reactive infrastructure can be done using the `ReactiveScriptExecutor` accessed best via `ReactiveRedisTemplate`. + +[source,java] +---- +public class Example { + + @Autowired + private ReactiveRedisTemplate template; + + public Flux theAnswerToLife() { + + DefaultRedisScript script = new DefaultRedisScript<>(); + script.setLocation(new ClassPathResource("META-INF/scripts/42.lua")); + script.setResultType(Long.class); + + return reactiveTemplate.execute(script); + } +} +---- + +Please refer to the <> for more details on scripting commands. diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java b/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java index 1b4d168e0..61f8a973f 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveRedisTemplate.java @@ -102,7 +102,6 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations implements ReactiveRedisOperations connection.keyCommands().exists(rawKey(key))); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#type(java.lang.Object) */ @Override @@ -220,7 +221,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations connection.keyCommands().type(rawKey(key))); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#keys(java.lang.Object) */ @Override @@ -233,7 +235,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations connection.keyCommands().randomKey()).map(this::readKey); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#rename(java.lang.Object, java.lang.Object) */ @Override @@ -253,7 +257,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations connection.keyCommands().rename(rawKey(oldKey), rawKey(newKey))); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#renameIfAbsent(java.lang.Object, java.lang.Object) */ @Override @@ -265,7 +270,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations connection.keyCommands().renameNX(rawKey(oldKey), rawKey(newKey))); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#delete(java.lang.Object[]) */ @Override @@ -284,7 +290,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations listOfKeys.flatMap(rawKeys -> connection.keyCommands().mDel(rawKeys))); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#delete(org.reactivestreams.Publisher) */ @Override @@ -297,7 +304,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations connection.keyCommands().pExpire(rawKey(key), timeout)); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#expireAt(java.lang.Object, java.time.Instant) */ @Override @@ -331,7 +340,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations connection.keyCommands().pExpireAt(rawKey(key), expireAt)); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#persist(java.lang.Object) */ @Override @@ -342,7 +352,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations connection.keyCommands().persist(rawKey(key))); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#getExpire(java.lang.Object) */ @Override @@ -364,7 +375,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHash() */ @Override @@ -459,7 +474,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForHyperLogLog() */ @Override @@ -476,7 +493,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForList() */ @Override @@ -493,7 +512,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForSet() */ @Override @@ -509,7 +530,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForValue() */ @Override @@ -525,7 +548,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#opsForZSet() */ @Override @@ -541,7 +566,8 @@ public class ReactiveRedisTemplate implements ReactiveRedisOperations implements ReactiveRedisOperations(this, serializationContext); } - /* (non-Javadoc) + /* + * (non-Javadoc) * @see org.springframework.data.redis.core.ReactiveRedisOperations#serialization() */ @Override