From 59d1b77e578b831fbd6514a4173f2f6176ca457d Mon Sep 17 00:00:00 2001
From: Anish Prasad <40836622+anish8129@users.noreply.github.com>
Date: Mon, 20 Nov 2023 19:17:31 +0530
Subject: [PATCH 1/3] Update DefaultJedisClientConfiguration.java

---
 .../DefaultJedisClientConfiguration.java      | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)

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 b38d9c902b..41f60451e7 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
@@ -24,6 +24,7 @@
 
 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 import org.springframework.lang.Nullable;
+import redis.clients.jedis.HostAndPortMapper;
 
 /**
  * Default implementation of {@literal JedisClientConfiguration}.
@@ -38,6 +39,7 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
 	private final Optional<SSLSocketFactory> sslSocketFactory;
 	private final Optional<SSLParameters> sslParameters;
 	private final Optional<HostnameVerifier> hostnameVerifier;
+	private final Optional<HostAndPortMapper> hostAndPortMapper;
 	private final boolean usePooling;
 	private final Optional<GenericObjectPoolConfig> poolConfig;
 	private final Optional<String> clientName;
@@ -53,6 +55,7 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
 		this.sslSocketFactory = Optional.ofNullable(sslSocketFactory);
 		this.sslParameters = Optional.ofNullable(sslParameters);
 		this.hostnameVerifier = Optional.ofNullable(hostnameVerifier);
+		this.hostAndPortMapper = Optional.empty();
 		this.usePooling = usePooling;
 		this.poolConfig = Optional.ofNullable(poolConfig);
 		this.clientName = Optional.ofNullable(clientName);
@@ -60,26 +63,66 @@ class DefaultJedisClientConfiguration implements JedisClientConfiguration {
 		this.connectTimeout = connectTimeout;
 	}
 
+	DefaultJedisClientConfiguration(boolean useSsl, @Nullable SSLSocketFactory sslSocketFactory,
+			@Nullable SSLParameters sslParameters, @Nullable HostnameVerifier hostnameVerifier,
+			@Nullable HostAndPortMapper hostAndPortMapper, boolean usePooling,
+			@Nullable GenericObjectPoolConfig poolConfig, @Nullable String clientName, Duration readTimeout,
+			Duration connectTimeout) {
+
+		this.useSsl = useSsl;
+		this.sslSocketFactory = Optional.ofNullable(sslSocketFactory);
+		this.sslParameters = Optional.ofNullable(sslParameters);
+		this.hostnameVerifier = Optional.ofNullable(hostnameVerifier);
+		this.hostAndPortMapper = Optional.ofNullable(hostAndPortMapper);
+		this.usePooling = usePooling;
+		this.poolConfig = Optional.ofNullable(poolConfig);
+		this.clientName = Optional.ofNullable(clientName);
+		this.readTimeout = readTimeout;
+		this.connectTimeout = connectTimeout;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#useSsl()
+	 */
 	@Override
 	public boolean isUseSsl() {
 		return useSsl;
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getSslSocketFactory()
+	 */
 	@Override
 	public Optional<SSLSocketFactory> getSslSocketFactory() {
 		return sslSocketFactory;
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getSslParameters()
+	 */
 	@Override
 	public Optional<SSLParameters> getSslParameters() {
 		return sslParameters;
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration#getHostnameVerifier()
+	 */
 	@Override
 	public Optional<HostnameVerifier> getHostnameVerifier() {
 		return hostnameVerifier;
 	}
 
+	@Override
+	public Optional<HostAndPortMapper> getHostAndPortMapper() {
+		return hostAndPortMapper;
+	}
+
+
 	@Override
 	public boolean isUsePooling() {
 		return usePooling;

From 56be73f74e112642e36807341b4c285f471e186e Mon Sep 17 00:00:00 2001
From: Anish Prasad <40836622+anish8129@users.noreply.github.com>
Date: Mon, 20 Nov 2023 19:17:59 +0530
Subject: [PATCH 2/3] Update JedisClientConfiguration.java

---
 .../jedis/JedisClientConfiguration.java       | 80 +++++++++++++++++--
 1 file changed, 72 insertions(+), 8 deletions(-)

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 3dad5f7740..7da5f54312 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
@@ -15,6 +15,7 @@
  */
 package org.springframework.data.redis.connection.jedis;
 
+import redis.clients.jedis.HostAndPortMapper;
 import redis.clients.jedis.JedisPoolConfig;
 import redis.clients.jedis.Protocol;
 
@@ -78,6 +79,11 @@ public interface JedisClientConfiguration {
 	 */
 	Optional<HostnameVerifier> getHostnameVerifier();
 
+	/**
+	 * @return the optional {@link HostAndPortMapper}.
+	 */
+	Optional<HostAndPortMapper> getHostAndPortMapper();
+
 	/**
 	 * @return {@literal true} to use connection-pooling. Applies only to single node Redis. Sentinel and Cluster modes
 	 *         use always connection-pooling regardless of the pooling setting.
@@ -168,6 +174,15 @@ interface JedisClientConfigurationBuilder {
 		 */
 		JedisClientConfigurationBuilder clientName(String clientName);
 
+		/**
+		 * Configure a {@code hostAndPortMapper}
+		 *
+		 * @param hostAndPortMapper must not be {@literal null}.
+		 * @return {@literal this} builder.
+		 * @throws IllegalArgumentException if clientName is {@literal null}.
+		 */
+		JedisClientConfigurationBuilder hostAndPortMapper(HostAndPortMapper hostAndPortMapper);
+
 		/**
 		 * Configure a read timeout.
 		 *
@@ -273,6 +288,7 @@ class DefaultJedisClientConfigurationBuilder implements JedisClientConfiguration
 		private @Nullable SSLSocketFactory sslSocketFactory;
 		private @Nullable SSLParameters sslParameters;
 		private @Nullable HostnameVerifier hostnameVerifier;
+		private @Nullable HostAndPortMapper hostAndPortMapper;
 		private boolean usePooling;
 		private GenericObjectPoolConfig poolConfig = new JedisPoolConfig();
 		private @Nullable String clientName;
@@ -281,6 +297,10 @@ class DefaultJedisClientConfigurationBuilder implements JedisClientConfiguration
 
 		private DefaultJedisClientConfigurationBuilder() {}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#useSsl()
+		 */
 		@Override
 		public JedisSslClientConfigurationBuilder useSsl() {
 
@@ -288,33 +308,49 @@ public JedisSslClientConfigurationBuilder useSsl() {
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisSslClientConfigurationBuilder#sslSocketFactory(javax.net.ssl.SSLSocketFactory)
+		 */
 		@Override
 		public JedisSslClientConfigurationBuilder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
 
-			Assert.notNull(sslSocketFactory, "SSLSocketFactory must not be null");
+			Assert.notNull(sslSocketFactory, "SSLSocketFactory must not be null!");
 
 			this.sslSocketFactory = sslSocketFactory;
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisSslClientConfigurationBuilder#sslParameters(javax.net.ssl.SSLParameters)
+		 */
 		@Override
 		public JedisSslClientConfigurationBuilder sslParameters(SSLParameters sslParameters) {
 
-			Assert.notNull(sslParameters, "SSLParameters must not be null");
+			Assert.notNull(sslParameters, "SSLParameters must not be null!");
 
 			this.sslParameters = sslParameters;
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisSslClientConfigurationBuilder#hostnameVerifier(javax.net.ssl.HostnameVerifier)
+		 */
 		@Override
 		public JedisSslClientConfigurationBuilder hostnameVerifier(HostnameVerifier hostnameVerifier) {
 
-			Assert.notNull(hostnameVerifier, "HostnameVerifier must not be null");
+			Assert.notNull(hostnameVerifier, "HostnameVerifier must not be null!");
 
 			this.hostnameVerifier = hostnameVerifier;
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#usePooling()
+		 */
 		@Override
 		public JedisPoolingClientConfigurationBuilder usePooling() {
 
@@ -322,42 +358,70 @@ public JedisPoolingClientConfigurationBuilder usePooling() {
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisPoolingClientConfigurationBuilder#poolConfig(org.apache.commons.pool2.impl.GenericObjectPoolConfig)
+		 */
 		@Override
 		public JedisPoolingClientConfigurationBuilder poolConfig(GenericObjectPoolConfig poolConfig) {
 
-			Assert.notNull(poolConfig, "GenericObjectPoolConfig must not be null");
+			Assert.notNull(poolConfig, "GenericObjectPoolConfig must not be null!");
 
 			this.poolConfig = poolConfig;
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisPoolingClientConfigurationBuilder#and()
+		 */
 		@Override
 		public JedisClientConfigurationBuilder and() {
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#clientName(java.lang.String)
+		 */
 		@Override
 		public JedisClientConfigurationBuilder clientName(String clientName) {
 
-			Assert.hasText(clientName, "Client name must not be null or empty");
+			Assert.hasText(clientName, "Client name must not be null or empty!");
 
 			this.clientName = clientName;
 			return this;
 		}
 
+		@Override
+		public JedisClientConfigurationBuilder hostAndPortMapper(HostAndPortMapper hostAndPortMapper) {
+			Assert.notNull(hostAndPortMapper, "HostAndPortMapper can not be null");
+
+			this.hostAndPortMapper = hostAndPortMapper;
+			return this;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#readTimeout(java.time.Duration)
+		 */
 		@Override
 		public JedisClientConfigurationBuilder readTimeout(Duration readTimeout) {
 
-			Assert.notNull(readTimeout, "Duration must not be null");
+			Assert.notNull(readTimeout, "Duration must not be null!");
 
 			this.readTimeout = readTimeout;
 			return this;
 		}
 
+		/*
+		 * (non-Javadoc)
+		 * @see org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder#connectTimeout(java.time.Duration)
+		 */
 		@Override
 		public JedisClientConfigurationBuilder connectTimeout(Duration connectTimeout) {
 
-			Assert.notNull(connectTimeout, "Duration must not be null");
+			Assert.notNull(connectTimeout, "Duration must not be null!");
 
 			this.connectTimeout = connectTimeout;
 			return this;
@@ -366,7 +430,7 @@ public JedisClientConfigurationBuilder connectTimeout(Duration connectTimeout) {
 		@Override
 		public JedisClientConfiguration build() {
 
-			return new DefaultJedisClientConfiguration(useSsl, sslSocketFactory, sslParameters, hostnameVerifier, usePooling,
+			return new DefaultJedisClientConfiguration(useSsl, sslSocketFactory, sslParameters, hostnameVerifier, hostAndPortMapper, usePooling,
 					poolConfig, clientName, readTimeout, connectTimeout);
 		}
 	}

From 36617a74c0040331ab20e27d4bd34036cf54ebe8 Mon Sep 17 00:00:00 2001
From: Anish Prasad <40836622+anish8129@users.noreply.github.com>
Date: Mon, 20 Nov 2023 19:18:36 +0530
Subject: [PATCH 3/3] Update JedisConnectionFactory.java

---
 .../redis/connection/jedis/JedisConnectionFactory.java     | 7 +++++++
 1 file changed, 7 insertions(+)

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 ba3575536a..4d281a17fe 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
@@ -18,6 +18,7 @@
 import redis.clients.jedis.Connection;
 import redis.clients.jedis.DefaultJedisClientConfig;
 import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.HostAndPortMapper;
 import redis.clients.jedis.Jedis;
 import redis.clients.jedis.JedisClientConfig;
 import redis.clients.jedis.JedisCluster;
@@ -635,6 +636,7 @@ private JedisClientConfig createClientConfig(int database, @Nullable String user
 			builder.user(username);
 		}
 		password.toOptional().map(String::new).ifPresent(builder::password);
+		this.clientConfiguration.getHostAndPortMapper().ifPresent(builder::hostAndPortMapper);
 
 		if (isUseSsl()) {
 
@@ -1068,6 +1070,11 @@ public Optional<HostnameVerifier> getHostnameVerifier() {
 			return Optional.ofNullable(hostnameVerifier);
 		}
 
+		@Override
+		public Optional<HostAndPortMapper> getHostAndPortMapper() {
+			return Optional.empty();
+		}
+
 		public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
 			this.hostnameVerifier = hostnameVerifier;
 		}