Skip to content

Commit 5760555

Browse files
committed
spring-projects#299 - Migrate Redis examples to Lettuce.
We now use Lettuce API instead of Jedis to align with Boot's driver choice.
1 parent ffc33fc commit 5760555

File tree

8 files changed

+116
-46
lines changed

8 files changed

+116
-46
lines changed

redis/repositories/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ redis/src $ ./redis-cli keys *
7474

7575
## Configuration ##
7676

77-
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.
77+
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.
7878

7979
```java
8080
@Configuration
@@ -83,13 +83,13 @@ class AppConfig {
8383

8484
@Bean
8585
RedisConnectionFactory connectionFactory() {
86-
return new JedisConnectionFactory();
86+
return new LettuceConnectionFactory();
8787
}
8888

8989
@Bean
9090
RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
9191

92-
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
92+
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
9393
template.setConnectionFactory(connectionFactory);
9494

9595
return template;

redis/repositories/src/main/java/example/springdata/redis/repositories/ApplicationConfiguration.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 the original author or authors.
2+
* Copyright 2016-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,26 +18,27 @@
1818
import org.springframework.context.annotation.Bean;
1919
import org.springframework.context.annotation.Configuration;
2020
import org.springframework.data.redis.connection.RedisConnectionFactory;
21-
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
21+
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
2222
import org.springframework.data.redis.core.RedisTemplate;
2323
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
2424

2525
/**
2626
* @author Christoph Strobl
27+
* @author Mark Paluch
2728
*/
2829
@Configuration
2930
@EnableRedisRepositories
3031
public class ApplicationConfiguration {
3132

3233
@Bean
3334
RedisConnectionFactory connectionFactory() {
34-
return new JedisConnectionFactory();
35+
return new LettuceConnectionFactory();
3536
}
3637

3738
@Bean
3839
RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {
3940

40-
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
41+
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
4142
template.setConnectionFactory(connectionFactory);
4243

4344
return template;

redis/sentinel/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class RedisSentinelApplicationConfig {
1515

1616
@Bean
1717
public RedisConnectionFactory connectionFactory() {
18-
return new JedisConnectionFactory(sentinelConfig());
18+
return new LettuceConnectionFactory(sentinelConfig(), LettuceClientConfiguration.defaultConfiguration());
1919
}
2020

2121
@Bean

redis/sentinel/src/main/java/example/springdata/redis/sentinel/RedisSentinelApplication.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424
import org.springframework.context.annotation.Configuration;
2525
import org.springframework.data.redis.connection.RedisConnectionFactory;
2626
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
27+
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
2728
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
2829
import org.springframework.data.redis.core.StringRedisTemplate;
2930
import org.springframework.util.StopWatch;
3031

3132
/**
3233
* @author Christoph Strobl
3334
* @author Oliver Gierke
35+
* @author Mark Paluch
3436
*/
3537
@Configuration
3638
public class RedisSentinelApplication {
@@ -74,7 +76,7 @@ public static void main(String[] args) throws Exception {
7476
}
7577

7678
public @Bean RedisConnectionFactory connectionFactory() {
77-
return new LettuceConnectionFactory(sentinelConfig());
79+
return new LettuceConnectionFactory(sentinelConfig(), LettuceClientConfiguration.defaultConfiguration());
7880
}
7981

8082
public @Bean RedisSentinelConfiguration sentinelConfig() {

redis/util/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
</dependency>
2121

2222
<dependency>
23-
<groupId>redis.clients</groupId>
24-
<artifactId>jedis</artifactId>
23+
<groupId>io.lettuce</groupId>
24+
<artifactId>lettuce-core</artifactId>
2525
</dependency>
2626

2727
<dependency>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.redis.test.util;
17+
18+
import io.lettuce.core.resource.ClientResources;
19+
import io.lettuce.core.resource.DefaultClientResources;
20+
21+
import java.util.concurrent.TimeUnit;
22+
import java.util.concurrent.atomic.AtomicReference;
23+
24+
/**
25+
* Utility to keep track of a single {@link ClientResources} instance used from test rules to prevent costly
26+
* creation/disposal of threading resources.
27+
*
28+
* @author Mark Paluch
29+
*/
30+
class ManagedClientResources {
31+
32+
private static final ManagedClientResources instance = new ManagedClientResources();
33+
34+
private final AtomicReference<ClientResources> clientResources = new AtomicReference<>();
35+
36+
/**
37+
* Obtain a managed instance of {@link ClientResources}. Allocates an instance if {@link ManagedClientResources} was
38+
* not initialized already.
39+
*
40+
* @return the {@link ClientResources}.
41+
*/
42+
static ClientResources getClientResources() {
43+
44+
AtomicReference<ClientResources> ref = instance.clientResources;
45+
46+
ClientResources clientResources = ref.get();
47+
if (clientResources != null) {
48+
return clientResources;
49+
}
50+
51+
clientResources = DefaultClientResources.create();
52+
53+
if (ref.compareAndSet(null, clientResources)) {
54+
return clientResources;
55+
}
56+
57+
clientResources.shutdown(0, 0, TimeUnit.SECONDS);
58+
59+
return ref.get();
60+
}
61+
62+
}

redis/util/src/main/java/example/springdata/redis/test/util/RequiresRedisSentinel.java

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,17 +15,22 @@
1515
*/
1616
package example.springdata.redis.test.util;
1717

18+
import io.lettuce.core.RedisClient;
19+
import io.lettuce.core.RedisURI;
20+
import io.lettuce.core.api.StatefulRedisConnection;
21+
22+
import java.time.Duration;
23+
1824
import org.junit.internal.AssumptionViolatedException;
1925
import org.junit.rules.TestRule;
2026
import org.junit.runner.Description;
2127
import org.junit.runners.model.Statement;
2228
import org.springframework.data.redis.connection.RedisNode;
2329
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
2430

25-
import redis.clients.jedis.Jedis;
26-
2731
/**
2832
* @author Christoph Strobl
33+
* @author Mark Paluch
2934
*/
3035
public class RequiresRedisSentinel implements TestRule {
3136

@@ -44,8 +49,8 @@ protected RequiresRedisSentinel(RedisSentinelConfiguration config) {
4449
}
4550

4651
/**
47-
* Create new {@link RedisSentinelRule} for given {@link RedisSentinelConfiguration}.
48-
*
52+
* Create new {@link RequiresRedisSentinel} for given {@link RedisSentinelConfiguration}.
53+
*
4954
* @param config
5055
* @return
5156
*/
@@ -54,8 +59,8 @@ public static RequiresRedisSentinel forConfig(RedisSentinelConfiguration config)
5459
}
5560

5661
/**
57-
* Create new {@link RedisSentinelRule} using default configuration.
58-
*
62+
* Create new {@link RequiresRedisSentinel} using default configuration.
63+
*
5964
* @return
6065
*/
6166
public static RequiresRedisSentinel withDefaultConfig() {
@@ -70,7 +75,7 @@ public RequiresRedisSentinel sentinelsDisabled() {
7075

7176
/**
7277
* Verifies all {@literal Sentinel} nodes are available.
73-
*
78+
*
7479
* @return
7580
*/
7681
public RequiresRedisSentinel allActive() {
@@ -81,7 +86,7 @@ public RequiresRedisSentinel allActive() {
8186

8287
/**
8388
* Verifies at least one {@literal Sentinel} node is available.
84-
*
89+
*
8590
* @return
8691
*/
8792
public RequiresRedisSentinel oneActive() {
@@ -93,7 +98,7 @@ public RequiresRedisSentinel oneActive() {
9398
/**
9499
* Will only check {@link RedisSentinelConfiguration} configuration in case {@link RequiresRedisSentinel} is detected
95100
* on test method.
96-
*
101+
*
97102
* @return
98103
*/
99104
public RequiresRedisSentinel dynamicModeSelection() {
@@ -138,9 +143,9 @@ private void verify(SentinelsAvailable verificationMode) {
138143

139144
if (failed > 0) {
140145
if (SentinelsAvailable.ALL_ACTIVE.equals(verificationMode)) {
141-
throw new AssumptionViolatedException(String.format(
142-
"Expected all Redis Sentinels to respone but %s of %s did not responde", failed, sentinelConfig
143-
.getSentinels().size()));
146+
throw new AssumptionViolatedException(
147+
String.format("Expected all Redis Sentinels to respone but %s of %s did not responde", failed,
148+
sentinelConfig.getSentinels().size()));
144149
}
145150

146151
if (SentinelsAvailable.ONE_ACTIVE.equals(verificationMode) && sentinelConfig.getSentinels().size() - 1 < failed) {
@@ -150,32 +155,23 @@ private void verify(SentinelsAvailable verificationMode) {
150155
}
151156

152157
if (SentinelsAvailable.NONE_ACTIVE.equals(verificationMode) && failed != sentinelConfig.getSentinels().size()) {
153-
throw new AssumptionViolatedException(String.format(
154-
"Expected to have no sentinels online but found that %s are still alive.", (sentinelConfig.getSentinels()
155-
.size() - failed)));
158+
throw new AssumptionViolatedException(
159+
String.format("Expected to have no sentinels online but found that %s are still alive.",
160+
(sentinelConfig.getSentinels().size() - failed)));
156161
}
157162
}
158163

159164
private boolean isAvailable(RedisNode node) {
160165

161-
Jedis jedis = null;
166+
RedisClient redisClient = RedisClient.create(ManagedClientResources.getClientResources(),
167+
RedisURI.create(node.getHost(), node.getPort()));
162168

163-
try {
164-
jedis = new Jedis(node.getHost(), node.getPort());
165-
jedis.connect();
166-
jedis.ping();
169+
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
170+
connection.sync().ping();
167171
} catch (Exception e) {
168172
return false;
169173
} finally {
170-
171-
if (jedis != null) {
172-
try {
173-
jedis.disconnect();
174-
jedis.close();
175-
} catch (Exception e) {
176-
e.printStackTrace();
177-
}
178-
}
174+
redisClient.shutdown(Duration.ZERO, Duration.ZERO);
179175
}
180176

181177
return true;

redis/util/src/main/java/example/springdata/redis/test/util/RequiresRedisServer.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
*/
1616
package example.springdata.redis.test.util;
1717

18-
import redis.clients.jedis.Jedis;
18+
import io.lettuce.core.RedisClient;
19+
import io.lettuce.core.RedisURI;
20+
import io.lettuce.core.api.StatefulRedisConnection;
1921

2022
import java.net.InetSocketAddress;
2123
import java.net.Socket;
24+
import java.time.Duration;
2225

2326
import org.junit.AssumptionViolatedException;
2427
import org.junit.rules.ExternalResource;
25-
import org.springframework.data.redis.connection.jedis.JedisConverters;
28+
import org.springframework.data.redis.connection.lettuce.LettuceConverters;
2629
import org.springframework.data.util.Version;
2730
import org.springframework.util.Assert;
2831
import org.springframework.util.StringUtils;
@@ -107,16 +110,22 @@ protected void before() throws Throwable {
107110
return;
108111
}
109112

110-
try (Jedis jedis = new Jedis(host, port)) {
113+
RedisClient redisClient = RedisClient.create(ManagedClientResources.getClientResources(),
114+
RedisURI.create(host, port));
111115

112-
String infoServer = jedis.info("server");
113-
String redisVersion = JedisConverters.stringToProps().convert(infoServer).getProperty("redis_version");
116+
try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
117+
118+
String infoServer = connection.sync().info("server");
119+
String redisVersion = LettuceConverters.stringToProps().convert(infoServer).getProperty("redis_version");
114120
Version runningVersion = Version.parse(redisVersion);
115121

116122
if (runningVersion.isLessThan(requiredVersion)) {
117123
throw new AssumptionViolatedException(String
118124
.format("This test requires Redis version %s but you run version %s", requiredVersion, runningVersion));
119125
}
126+
127+
} finally {
128+
redisClient.shutdown(Duration.ZERO, Duration.ZERO);
120129
}
121130
}
122131
}

0 commit comments

Comments
 (0)