Skip to content

Commit

Permalink
Introduce JedisClientConfigBuilderCustomizer to support client conf…
Browse files Browse the repository at this point in the history
…ig 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
  • Loading branch information
mp911de authored and christophstrobl committed Oct 10, 2024
1 parent cf42be1 commit feb534f
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
*/
class DefaultJedisClientConfiguration implements JedisClientConfiguration {

private final Optional<JedisClientConfigBuilderCustomizer> customizer;
private final boolean useSsl;
private final Optional<SSLSocketFactory> sslSocketFactory;
private final Optional<SSLParameters> sslParameters;
Expand All @@ -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);
Expand All @@ -60,6 +63,11 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
this.connectTimeout = connectTimeout;
}

@Override
public Optional<JedisClientConfigBuilderCustomizer> getCustomizer() {
return customizer;
}

@Override
public boolean isUseSsl() {
return useSsl;
Expand Down
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
*/
public interface JedisClientConfiguration {

/**
* @return the optional {@link JedisClientConfigBuilderCustomizer}.
* @since 3.4
*/
Optional<JedisClientConfigBuilderCustomizer> getCustomizer();

/**
* @return {@literal true} to use SSL, {@literal false} to use unencrypted connections.
*/
Expand Down Expand Up @@ -119,6 +125,8 @@ static JedisClientConfigurationBuilder builder() {
/**
* Creates a default {@link JedisClientConfiguration}.
* <dl>
* <dt>Customizer</dt>
* <dd>none</dd>
* <dt>SSL enabled</dt>
* <dd>no</dd>
* <dt>Pooling enabled</dt>
Expand All @@ -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.
*
Expand Down Expand Up @@ -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;
Expand All @@ -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() {

Expand Down Expand Up @@ -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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -1087,6 +1089,11 @@ public static JedisClientConfiguration create(GenericObjectPoolConfig jedisPoolC
return configuration;
}

@Override
public Optional<JedisClientConfigBuilderCustomizer> getCustomizer() {
return Optional.empty();
}

@Override
public boolean isUseSsl() {
return useSsl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {

Expand Down

0 comments on commit feb534f

Please sign in to comment.