diff --git a/pom.xml b/pom.xml
index b20be3b3a5..0b827babcd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-redis
- 3.4.0-SNAPSHOT
+ 3.4.0-GH-3007-SNAPSHOT
Spring Data Redis
Spring Data module for Redis
diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java
index 50fd68211e..683c0ec55a 100644
--- a/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java
+++ b/src/main/java/org/springframework/data/redis/connection/jedis/DefaultJedisClientConfiguration.java
@@ -34,6 +34,7 @@
*/
class DefaultJedisClientConfiguration implements JedisClientConfiguration {
+ private final Optional customizer;
private final boolean useSsl;
private final Optional sslSocketFactory;
private final Optional sslParameters;
@@ -44,11 +45,13 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
private final Duration readTimeout;
private final Duration connectTimeout;
- DefaultJedisClientConfiguration(boolean useSsl, @Nullable SSLSocketFactory sslSocketFactory,
+ DefaultJedisClientConfiguration(@Nullable JedisClientConfigBuilderCustomizer customizer, boolean useSsl,
+ @Nullable SSLSocketFactory sslSocketFactory,
@Nullable SSLParameters sslParameters, @Nullable HostnameVerifier hostnameVerifier, boolean usePooling,
@Nullable GenericObjectPoolConfig poolConfig, @Nullable String clientName, Duration readTimeout,
Duration connectTimeout) {
+ this.customizer = Optional.ofNullable(customizer);
this.useSsl = useSsl;
this.sslSocketFactory = Optional.ofNullable(sslSocketFactory);
this.sslParameters = Optional.ofNullable(sslParameters);
@@ -60,6 +63,11 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
this.connectTimeout = connectTimeout;
}
+ @Override
+ public Optional getCustomizer() {
+ return customizer;
+ }
+
@Override
public boolean isUseSsl() {
return useSsl;
diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfigBuilderCustomizer.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfigBuilderCustomizer.java
new file mode 100644
index 0000000000..8f508c374f
--- /dev/null
+++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfigBuilderCustomizer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2024 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
+ *
+ * https://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 org.springframework.data.redis.connection.jedis;
+
+import redis.clients.jedis.DefaultJedisClientConfig;
+
+/**
+ * Strategy interface for customizing {@link DefaultJedisClientConfig.Builder JedisClientConfig}. Any ClientConfig will
+ * be used to call this interface implementation so you can set the protocol, client name, etc. after Spring has applies
+ * its defaults.
+ *
+ * @author Mark Paluch
+ * @since 3.4
+ * @see redis.clients.jedis.DefaultJedisClientConfig.Builder
+ */
+@FunctionalInterface
+public interface JedisClientConfigBuilderCustomizer {
+
+ /**
+ * Customize the {@link DefaultJedisClientConfig.Builder}.
+ *
+ * @param builder the builder to customize.
+ */
+ void customize(DefaultJedisClientConfig.Builder builder);
+
+}
diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java
index 1c9628db0c..b6b9a22467 100644
--- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java
+++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisClientConfiguration.java
@@ -58,6 +58,12 @@
*/
public interface JedisClientConfiguration {
+ /**
+ * @return the optional {@link JedisClientConfigBuilderCustomizer}.
+ * @since 3.4
+ */
+ Optional getCustomizer();
+
/**
* @return {@literal true} to use SSL, {@literal false} to use unencrypted connections.
*/
@@ -119,6 +125,8 @@ static JedisClientConfigurationBuilder builder() {
/**
* Creates a default {@link JedisClientConfiguration}.
*
+ * - Customizer
+ * - none
* - SSL enabled
* - no
* - Pooling enabled
@@ -142,6 +150,15 @@ static JedisClientConfiguration defaultConfiguration() {
*/
interface JedisClientConfigurationBuilder {
+ /**
+ * Configure a {@link JedisClientConfigBuilderCustomizer} to configure
+ * {@link redis.clients.jedis.JedisClientConfig}.
+ *
+ * @return {@link JedisClientConfigurationBuilder}.
+ * @since 3.4
+ */
+ JedisClientConfigurationBuilder customize(JedisClientConfigBuilderCustomizer customizer);
+
/**
* Enable SSL connections.
*
@@ -269,6 +286,7 @@ interface JedisSslClientConfigurationBuilder {
class DefaultJedisClientConfigurationBuilder implements JedisClientConfigurationBuilder,
JedisPoolingClientConfigurationBuilder, JedisSslClientConfigurationBuilder {
+ private @Nullable JedisClientConfigBuilderCustomizer customizer;
private boolean useSsl;
private @Nullable SSLSocketFactory sslSocketFactory;
private @Nullable SSLParameters sslParameters;
@@ -281,6 +299,15 @@ class DefaultJedisClientConfigurationBuilder implements JedisClientConfiguration
private DefaultJedisClientConfigurationBuilder() {}
+ @Override
+ public JedisClientConfigurationBuilder customize(JedisClientConfigBuilderCustomizer customizer) {
+
+ Assert.notNull(customizer, "JedisClientConfigBuilderCustomizer must not be null");
+
+ this.customizer = customizer;
+ return this;
+ }
+
@Override
public JedisSslClientConfigurationBuilder useSsl() {
@@ -366,8 +393,8 @@ public JedisClientConfigurationBuilder connectTimeout(Duration connectTimeout) {
@Override
public JedisClientConfiguration build() {
- return new DefaultJedisClientConfiguration(useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling,
- poolConfig, clientName, readTimeout, connectTimeout);
+ return new DefaultJedisClientConfiguration(customizer, useSsl, sslSocketFactory, sslParameters, hostnameVerifier,
+ usePooling, poolConfig, clientName, readTimeout, connectTimeout);
}
}
diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java
index 21bd50df5e..c2ecc3e2cf 100644
--- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java
+++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.java
@@ -711,6 +711,8 @@ private JedisClientConfig createClientConfig(int database, @Nullable String user
this.clientConfiguration.getSslParameters().ifPresent(builder::sslParameters);
}
+ this.clientConfiguration.getCustomizer().ifPresent(customizer -> customizer.customize(builder));
+
return builder.build();
}
@@ -1087,6 +1089,11 @@ public static JedisClientConfiguration create(GenericObjectPoolConfig jedisPoolC
return configuration;
}
+ @Override
+ public Optional getCustomizer() {
+ return Optional.empty();
+ }
+
@Override
public boolean isUseSsl() {
return useSsl;
diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java
index f6e3f3f9e4..b553cf4415 100644
--- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionFactoryUnitTests.java
@@ -18,9 +18,11 @@
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
+import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
+import redis.clients.jedis.RedisProtocol;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
@@ -338,6 +340,30 @@ void afterPropertiesTriggersConnectionInitialization() {
assertThat(connectionFactory.isRunning()).isTrue();
}
+ @Test // GH-3007
+ void clientConfigurationAppliesCustomizer() {
+
+ JedisClientConfig resp3Config = apply(
+ JedisClientConfiguration.builder().customize(DefaultJedisClientConfig.Builder::resp3).build());
+
+ assertThat(resp3Config.getRedisProtocol()).isEqualTo(RedisProtocol.RESP3);
+
+ JedisClientConfig resp2Config = apply(
+ JedisClientConfiguration.builder().customize(it -> it.protocol(RedisProtocol.RESP2)).build());
+
+ assertThat(resp2Config.getRedisProtocol()).isEqualTo(RedisProtocol.RESP2);
+ }
+
+ private static JedisClientConfig apply(JedisClientConfiguration configuration) {
+
+ JedisConnectionFactory connectionFactory = new JedisConnectionFactory(new RedisStandaloneConfiguration(),
+ configuration);
+ connectionFactory.setEarlyStartup(false);
+ connectionFactory.afterPropertiesSet();
+
+ return (JedisClientConfig) ReflectionTestUtils.getField(connectionFactory, "clientConfig");
+ }
+
@Test // GH-2866
void earlyStartupDoesNotStartConnectionFactory() {