#299 - Migrate Redis examples to Lettuce.
We now use Lettuce API instead of Jedis to align with Boot's driver choice.
This commit is contained in:
@@ -74,7 +74,7 @@ redis/src $ ./redis-cli keys *
|
||||
|
||||
## Configuration ##
|
||||
|
||||
The below configuration uses [Jedis](https://github.com/xetorthio/jedis) to connect to Redis on its default port. Please note the usage of `@EnableRedisRepositories` to create `Repository` instances.
|
||||
The below configuration uses [Lettuce](https://github.com/lettuce-io/lettuce-core) to connect to Redis on its default port. Please note the usage of `@EnableRedisRepositories` to create `Repository` instances.
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
@@ -83,13 +83,13 @@ class AppConfig {
|
||||
|
||||
@Bean
|
||||
RedisConnectionFactory connectionFactory() {
|
||||
return new JedisConnectionFactory();
|
||||
return new LettuceConnectionFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
|
||||
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
|
||||
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
|
||||
return template;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,12 +18,13 @@ package example.springdata.redis.repositories;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRedisRepositories
|
||||
@@ -31,13 +32,13 @@ public class ApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
RedisConnectionFactory connectionFactory() {
|
||||
return new JedisConnectionFactory();
|
||||
return new LettuceConnectionFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
|
||||
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
|
||||
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
|
||||
return template;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class RedisSentinelApplicationConfig {
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
return new JedisConnectionFactory(sentinelConfig());
|
||||
return new LettuceConnectionFactory(sentinelConfig(), LettuceClientConfiguration.defaultConfiguration());
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.util.StopWatch;
|
||||
@@ -31,6 +32,7 @@ import org.springframework.util.StopWatch;
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisSentinelApplication {
|
||||
@@ -74,7 +76,7 @@ public class RedisSentinelApplication {
|
||||
}
|
||||
|
||||
public @Bean RedisConnectionFactory connectionFactory() {
|
||||
return new LettuceConnectionFactory(sentinelConfig());
|
||||
return new LettuceConnectionFactory(sentinelConfig(), LettuceClientConfiguration.defaultConfiguration());
|
||||
}
|
||||
|
||||
public @Bean RedisSentinelConfiguration sentinelConfig() {
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package example.springdata.redis.test.util;
|
||||
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
import io.lettuce.core.resource.DefaultClientResources;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Utility to keep track of a single {@link ClientResources} instance used from test rules to prevent costly
|
||||
* creation/disposal of threading resources.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class ManagedClientResources {
|
||||
|
||||
private static final ManagedClientResources instance = new ManagedClientResources();
|
||||
|
||||
private final AtomicReference<ClientResources> clientResources = new AtomicReference<>();
|
||||
|
||||
/**
|
||||
* Obtain a managed instance of {@link ClientResources}. Allocates an instance if {@link ManagedClientResources} was
|
||||
* not initialized already.
|
||||
*
|
||||
* @return the {@link ClientResources}.
|
||||
*/
|
||||
static ClientResources getClientResources() {
|
||||
|
||||
AtomicReference<ClientResources> ref = instance.clientResources;
|
||||
|
||||
ClientResources clientResources = ref.get();
|
||||
if (clientResources != null) {
|
||||
return clientResources;
|
||||
}
|
||||
|
||||
clientResources = DefaultClientResources.create();
|
||||
|
||||
if (ref.compareAndSet(null, clientResources)) {
|
||||
return clientResources;
|
||||
}
|
||||
|
||||
clientResources.shutdown(0, 0, TimeUnit.SECONDS);
|
||||
|
||||
return ref.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,12 @@
|
||||
*/
|
||||
package example.springdata.redis.test.util;
|
||||
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.api.StatefulRedisConnection;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.internal.AssumptionViolatedException;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
@@ -22,10 +28,9 @@ import org.junit.runners.model.Statement;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class RequiresRedisSentinel implements TestRule {
|
||||
|
||||
@@ -44,8 +49,8 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link RedisSentinelRule} for given {@link RedisSentinelConfiguration}.
|
||||
*
|
||||
* Create new {@link RequiresRedisSentinel} for given {@link RedisSentinelConfiguration}.
|
||||
*
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
@@ -54,8 +59,8 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link RedisSentinelRule} using default configuration.
|
||||
*
|
||||
* Create new {@link RequiresRedisSentinel} using default configuration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static RequiresRedisSentinel withDefaultConfig() {
|
||||
@@ -70,7 +75,7 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
|
||||
/**
|
||||
* Verifies all {@literal Sentinel} nodes are available.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RequiresRedisSentinel allActive() {
|
||||
@@ -81,7 +86,7 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
|
||||
/**
|
||||
* Verifies at least one {@literal Sentinel} node is available.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RequiresRedisSentinel oneActive() {
|
||||
@@ -93,7 +98,7 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
/**
|
||||
* Will only check {@link RedisSentinelConfiguration} configuration in case {@link RequiresRedisSentinel} is detected
|
||||
* on test method.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RequiresRedisSentinel dynamicModeSelection() {
|
||||
@@ -138,9 +143,9 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
|
||||
if (failed > 0) {
|
||||
if (SentinelsAvailable.ALL_ACTIVE.equals(verificationMode)) {
|
||||
throw new AssumptionViolatedException(String.format(
|
||||
"Expected all Redis Sentinels to respone but %s of %s did not responde", failed, sentinelConfig
|
||||
.getSentinels().size()));
|
||||
throw new AssumptionViolatedException(
|
||||
String.format("Expected all Redis Sentinels to respone but %s of %s did not responde", failed,
|
||||
sentinelConfig.getSentinels().size()));
|
||||
}
|
||||
|
||||
if (SentinelsAvailable.ONE_ACTIVE.equals(verificationMode) && sentinelConfig.getSentinels().size() - 1 < failed) {
|
||||
@@ -150,32 +155,23 @@ public class RequiresRedisSentinel implements TestRule {
|
||||
}
|
||||
|
||||
if (SentinelsAvailable.NONE_ACTIVE.equals(verificationMode) && failed != sentinelConfig.getSentinels().size()) {
|
||||
throw new AssumptionViolatedException(String.format(
|
||||
"Expected to have no sentinels online but found that %s are still alive.", (sentinelConfig.getSentinels()
|
||||
.size() - failed)));
|
||||
throw new AssumptionViolatedException(
|
||||
String.format("Expected to have no sentinels online but found that %s are still alive.",
|
||||
(sentinelConfig.getSentinels().size() - failed)));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAvailable(RedisNode node) {
|
||||
|
||||
Jedis jedis = null;
|
||||
RedisClient redisClient = RedisClient.create(ManagedClientResources.getClientResources(),
|
||||
RedisURI.create(node.getHost(), node.getPort()));
|
||||
|
||||
try {
|
||||
jedis = new Jedis(node.getHost(), node.getPort());
|
||||
jedis.connect();
|
||||
jedis.ping();
|
||||
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
|
||||
connection.sync().ping();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
} finally {
|
||||
|
||||
if (jedis != null) {
|
||||
try {
|
||||
jedis.disconnect();
|
||||
jedis.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
redisClient.shutdown(Duration.ZERO, Duration.ZERO);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
*/
|
||||
package example.springdata.redis.test.util;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.api.StatefulRedisConnection;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.AssumptionViolatedException;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConverters;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConverters;
|
||||
import org.springframework.data.util.Version;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -107,16 +110,22 @@ public class RequiresRedisServer extends ExternalResource {
|
||||
return;
|
||||
}
|
||||
|
||||
try (Jedis jedis = new Jedis(host, port)) {
|
||||
RedisClient redisClient = RedisClient.create(ManagedClientResources.getClientResources(),
|
||||
RedisURI.create(host, port));
|
||||
|
||||
String infoServer = jedis.info("server");
|
||||
String redisVersion = JedisConverters.stringToProps().convert(infoServer).getProperty("redis_version");
|
||||
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
|
||||
|
||||
String infoServer = connection.sync().info("server");
|
||||
String redisVersion = LettuceConverters.stringToProps().convert(infoServer).getProperty("redis_version");
|
||||
Version runningVersion = Version.parse(redisVersion);
|
||||
|
||||
if (runningVersion.isLessThan(requiredVersion)) {
|
||||
throw new AssumptionViolatedException(String
|
||||
.format("This test requires Redis version %s but you run version %s", requiredVersion, runningVersion));
|
||||
}
|
||||
|
||||
} finally {
|
||||
redisClient.shutdown(Duration.ZERO, Duration.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user