diff --git a/src/main/antora/modules/ROOT/pages/redis/connection-modes.adoc b/src/main/antora/modules/ROOT/pages/redis/connection-modes.adoc index e509a06fc..062eb33d0 100644 --- a/src/main/antora/modules/ROOT/pages/redis/connection-modes.adoc +++ b/src/main/antora/modules/ROOT/pages/redis/connection-modes.adoc @@ -96,7 +96,7 @@ public RedisConnectionFactory jedisConnectionFactory() { [TIP] ==== -`RedisSentinelConfiguration` can also be defined with a `PropertySource`, which lets you set the following properties: +`RedisSentinelConfiguration` can also be defined through `RedisSentinelConfiguration.of(PropertySource)`, which lets you pick up the following properties: .Configuration Properties * `spring.redis.sentinel.master`: name of the master node. @@ -164,7 +164,7 @@ public class AppConfig { [TIP] ==== -`RedisClusterConfiguration` can also be defined through `PropertySource` and has the following properties: +`RedisClusterConfiguration` can also be defined through `RedisClusterConfiguration.of(PropertySource)`, which lets you pick up the following properties: .Configuration Properties - `spring.redis.cluster.nodes`: Comma-delimited list of host:port pairs. diff --git a/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java b/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java index f2171043d..620e132d0 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisClusterConfiguration.java @@ -51,16 +51,14 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon private RedisPassword password = RedisPassword.none(); - private final Set clusterNodes; + private final Set clusterNodes = new LinkedHashSet<>(); private @Nullable String username = null; /** * Creates a new, default {@link RedisClusterConfiguration}. */ - public RedisClusterConfiguration() { - this(new MapPropertySource("RedisClusterConfiguration", Collections.emptyMap())); - } + public RedisClusterConfiguration() {} /** * Creates a new {@link RedisClusterConfiguration} for given {@link String hostPort} combinations. @@ -75,28 +73,31 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon * @param clusterNodes must not be {@literal null}. */ public RedisClusterConfiguration(Collection clusterNodes) { - this(new MapPropertySource("RedisClusterConfiguration", asMap(clusterNodes, -1))); + initialize(new MapPropertySource("RedisClusterConfiguration", asMap(clusterNodes, -1))); } /** * Creates a new {@link RedisClusterConfiguration} looking up configuration values from the given * {@link PropertySource}. * - *
-	 * 
+	 * 
 	 * spring.redis.cluster.nodes=127.0.0.1:23679,127.0.0.1:23680,127.0.0.1:23681
 	 * spring.redis.cluster.max-redirects=3
-	 * 
 	 * 
* * @param propertySource must not be {@literal null}. + * @deprecated since 3.3, use {@link RedisSentinelConfiguration#of(PropertySource)} instead. This constructor will be + * made private in the next major release. */ + @Deprecated(since = "3.3") public RedisClusterConfiguration(PropertySource propertySource) { + initialize(propertySource); + } + + private void initialize(PropertySource propertySource) { Assert.notNull(propertySource, "PropertySource must not be null"); - this.clusterNodes = new LinkedHashSet<>(); - if (propertySource.containsProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY)) { Object redisClusterNodes = propertySource.getProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY); @@ -109,6 +110,23 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon } } + /** + * Creates a new {@link RedisClusterConfiguration} looking up configuration values from the given + * {@link PropertySource}. + * + *
+	 * spring.redis.cluster.nodes=127.0.0.1:23679,127.0.0.1:23680,127.0.0.1:23681
+	 * spring.redis.cluster.max-redirects=3
+	 * 
+ * + * @param propertySource must not be {@literal null}. + * @return a new {@link RedisClusterConfiguration} configured from the given {@link PropertySource}. + * @since 3.3 + */ + public static RedisClusterConfiguration of(PropertySource propertySource) { + return new RedisClusterConfiguration(propertySource); + } + private void appendClusterNodes(Set hostAndPorts) { for (String hostAndPort : hostAndPorts) { diff --git a/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java b/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java index 583d539bb..24b390724 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisSentinelConfiguration.java @@ -15,7 +15,7 @@ */ package org.springframework.data.redis.connection; -import static org.springframework.util.StringUtils.commaDelimitedListToSet; +import static org.springframework.util.StringUtils.*; import java.util.Collections; import java.util.HashMap; @@ -32,8 +32,8 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** - * {@link RedisConfiguration Configuration} class used to set up a {@link RedisConnection} - * with {@link RedisConnectionFactory} for connecting to Redis Sentinel(s). + * {@link RedisConfiguration Configuration} class used to set up a {@link RedisConnection} with + * {@link RedisConnectionFactory} for connecting to Redis Sentinel(s). * Useful when setting up a highly available Redis environment. * * @author Christoph Strobl @@ -101,7 +101,10 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC * * @param propertySource must not be {@literal null}. * @since 1.5 + * @deprecated since 3.3, use {@link RedisSentinelConfiguration#of(PropertySource)} instead. This constructor will be + * made private in the next major release. */ + @Deprecated(since = "3.3") public RedisSentinelConfiguration(PropertySource propertySource) { Assert.notNull(propertySource, "PropertySource must not be null"); @@ -153,6 +156,17 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC } } + /** + * Construct a new {@link RedisSentinelConfiguration} from the given {@link PropertySource}. + * + * @param propertySource must not be {@literal null}. + * @return a new {@link RedisSentinelConfiguration} configured from the given {@link PropertySource}. + * @since 3.3 + */ + public static RedisSentinelConfiguration of(PropertySource propertySource) { + return new RedisSentinelConfiguration(propertySource); + } + /** * Set {@literal Sentinels} to connect to. * @@ -315,8 +329,7 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC return false; } - return this.database == that.database - && ObjectUtils.nullSafeEquals(this.master, that.master) + return this.database == that.database && ObjectUtils.nullSafeEquals(this.master, that.master) && ObjectUtils.nullSafeEquals(this.sentinels, that.sentinels) && ObjectUtils.nullSafeEquals(this.dataNodeUsername, that.dataNodeUsername) && ObjectUtils.nullSafeEquals(this.dataNodePassword, that.dataNodePassword) diff --git a/src/test/java/org/springframework/data/redis/connection/RedisClusterConfigurationUnitTests.java b/src/test/java/org/springframework/data/redis/connection/RedisClusterConfigurationUnitTests.java index 53fba16d7..6d969d087 100644 --- a/src/test/java/org/springframework/data/redis/connection/RedisClusterConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/RedisClusterConfigurationUnitTests.java @@ -83,8 +83,7 @@ class RedisClusterConfigurationUnitTests { @Test // DATAREDIS-315 void shouldThrowExceptionWhenListOfHostAndPortIsNull() { - assertThatIllegalArgumentException() - .isThrownBy(() -> new RedisClusterConfiguration(Collections.singleton(null))); + assertThatIllegalArgumentException().isThrownBy(() -> new RedisClusterConfiguration(Collections.singleton(null))); } @Test // DATAREDIS-315 @@ -97,13 +96,13 @@ class RedisClusterConfigurationUnitTests { @Test // DATAREDIS-315 void shouldThrowExceptionGivenNullPropertySource() { - assertThatIllegalArgumentException().isThrownBy(() -> new RedisClusterConfiguration((PropertySource) null)); + assertThatIllegalArgumentException().isThrownBy(() -> RedisClusterConfiguration.of((PropertySource) null)); } @Test // DATAREDIS-315 void shouldNotFailWhenGivenPropertySourceNotContainingRelevantProperties() { - RedisClusterConfiguration config = new RedisClusterConfiguration(new MockPropertySource()); + RedisClusterConfiguration config = RedisClusterConfiguration.of(new MockPropertySource()); assertThat(config.getMaxRedirects()).isNull(); assertThat(config.getClusterNodes().size()).isEqualTo(0); @@ -116,7 +115,7 @@ class RedisClusterConfigurationUnitTests { propertySource.setProperty("spring.redis.cluster.nodes", HOST_AND_PORT_1); propertySource.setProperty("spring.redis.cluster.max-redirects", "5"); - RedisClusterConfiguration config = new RedisClusterConfiguration(propertySource); + RedisClusterConfiguration config = RedisClusterConfiguration.of(propertySource); assertThat(config.getMaxRedirects()).isEqualTo(5); assertThat(config.getClusterNodes()).contains(new RedisNode("127.0.0.1", 123)); @@ -130,7 +129,7 @@ class RedisClusterConfigurationUnitTests { StringUtils.collectionToCommaDelimitedString(Arrays.asList(HOST_AND_PORT_1, HOST_AND_PORT_2, HOST_AND_PORT_3))); propertySource.setProperty("spring.redis.cluster.max-redirects", "5"); - RedisClusterConfiguration config = new RedisClusterConfiguration(propertySource); + RedisClusterConfiguration config = RedisClusterConfiguration.of(propertySource); assertThat(config.getMaxRedirects()).isEqualTo(5); assertThat(config.getClusterNodes()).contains(new RedisNode("127.0.0.1", 123), new RedisNode("localhost", 456), @@ -138,7 +137,7 @@ class RedisClusterConfigurationUnitTests { } @Test // GH-2360 - public void shouldBeCreatedCorrectlyGivenValidPropertySourceWithMultipleIPv6AddressesAndPorts() { + void shouldBeCreatedCorrectlyGivenValidPropertySourceWithMultipleIPv6AddressesAndPorts() { MockPropertySource propertySource = new MockPropertySource(); @@ -146,7 +145,7 @@ class RedisClusterConfigurationUnitTests { StringUtils.collectionToCommaDelimitedString(Arrays.asList(HOST_AND_PORT_4, HOST_AND_PORT_5))); propertySource.setProperty("spring.redis.cluster.max-redirects", 2); - RedisClusterConfiguration configuration = new RedisClusterConfiguration(propertySource); + RedisClusterConfiguration configuration = RedisClusterConfiguration.of(propertySource); assertThat(configuration.getMaxRedirects()).isEqualTo(2); assertThat(configuration.getClusterNodes()).contains(new RedisNode("fe80::a00:27ff:fe4b:ee48", 6379), diff --git a/src/test/java/org/springframework/data/redis/connection/RedisSentinelConfigurationUnitTests.java b/src/test/java/org/springframework/data/redis/connection/RedisSentinelConfigurationUnitTests.java index 055139d5a..2b38c0a75 100644 --- a/src/test/java/org/springframework/data/redis/connection/RedisSentinelConfigurationUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/RedisSentinelConfigurationUnitTests.java @@ -96,13 +96,13 @@ class RedisSentinelConfigurationUnitTests { @Test // DATAREDIS-372 void shouldThrowExceptionGivenNullPropertySource() { - assertThatIllegalArgumentException().isThrownBy(() -> new RedisSentinelConfiguration(null)); + assertThatIllegalArgumentException().isThrownBy(() -> RedisSentinelConfiguration.of(null)); } @Test // DATAREDIS-372 void shouldNotFailWhenGivenPropertySourceNotContainingRelevantProperties() { - RedisSentinelConfiguration config = new RedisSentinelConfiguration(new MockPropertySource()); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(new MockPropertySource()); assertThat(config.getMaster()).isNull(); assertThat(config.getSentinels()).isEmpty(); @@ -115,7 +115,7 @@ class RedisSentinelConfigurationUnitTests { propertySource.setProperty("spring.redis.sentinel.master", "myMaster"); propertySource.setProperty("spring.redis.sentinel.nodes", HOST_AND_PORT_1); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getMaster()).isNotNull(); assertThat(config.getMaster().getName()).isEqualTo("myMaster"); @@ -131,7 +131,7 @@ class RedisSentinelConfigurationUnitTests { propertySource.setProperty("spring.redis.sentinel.nodes", StringUtils.collectionToCommaDelimitedString(Arrays.asList(HOST_AND_PORT_1, HOST_AND_PORT_2, HOST_AND_PORT_3))); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getSentinels()).hasSize(3); assertThat(config.getSentinels()).contains(new RedisNode("127.0.0.1", 123), new RedisNode("localhost", 456), @@ -151,6 +151,7 @@ class RedisSentinelConfigurationUnitTests { @Test // GH-2218 void dataNodeUsernameDoesNotAffectSentinelUsername() { + RedisSentinelConfiguration configuration = new RedisSentinelConfiguration("myMaster", Collections.singleton(HOST_AND_PORT_1)); configuration.setUsername("data-admin"); @@ -168,7 +169,7 @@ class RedisSentinelConfigurationUnitTests { propertySource.setProperty("spring.redis.sentinel.nodes", HOST_AND_PORT_1); propertySource.setProperty("spring.redis.sentinel.password", "computer-says-no"); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getSentinelPassword()).isEqualTo(RedisPassword.of("computer-says-no")); assertThat(config.getSentinels()).hasSize(1).contains(new RedisNode("127.0.0.1", 123)); @@ -183,7 +184,7 @@ class RedisSentinelConfigurationUnitTests { propertySource.setProperty("spring.redis.sentinel.username", "sentinel-admin"); propertySource.setProperty("spring.redis.sentinel.password", "foo"); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getSentinelUsername()).isEqualTo("sentinel-admin"); assertThat(config.getSentinelPassword()).isEqualTo(RedisPassword.of("foo")); @@ -192,40 +193,44 @@ class RedisSentinelConfigurationUnitTests { @Test // GH-2860 void readSentinelDataNodeUsernameFromConfigProperty() { + MockPropertySource propertySource = new MockPropertySource(); propertySource.setProperty("spring.redis.sentinel.dataNode.username", "datanode-user"); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getDataNodeUsername()).isEqualTo("datanode-user"); } @Test // GH-2860 void readSentinelDataNodePasswordFromConfigProperty() { + MockPropertySource propertySource = new MockPropertySource(); propertySource.setProperty("spring.redis.sentinel.dataNode.password", "datanode-password"); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getDataNodePassword()).isEqualTo(RedisPassword.of("datanode-password")); } @Test // GH-2860 void readSentinelDataNodeDatabaseFromConfigProperty() { + MockPropertySource propertySource = new MockPropertySource(); propertySource.setProperty("spring.redis.sentinel.dataNode.database", "5"); - RedisSentinelConfiguration config = new RedisSentinelConfiguration(propertySource); + RedisSentinelConfiguration config = RedisSentinelConfiguration.of(propertySource); assertThat(config.getDatabase()).isEqualTo(5); } @Test // GH-2860 void shouldThrowErrorWhen() { + MockPropertySource propertySource = new MockPropertySource(); propertySource.setProperty("spring.redis.sentinel.dataNode.database", "thisIsNotAnInteger"); - ThrowableAssert.ThrowingCallable call = () -> new RedisSentinelConfiguration(propertySource); + ThrowableAssert.ThrowingCallable call = () -> RedisSentinelConfiguration.of(propertySource); assertThatThrownBy(call).isInstanceOf(IllegalArgumentException.class) .hasMessage("Invalid DB index '%s'; integer required", "thisIsNotAnInteger"); @@ -233,10 +238,11 @@ class RedisSentinelConfigurationUnitTests { @Test // GH-2860 void shouldThrowErrorWhen2() { + MockPropertySource propertySource = new MockPropertySource(); propertySource.setProperty("spring.redis.sentinel.dataNode.database", "null"); - ThrowableAssert.ThrowingCallable call = () -> new RedisSentinelConfiguration(propertySource); + ThrowableAssert.ThrowingCallable call = () -> RedisSentinelConfiguration.of(propertySource); assertThatThrownBy(call).isInstanceOf(IllegalArgumentException.class) .hasMessage("Invalid DB index '%s'; integer required", "null");