Polishing.
Reorder methods. Remove unnecessary null guards. Introduce hashCode/equals methods to RedisConfiguration implementations. Refactor tests. Let LettuceClientConfiguration.builder apply settings from RedisURI. Introduce SentinelMasterId to implement equals method. See #2116. Original pull request: #2117.
This commit is contained in:
@@ -31,6 +31,7 @@ import org.springframework.data.redis.connection.RedisConfiguration.ClusterConfi
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.NumberUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -223,6 +224,44 @@ public class RedisClusterConfiguration implements RedisConfiguration, ClusterCon
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof RedisClusterConfiguration)) {
|
||||
return false;
|
||||
}
|
||||
RedisClusterConfiguration that = (RedisClusterConfiguration) o;
|
||||
if (!ObjectUtils.nullSafeEquals(clusterNodes, that.clusterNodes)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(maxRedirects, that.maxRedirects)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(username, that.username)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(password, that.password);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(clusterNodes);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(maxRedirects);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(username);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(password);
|
||||
return result;
|
||||
}
|
||||
|
||||
private RedisNode readHostAndPortFromString(String hostAndPort) {
|
||||
|
||||
String[] args = split(hostAndPort, ":");
|
||||
|
||||
@@ -349,11 +349,11 @@ public interface RedisConfiguration {
|
||||
*
|
||||
* @param name must not be {@literal null}.
|
||||
*/
|
||||
default void setMaster(final String name) {
|
||||
default void setMaster(String name) {
|
||||
|
||||
Assert.notNull(name, "Name of sentinel master must not be null.");
|
||||
|
||||
setMaster(() -> name);
|
||||
setMaster(new SentinelMasterId(name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.data.redis.connection.RedisConfiguration.SentinelConfiguration;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -289,6 +290,52 @@ public class RedisSentinelConfiguration implements RedisConfiguration, SentinelC
|
||||
return sentinelPassword;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof RedisSentinelConfiguration)) {
|
||||
return false;
|
||||
}
|
||||
RedisSentinelConfiguration that = (RedisSentinelConfiguration) o;
|
||||
if (database != that.database) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(master, that.master)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(sentinels, that.sentinels)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(dataNodeUsername, that.dataNodeUsername)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(dataNodePassword, that.dataNodePassword)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(sentinelPassword, that.sentinelPassword);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(master);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(sentinels);
|
||||
result = 31 * result + database;
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(dataNodeUsername);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(dataNodePassword);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(sentinelPassword);
|
||||
return result;
|
||||
}
|
||||
|
||||
private RedisNode readHostAndPortFromString(String hostAndPort) {
|
||||
|
||||
String[] args = split(hostAndPort, ":");
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection;
|
||||
import org.springframework.data.redis.connection.RedisConfiguration.DomainSocketConfiguration;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Configuration class used for setting up {@link RedisConnection} via {@link RedisConnectionFactory} connecting to
|
||||
@@ -133,4 +134,42 @@ public class RedisSocketConfiguration implements RedisConfiguration, DomainSocke
|
||||
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof RedisSocketConfiguration)) {
|
||||
return false;
|
||||
}
|
||||
RedisSocketConfiguration that = (RedisSocketConfiguration) o;
|
||||
if (database != that.database) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(socket, that.socket)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(username, that.username)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(password, that.password);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(socket);
|
||||
result = 31 * result + database;
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(username);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(password);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.data.redis.connection.RedisConfiguration.WithHostAndP
|
||||
import org.springframework.data.redis.connection.RedisConfiguration.WithPassword;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Configuration class used for setting up {@link RedisConnection} via {@link RedisConnectionFactory} using connecting
|
||||
@@ -166,4 +167,46 @@ public class RedisStandaloneConfiguration
|
||||
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof RedisStandaloneConfiguration)) {
|
||||
return false;
|
||||
}
|
||||
RedisStandaloneConfiguration that = (RedisStandaloneConfiguration) o;
|
||||
if (port != that.port) {
|
||||
return false;
|
||||
}
|
||||
if (database != that.database) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(hostName, that.hostName)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(username, that.username)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(password, that.password);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(hostName);
|
||||
result = 31 * result + port;
|
||||
result = 31 * result + database;
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(username);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(password);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import org.springframework.data.redis.connection.RedisConfiguration.StaticMasterReplicaConfiguration;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Configuration class used for setting up {@link RedisConnection} via {@link RedisConnectionFactory} using the provided
|
||||
@@ -181,4 +182,42 @@ public class RedisStaticMasterReplicaConfiguration implements RedisConfiguration
|
||||
public List<RedisStandaloneConfiguration> getNodes() {
|
||||
return Collections.unmodifiableList(nodes);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof RedisStaticMasterReplicaConfiguration)) {
|
||||
return false;
|
||||
}
|
||||
RedisStaticMasterReplicaConfiguration that = (RedisStaticMasterReplicaConfiguration) o;
|
||||
if (database != that.database) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(nodes, that.nodes)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(username, that.username)) {
|
||||
return false;
|
||||
}
|
||||
return ObjectUtils.nullSafeEquals(password, that.password);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(nodes);
|
||||
result = 31 * result + database;
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(username);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(password);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2021 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;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Simple {@link NamedNode}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.5.3
|
||||
*/
|
||||
class SentinelMasterId implements NamedNode {
|
||||
|
||||
private final String name;
|
||||
|
||||
public SentinelMasterId(String name) {
|
||||
Assert.hasText(name, "Sentinel Master Id must not be null or empty");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.NamedNode#getName()
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof SentinelMasterId)) {
|
||||
return false;
|
||||
}
|
||||
SentinelMasterId that = (SentinelMasterId) o;
|
||||
return ObjectUtils.nullSafeEquals(name, that.name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(name);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Redis client configuration for lettuce. This configuration provides optional configuration elements such as
|
||||
@@ -173,6 +174,30 @@ public interface LettuceClientConfiguration {
|
||||
|
||||
LettuceClientConfigurationBuilder() {}
|
||||
|
||||
/**
|
||||
* Apply SSL settings, command timeout, and client name from a {@link RedisURI}.
|
||||
*
|
||||
* @param redisUri the connection URI.
|
||||
* @return {@literal this} builder.
|
||||
* @since 2.5.3
|
||||
*/
|
||||
public LettuceClientConfigurationBuilder apply(RedisURI redisUri) {
|
||||
|
||||
this.useSsl = redisUri.isSsl();
|
||||
this.verifyPeer = redisUri.isVerifyPeer();
|
||||
this.startTls = redisUri.isStartTls();
|
||||
|
||||
if (!redisUri.getTimeout().equals(RedisURI.DEFAULT_TIMEOUT_DURATION)) {
|
||||
this.timeout = redisUri.getTimeout();
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(redisUri.getClientName())) {
|
||||
this.clientName = redisUri.getClientName();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable SSL connections.
|
||||
*
|
||||
|
||||
@@ -282,29 +282,51 @@ public class LettuceConnectionFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RedisConfiguration} based on a {@link RedisURI} according to the following:
|
||||
* Creates a {@link RedisConfiguration} based on a {@link String URI} according to the following:
|
||||
* <ul>
|
||||
* <li>If {@code redisURI} has sentinel info a {@link RedisSentinelConfiguration} is returned</li>
|
||||
* <li>If {@code redisURI} has socket info a {@link RedisSocketConfiguration} is returned</li>
|
||||
* <li>If {@code redisUri} contains sentinels, a {@link RedisSentinelConfiguration} is returned</li>
|
||||
* <li>If {@code redisUri} has a configured socket a {@link RedisSocketConfiguration} is returned</li>
|
||||
* <li>Otherwise a {@link RedisStandaloneConfiguration} is returned</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param redisURI the connection info in the format of a RedisURI
|
||||
* @param redisUri the connection URI in the format of a {@link RedisURI}.
|
||||
* @return an appropriate {@link RedisConfiguration} instance representing the Redis URI.
|
||||
* @since 2.5.3
|
||||
* @see RedisURI
|
||||
*/
|
||||
public static RedisConfiguration createRedisConfiguration(RedisURI redisURI) {
|
||||
public static RedisConfiguration createRedisConfiguration(String redisUri) {
|
||||
|
||||
Assert.notNull(redisURI, "RedisURI must not be null");
|
||||
Assert.hasText(redisUri, "RedisURI must not be null and not empty");
|
||||
|
||||
if (!ObjectUtils.isEmpty(redisURI.getSentinels())) {
|
||||
return LettuceConverters.redisUriToSentinelConfiguration(redisURI);
|
||||
return createRedisConfiguration(RedisURI.create(redisUri));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RedisConfiguration} based on a {@link RedisURI} according to the following:
|
||||
* <ul>
|
||||
* <li>If {@link RedisURI} contains sentinels, a {@link RedisSentinelConfiguration} is returned</li>
|
||||
* <li>If {@link RedisURI} has a configured socket a {@link RedisSocketConfiguration} is returned</li>
|
||||
* <li>Otherwise a {@link RedisStandaloneConfiguration} is returned</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param redisUri the connection URI.
|
||||
* @return an appropriate {@link RedisConfiguration} instance representing the Redis URI.
|
||||
* @since 2.5.3
|
||||
* @see RedisURI
|
||||
*/
|
||||
public static RedisConfiguration createRedisConfiguration(RedisURI redisUri) {
|
||||
|
||||
Assert.notNull(redisUri, "RedisURI must not be null");
|
||||
|
||||
if (!ObjectUtils.isEmpty(redisUri.getSentinels())) {
|
||||
return LettuceConverters.createRedisSentinelConfiguration(redisUri);
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(redisURI.getSocket())) {
|
||||
return LettuceConverters.redisUriToSocketConfiguration(redisURI);
|
||||
if (!ObjectUtils.isEmpty(redisUri.getSocket())) {
|
||||
return LettuceConverters.createRedisSocketConfiguration(redisUri);
|
||||
}
|
||||
|
||||
return LettuceConverters.redisUriToStandaloneConfiguration(redisURI);
|
||||
return LettuceConverters.createRedisStandaloneConfiguration(redisUri);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -524,16 +524,51 @@ public abstract class LettuceConverters extends Converters {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link RedisURI} to its corresponding {@link RedisStandaloneConfiguration}.
|
||||
*
|
||||
* @param redisURI the uri containing the Redis connection info
|
||||
* @return a {@link RedisStandaloneConfiguration} representing the connection information in the Redis URI.
|
||||
* @since 2.5.3
|
||||
*/
|
||||
static RedisStandaloneConfiguration createRedisStandaloneConfiguration(RedisURI redisURI) {
|
||||
|
||||
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
|
||||
standaloneConfiguration.setHostName(redisURI.getHost());
|
||||
standaloneConfiguration.setPort(redisURI.getPort());
|
||||
standaloneConfiguration.setDatabase(redisURI.getDatabase());
|
||||
|
||||
applyAuthentication(redisURI, standaloneConfiguration);
|
||||
|
||||
return standaloneConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link RedisURI} to its corresponding {@link RedisSocketConfiguration}.
|
||||
*
|
||||
* @param redisURI the uri containing the Redis connection info using a local unix domain socket
|
||||
* @return a {@link RedisSocketConfiguration} representing the connection information in the Redis URI.
|
||||
* @since 2.5.3
|
||||
*/
|
||||
static RedisSocketConfiguration createRedisSocketConfiguration(RedisURI redisURI) {
|
||||
|
||||
RedisSocketConfiguration socketConfiguration = new RedisSocketConfiguration();
|
||||
socketConfiguration.setSocket(redisURI.getSocket());
|
||||
socketConfiguration.setDatabase(redisURI.getDatabase());
|
||||
|
||||
applyAuthentication(redisURI, socketConfiguration);
|
||||
|
||||
return socketConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link RedisURI} to its corresponding {@link RedisSentinelConfiguration}.
|
||||
*
|
||||
* @param redisURI the uri containing the Redis Sentinel connection info
|
||||
* @return a {@link RedisSentinelConfiguration} representing the Redis Sentinel information in the Redis URI.
|
||||
* @since 2.6
|
||||
* @since 2.5.3
|
||||
*/
|
||||
static RedisSentinelConfiguration redisUriToSentinelConfiguration(RedisURI redisURI) {
|
||||
|
||||
Assert.notNull(redisURI, "RedisURI is required");
|
||||
static RedisSentinelConfiguration createRedisSentinelConfiguration(RedisURI redisURI) {
|
||||
|
||||
RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
|
||||
if (!ObjectUtils.isEmpty(redisURI.getSentinelMasterId())) {
|
||||
@@ -554,51 +589,12 @@ public abstract class LettuceConverters extends Converters {
|
||||
return sentinelConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link RedisURI} to its corresponding {@link RedisSocketConfiguration}.
|
||||
*
|
||||
* @param redisURI the uri containing the Redis connection info using a local unix domain socket
|
||||
* @return a {@link RedisSocketConfiguration} representing the connection information in the Redis URI.
|
||||
* @since 2.6
|
||||
*/
|
||||
static RedisSocketConfiguration redisUriToSocketConfiguration(RedisURI redisURI) {
|
||||
|
||||
Assert.notNull(redisURI, "RedisURI is required");
|
||||
|
||||
RedisSocketConfiguration socketConfiguration = new RedisSocketConfiguration();
|
||||
socketConfiguration.setSocket(redisURI.getSocket());
|
||||
socketConfiguration.setDatabase(redisURI.getDatabase());
|
||||
|
||||
applyAuthentication(redisURI, socketConfiguration);
|
||||
|
||||
return socketConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link RedisURI} to its corresponding {@link RedisStandaloneConfiguration}.
|
||||
*
|
||||
* @param redisURI the uri containing the Redis connection info
|
||||
* @return a {@link RedisStandaloneConfiguration} representing the connection information in the Redis URI.
|
||||
* @since 2.6
|
||||
*/
|
||||
static RedisStandaloneConfiguration redisUriToStandaloneConfiguration(RedisURI redisURI) {
|
||||
|
||||
Assert.notNull(redisURI, "RedisURI is required");
|
||||
|
||||
RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();
|
||||
standaloneConfiguration.setHostName(redisURI.getHost());
|
||||
standaloneConfiguration.setPort(redisURI.getPort());
|
||||
standaloneConfiguration.setDatabase(redisURI.getDatabase());
|
||||
|
||||
applyAuthentication(redisURI, standaloneConfiguration);
|
||||
|
||||
return standaloneConfiguration;
|
||||
}
|
||||
|
||||
private static void applyAuthentication(RedisURI redisURI, RedisConfiguration.WithAuthentication redisConfiguration) {
|
||||
|
||||
if (StringUtils.hasText(redisURI.getUsername())) {
|
||||
redisConfiguration.setUsername(redisURI.getUsername());
|
||||
}
|
||||
|
||||
if (redisURI.getPassword() != null) {
|
||||
redisConfiguration.setPassword(redisURI.getPassword());
|
||||
}
|
||||
|
||||
@@ -18,12 +18,13 @@ package org.springframework.data.redis.connection.lettuce;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.TimeoutOptions;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.data.redis.test.extension.LettuceTestClientResources;
|
||||
|
||||
@@ -105,4 +106,29 @@ class LettuceClientConfigurationUnitTests {
|
||||
void clientConfigurationThrowsExceptionForEmptyClientName() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> LettuceClientConfiguration.builder().clientName(" "));
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void shouldApplySettingsFromRedisURI() {
|
||||
|
||||
LettuceClientConfiguration configuration = LettuceClientConfiguration.builder() //
|
||||
.apply(RedisURI.create("rediss://foo?verifyPeer=FULL&clientName=bar&timeout=10s")).build();
|
||||
|
||||
assertThat(configuration.isUseSsl()).isTrue();
|
||||
assertThat(configuration.isVerifyPeer()).isTrue();
|
||||
assertThat(configuration.isStartTls()).isFalse();
|
||||
assertThat(configuration.getClientName()).contains("bar");
|
||||
assertThat(configuration.getCommandTimeout()).isEqualTo(Duration.ofSeconds(10));
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void emptySettingsRetainClientConfiguration() {
|
||||
|
||||
LettuceClientConfiguration configuration = LettuceClientConfiguration.builder() //
|
||||
.clientName("hello") //
|
||||
.commandTimeout(Duration.ofMillis(1)) //
|
||||
.apply(RedisURI.create("rediss://foo")).build();
|
||||
|
||||
assertThat(configuration.getClientName()).contains("hello");
|
||||
assertThat(configuration.getCommandTimeout()).isEqualTo(Duration.ofMillis(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-2021 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.lettuce;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import io.lettuce.core.RedisURI;
|
||||
|
||||
import org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisSocketConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link LettuceConnectionFactory#createRedisConfiguration(RedisURI)} factory method.
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
class LettuceConnectionFactoryCreateRedisConfigurationUnitTests {
|
||||
|
||||
@Test
|
||||
void requiresRedisURI() {
|
||||
assertThatThrownBy(() -> LettuceConnectionFactory.createRedisConfiguration(null))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("RedisURI must not be null");
|
||||
}
|
||||
|
||||
@Nested // GH-2117
|
||||
class CreateRedisSentinelConfiguration {
|
||||
|
||||
@Test
|
||||
void minimalFieldsSetOnRedisURI() {
|
||||
RedisURI redisURI = RedisURI.create("redis-sentinel://myserver?sentinelMasterId=5150");
|
||||
RedisSentinelConfiguration expectedSentinelConfiguration = new RedisSentinelConfiguration();
|
||||
expectedSentinelConfiguration.setMaster("5150");
|
||||
expectedSentinelConfiguration.addSentinel(new RedisNode("myserver", 26379));
|
||||
|
||||
RedisConfiguration sentinelConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(sentinelConfiguration).usingRecursiveComparison(sentinelCompareConfig())
|
||||
.isInstanceOf(RedisSentinelConfiguration.class)
|
||||
.isEqualTo(expectedSentinelConfiguration);
|
||||
}
|
||||
|
||||
@Test
|
||||
void allFieldsSetOnRedisURI() {
|
||||
RedisURI redisURI = RedisURI.create("redis-sentinel://fooUser:fooPass@myserver1:111,myserver2:222/7?sentinelMasterId=5150");
|
||||
// Set the passwords directly on the sentinels so that it gets picked up by converter
|
||||
char[] sentinelPass = "changeme".toCharArray();
|
||||
redisURI.getSentinels().forEach(sentinelRedisUri -> sentinelRedisUri.setPassword(sentinelPass));
|
||||
RedisSentinelConfiguration expectedSentinelConfiguration = new RedisSentinelConfiguration();
|
||||
expectedSentinelConfiguration.setMaster("5150");
|
||||
expectedSentinelConfiguration.setDatabase(7);
|
||||
expectedSentinelConfiguration.setUsername("fooUser");
|
||||
expectedSentinelConfiguration.setPassword("fooPass");
|
||||
expectedSentinelConfiguration.setSentinelPassword(sentinelPass);
|
||||
expectedSentinelConfiguration.addSentinel(new RedisNode("myserver1", 111));
|
||||
expectedSentinelConfiguration.addSentinel(new RedisNode("myserver2", 222));
|
||||
|
||||
RedisConfiguration sentinelConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(sentinelConfiguration).usingRecursiveComparison(sentinelCompareConfig())
|
||||
.isInstanceOf(RedisSentinelConfiguration.class)
|
||||
.isEqualTo(expectedSentinelConfiguration);
|
||||
}
|
||||
|
||||
// RedisSentinelConfiguration does not provide equals impl
|
||||
private RecursiveComparisonConfiguration sentinelCompareConfig() {
|
||||
return RecursiveComparisonConfiguration.builder().withComparedFields(
|
||||
"master",
|
||||
"username",
|
||||
"password",
|
||||
"sentinelPassword",
|
||||
"database",
|
||||
"sentinels")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested // GH-2117
|
||||
class CreateRedisSocketConfiguration {
|
||||
|
||||
@Test
|
||||
void minimalFieldsSetOnRedisURI() {
|
||||
RedisURI redisURI = RedisURI.builder()
|
||||
.socket("mysocket")
|
||||
.build();
|
||||
RedisSocketConfiguration expectedSocketConfiguration = new RedisSocketConfiguration();
|
||||
expectedSocketConfiguration.setSocket("mysocket");
|
||||
|
||||
RedisConfiguration socketConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(socketConfiguration).usingRecursiveComparison(socketCompareConfig())
|
||||
.isInstanceOf(RedisSocketConfiguration.class)
|
||||
.isEqualTo(expectedSocketConfiguration);
|
||||
}
|
||||
|
||||
@Test
|
||||
void allFieldsSetOnRedisURI() {
|
||||
RedisURI redisURI = RedisURI.builder()
|
||||
.socket("mysocket")
|
||||
.withAuthentication("fooUser", "fooPass".toCharArray())
|
||||
.withDatabase(7)
|
||||
.build();
|
||||
RedisSocketConfiguration expectedSocketConfiguration = new RedisSocketConfiguration();
|
||||
expectedSocketConfiguration.setSocket("mysocket");
|
||||
expectedSocketConfiguration.setUsername("fooUser");
|
||||
expectedSocketConfiguration.setPassword("fooPass");
|
||||
expectedSocketConfiguration.setDatabase(7);
|
||||
|
||||
RedisConfiguration socketConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(socketConfiguration).usingRecursiveComparison(socketCompareConfig())
|
||||
.isInstanceOf(RedisSocketConfiguration.class)
|
||||
.isEqualTo(expectedSocketConfiguration);
|
||||
}
|
||||
|
||||
// RedisSocketConfiguration does not provide equals impl
|
||||
private RecursiveComparisonConfiguration socketCompareConfig() {
|
||||
return RecursiveComparisonConfiguration.builder().withComparedFields(
|
||||
"socket",
|
||||
"username",
|
||||
"password",
|
||||
"database")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested // GH-2117
|
||||
class CreateRedisStandaloneConfiguration {
|
||||
|
||||
@Test
|
||||
void minimalFieldsSetOnRedisURI() {
|
||||
RedisURI redisURI = RedisURI.create("redis://myserver");
|
||||
RedisStandaloneConfiguration expectedStandaloneConfiguration = new RedisStandaloneConfiguration();
|
||||
expectedStandaloneConfiguration.setHostName("myserver");
|
||||
|
||||
RedisConfiguration StandaloneConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(StandaloneConfiguration).usingRecursiveComparison(standaloneCompareConfig())
|
||||
.isInstanceOf(RedisStandaloneConfiguration.class)
|
||||
.isEqualTo(expectedStandaloneConfiguration);
|
||||
}
|
||||
|
||||
@Test
|
||||
void allFieldsSetOnRedisURI() {
|
||||
RedisURI redisURI = RedisURI.create("redis://fooUser:fooPass@myserver1:111/7");
|
||||
RedisStandaloneConfiguration expectedStandaloneConfiguration = new RedisStandaloneConfiguration();
|
||||
expectedStandaloneConfiguration.setHostName("myserver1");
|
||||
expectedStandaloneConfiguration.setPort(111);
|
||||
expectedStandaloneConfiguration.setDatabase(7);
|
||||
expectedStandaloneConfiguration.setUsername("fooUser");
|
||||
expectedStandaloneConfiguration.setPassword("fooPass");
|
||||
|
||||
RedisConfiguration StandaloneConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(StandaloneConfiguration).usingRecursiveComparison(standaloneCompareConfig())
|
||||
.isInstanceOf(RedisStandaloneConfiguration.class)
|
||||
.isEqualTo(expectedStandaloneConfiguration);
|
||||
|
||||
}
|
||||
|
||||
// RedisStandaloneConfiguration does not provide equals impl
|
||||
private RecursiveComparisonConfiguration standaloneCompareConfig() {
|
||||
return RecursiveComparisonConfiguration.builder().withComparedFields(
|
||||
"host",
|
||||
"port",
|
||||
"username",
|
||||
"password",
|
||||
"database")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2015-2021 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.lettuce;
|
||||
|
||||
import io.lettuce.core.RedisURI;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link LettuceConnectionFactory#createRedisConfiguration(RedisURI)} factory method.
|
||||
*
|
||||
* @author Chris Bono
|
||||
*/
|
||||
class LettuceConnectionFactoryRedisURITests {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -56,6 +56,7 @@ import org.springframework.data.redis.connection.RedisClusterConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisClusterConnection;
|
||||
import org.springframework.data.redis.connection.RedisConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.RedisPassword;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisSocketConfiguration;
|
||||
@@ -72,6 +73,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
* @author Ruben Cervilla
|
||||
* @author Luis De Bello
|
||||
* @author Andrea Como
|
||||
* @author Chris Bono
|
||||
*/
|
||||
class LettuceConnectionFactoryUnitTests {
|
||||
|
||||
@@ -1026,6 +1028,110 @@ class LettuceConnectionFactoryUnitTests {
|
||||
assertThatIllegalStateException().isThrownBy(connectionFactory::getReactiveClusterConnection);
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createRedisConfigurationRequiresRedisUri() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> LettuceConnectionFactory.createRedisConfiguration((RedisURI) null))
|
||||
.withMessage("RedisURI must not be null");
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createMinimalRedisStandaloneConfiguration() {
|
||||
|
||||
RedisURI redisURI = RedisURI.create("redis://myserver");
|
||||
|
||||
RedisStandaloneConfiguration expected = new RedisStandaloneConfiguration();
|
||||
expected.setHostName("myserver");
|
||||
|
||||
RedisConfiguration configuration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(configuration).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createFullRedisStanaloneConfiguration() {
|
||||
|
||||
RedisURI redisURI = RedisURI.create("redis://fooUser:fooPass@myserver1:111/7");
|
||||
|
||||
RedisStandaloneConfiguration expected = new RedisStandaloneConfiguration();
|
||||
expected.setHostName("myserver1");
|
||||
expected.setPort(111);
|
||||
expected.setDatabase(7);
|
||||
expected.setUsername("fooUser");
|
||||
expected.setPassword("fooPass");
|
||||
|
||||
RedisConfiguration configuration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(configuration).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createMinimalRedisSocketConfiguration() {
|
||||
|
||||
RedisURI redisURI = RedisURI.Builder.socket("mysocket").build();
|
||||
|
||||
RedisSocketConfiguration expected = new RedisSocketConfiguration();
|
||||
expected.setSocket("mysocket");
|
||||
|
||||
RedisConfiguration socketConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(socketConfiguration).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createFullRedisSocketConfiguration() {
|
||||
|
||||
RedisURI redisURI = RedisURI.Builder.socket("mysocket").withAuthentication("fooUser", "fooPass".toCharArray())
|
||||
.withDatabase(7).build();
|
||||
|
||||
RedisSocketConfiguration expected = new RedisSocketConfiguration();
|
||||
expected.setSocket("mysocket");
|
||||
expected.setUsername("fooUser");
|
||||
expected.setPassword("fooPass");
|
||||
expected.setDatabase(7);
|
||||
|
||||
RedisConfiguration socketConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(socketConfiguration).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createMinimalRedisSentinelConfiguration() {
|
||||
|
||||
RedisURI redisURI = RedisURI.create("redis-sentinel://myserver?sentinelMasterId=5150");
|
||||
|
||||
RedisSentinelConfiguration expected = new RedisSentinelConfiguration();
|
||||
expected.setMaster("5150");
|
||||
expected.addSentinel(new RedisNode("myserver", 26379));
|
||||
|
||||
RedisConfiguration sentinelConfiguration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(sentinelConfiguration).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test // GH-2116
|
||||
void createFullRedisSentinelConfiguration() {
|
||||
|
||||
RedisURI redisURI = RedisURI
|
||||
.create("redis-sentinel://fooUser:fooPass@myserver1:111,myserver2:222/7?sentinelMasterId=5150");
|
||||
// Set the passwords directly on the sentinels so that it gets picked up by converter
|
||||
char[] sentinelPass = "changeme".toCharArray();
|
||||
redisURI.getSentinels().forEach(sentinelRedisUri -> sentinelRedisUri.setPassword(sentinelPass));
|
||||
|
||||
RedisSentinelConfiguration expected = new RedisSentinelConfiguration();
|
||||
expected.setMaster("5150");
|
||||
expected.setDatabase(7);
|
||||
expected.setUsername("fooUser");
|
||||
expected.setPassword("fooPass");
|
||||
expected.setSentinelPassword(sentinelPass);
|
||||
expected.addSentinel(new RedisNode("myserver1", 111));
|
||||
expected.addSentinel(new RedisNode("myserver2", 222));
|
||||
|
||||
RedisConfiguration configuration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
|
||||
|
||||
assertThat(configuration).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
static class CustomRedisConfiguration implements RedisConfiguration, WithHostAndPort {
|
||||
|
||||
Reference in New Issue
Block a user