Skip to content

Commit feb534f

Browse files
mp911dechristophstrobl
authored andcommitted
Introduce JedisClientConfigBuilderCustomizer to support client config customization.
We now support customization of Jedis' JedisClientConfig that is used for various client configurations for setting extended properties that Spring Data Redis doesn't configure itself. Closes: #3007 Original Pull Request: #3014
1 parent cf42be1 commit feb534f

File tree

5 files changed

+110
-3
lines changed

5 files changed

+110
-3
lines changed

src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
*/
3535
class DefaultJedisClientConfiguration implements JedisClientConfiguration {
3636

37+
private final Optional<JedisClientConfigBuilderCustomizer> customizer;
3738
private final boolean useSsl;
3839
private final Optional<SSLSocketFactory> sslSocketFactory;
3940
private final Optional<SSLParameters> sslParameters;
@@ -44,11 +45,13 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
4445
private final Duration readTimeout;
4546
private final Duration connectTimeout;
4647

47-
DefaultJedisClientConfiguration(boolean useSsl, @Nullable SSLSocketFactory sslSocketFactory,
48+
DefaultJedisClientConfiguration(@Nullable JedisClientConfigBuilderCustomizer customizer, boolean useSsl,
49+
@Nullable SSLSocketFactory sslSocketFactory,
4850
@Nullable SSLParameters sslParameters, @Nullable HostnameVerifier hostnameVerifier, boolean usePooling,
4951
@Nullable GenericObjectPoolConfig poolConfig, @Nullable String clientName, Duration readTimeout,
5052
Duration connectTimeout) {
5153

54+
this.customizer = Optional.ofNullable(customizer);
5255
this.useSsl = useSsl;
5356
this.sslSocketFactory = Optional.ofNullable(sslSocketFactory);
5457
this.sslParameters = Optional.ofNullable(sslParameters);
@@ -60,6 +63,11 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
6063
this.connectTimeout = connectTimeout;
6164
}
6265

66+
@Override
67+
public Optional<JedisClientConfigBuilderCustomizer> getCustomizer() {
68+
return customizer;
69+
}
70+
6371
@Override
6472
public boolean isUseSsl() {
6573
return useSsl;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2024 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+
* https://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 org.springframework.data.redis.connection.jedis;
17+
18+
import redis.clients.jedis.DefaultJedisClientConfig;
19+
20+
/**
21+
* Strategy interface for customizing {@link DefaultJedisClientConfig.Builder JedisClientConfig}. Any ClientConfig will
22+
* be used to call this interface implementation so you can set the protocol, client name, etc. after Spring has applies
23+
* its defaults.
24+
*
25+
* @author Mark Paluch
26+
* @since 3.4
27+
* @see redis.clients.jedis.DefaultJedisClientConfig.Builder
28+
*/
29+
@FunctionalInterface
30+
public interface JedisClientConfigBuilderCustomizer {
31+
32+
/**
33+
* Customize the {@link DefaultJedisClientConfig.Builder}.
34+
*
35+
* @param builder the builder to customize.
36+
*/
37+
void customize(DefaultJedisClientConfig.Builder builder);
38+
39+
}

src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@
5858
*/
5959
public interface JedisClientConfiguration {
6060

61+
/**
62+
* @return the optional {@link JedisClientConfigBuilderCustomizer}.
63+
* @since 3.4
64+
*/
65+
Optional<JedisClientConfigBuilderCustomizer> getCustomizer();
66+
6167
/**
6268
* @return {@literal true} to use SSL, {@literal false} to use unencrypted connections.
6369
*/
@@ -119,6 +125,8 @@ static JedisClientConfigurationBuilder builder() {
119125
/**
120126
* Creates a default {@link JedisClientConfiguration}.
121127
* <dl>
128+
* <dt>Customizer</dt>
129+
* <dd>none</dd>
122130
* <dt>SSL enabled</dt>
123131
* <dd>no</dd>
124132
* <dt>Pooling enabled</dt>
@@ -142,6 +150,15 @@ static JedisClientConfiguration defaultConfiguration() {
142150
*/
143151
interface JedisClientConfigurationBuilder {
144152

153+
/**
154+
* Configure a {@link JedisClientConfigBuilderCustomizer} to configure
155+
* {@link redis.clients.jedis.JedisClientConfig}.
156+
*
157+
* @return {@link JedisClientConfigurationBuilder}.
158+
* @since 3.4
159+
*/
160+
JedisClientConfigurationBuilder customize(JedisClientConfigBuilderCustomizer customizer);
161+
145162
/**
146163
* Enable SSL connections.
147164
*
@@ -269,6 +286,7 @@ interface JedisSslClientConfigurationBuilder {
269286
class DefaultJedisClientConfigurationBuilder implements JedisClientConfigurationBuilder,
270287
JedisPoolingClientConfigurationBuilder, JedisSslClientConfigurationBuilder {
271288

289+
private @Nullable JedisClientConfigBuilderCustomizer customizer;
272290
private boolean useSsl;
273291
private @Nullable SSLSocketFactory sslSocketFactory;
274292
private @Nullable SSLParameters sslParameters;
@@ -281,6 +299,15 @@ class DefaultJedisClientConfigurationBuilder implements JedisClientConfiguration
281299

282300
private DefaultJedisClientConfigurationBuilder() {}
283301

302+
@Override
303+
public JedisClientConfigurationBuilder customize(JedisClientConfigBuilderCustomizer customizer) {
304+
305+
Assert.notNull(customizer, "JedisClientConfigBuilderCustomizer must not be null");
306+
307+
this.customizer = customizer;
308+
return this;
309+
}
310+
284311
@Override
285312
public JedisSslClientConfigurationBuilder useSsl() {
286313

@@ -366,8 +393,8 @@ public JedisClientConfigurationBuilder connectTimeout(Duration connectTimeout) {
366393
@Override
367394
public JedisClientConfiguration build() {
368395

369-
return new DefaultJedisClientConfiguration(useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling,
370-
poolConfig, clientName, readTimeout, connectTimeout);
396+
return new DefaultJedisClientConfiguration(customizer, useSsl, sslSocketFactory, sslParameters, hostnameVerifier,
397+
usePooling, poolConfig, clientName, readTimeout, connectTimeout);
371398
}
372399
}
373400

src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,8 @@ private JedisClientConfig createClientConfig(int database, @Nullable String user
711711
this.clientConfiguration.getSslParameters().ifPresent(builder::sslParameters);
712712
}
713713

714+
this.clientConfiguration.getCustomizer().ifPresent(customizer -> customizer.customize(builder));
715+
714716
return builder.build();
715717
}
716718

@@ -1087,6 +1089,11 @@ public static JedisClientConfiguration create(GenericObjectPoolConfig jedisPoolC
10871089
return configuration;
10881090
}
10891091

1092+
@Override
1093+
public Optional<JedisClientConfigBuilderCustomizer> getCustomizer() {
1094+
return Optional.empty();
1095+
}
1096+
10901097
@Override
10911098
public boolean isUseSsl() {
10921099
return useSsl;

src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
import static org.assertj.core.api.Assertions.*;
1919
import static org.mockito.Mockito.*;
2020

21+
import redis.clients.jedis.DefaultJedisClientConfig;
2122
import redis.clients.jedis.JedisClientConfig;
2223
import redis.clients.jedis.JedisCluster;
2324
import redis.clients.jedis.JedisPoolConfig;
25+
import redis.clients.jedis.RedisProtocol;
2426

2527
import java.io.IOException;
2628
import java.security.NoSuchAlgorithmException;
@@ -338,6 +340,30 @@ void afterPropertiesTriggersConnectionInitialization() {
338340
assertThat(connectionFactory.isRunning()).isTrue();
339341
}
340342

343+
@Test // GH-3007
344+
void clientConfigurationAppliesCustomizer() {
345+
346+
JedisClientConfig resp3Config = apply(
347+
JedisClientConfiguration.builder().customize(DefaultJedisClientConfig.Builder::resp3).build());
348+
349+
assertThat(resp3Config.getRedisProtocol()).isEqualTo(RedisProtocol.RESP3);
350+
351+
JedisClientConfig resp2Config = apply(
352+
JedisClientConfiguration.builder().customize(it -> it.protocol(RedisProtocol.RESP2)).build());
353+
354+
assertThat(resp2Config.getRedisProtocol()).isEqualTo(RedisProtocol.RESP2);
355+
}
356+
357+
private static JedisClientConfig apply(JedisClientConfiguration configuration) {
358+
359+
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(new RedisStandaloneConfiguration(),
360+
configuration);
361+
connectionFactory.setEarlyStartup(false);
362+
connectionFactory.afterPropertiesSet();
363+
364+
return (JedisClientConfig) ReflectionTestUtils.getField(connectionFactory, "clientConfig");
365+
}
366+
341367
@Test // GH-2866
342368
void earlyStartupDoesNotStartConnectionFactory() {
343369

0 commit comments

Comments
 (0)