Skip to content

Commit 2c0d2a5

Browse files
prateek-kumar-improvingalexr-bq
authored andcommitted
Java: SSL/TLS for Jedis compatibility layer (#4613)
* Java: SSL/TLS for Jedis compatibility layer Signed-off-by: Prateek Kumar <prateek.kumar@improving.com> Signed-off-by: Alex Rehnby-Martin <alex.rehnby-martin@improving.com>
1 parent e59c2ae commit 2c0d2a5

File tree

8 files changed

+693
-59
lines changed

8 files changed

+693
-59
lines changed

java/client/src/main/java/redis/clients/jedis/ConfigurationMapper.java

Lines changed: 285 additions & 43 deletions
Large diffs are not rendered by default.

java/client/src/main/java/redis/clients/jedis/DefaultJedisClientConfig.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class DefaultJedisClientConfig implements JedisClientConfig {
2626
private final SSLSocketFactory sslSocketFactory;
2727
private final SSLParameters sslParameters;
2828
private final HostnameVerifier hostnameVerifier;
29+
private final SslOptions sslOptions;
2930
private final RedisProtocol redisProtocol;
3031

3132
private DefaultJedisClientConfig(Builder builder) {
@@ -40,6 +41,7 @@ private DefaultJedisClientConfig(Builder builder) {
4041
this.sslSocketFactory = builder.sslSocketFactory;
4142
this.sslParameters = builder.sslParameters;
4243
this.hostnameVerifier = builder.hostnameVerifier;
44+
this.sslOptions = builder.sslOptions;
4345
this.redisProtocol = builder.redisProtocol;
4446
}
4547

@@ -102,6 +104,11 @@ public HostnameVerifier getHostnameVerifier() {
102104
return hostnameVerifier;
103105
}
104106

107+
@Override
108+
public SslOptions getSslOptions() {
109+
return sslOptions;
110+
}
111+
105112
@Override
106113
public RedisProtocol getRedisProtocol() {
107114
return redisProtocol;
@@ -119,6 +126,7 @@ public static class Builder {
119126
private SSLSocketFactory sslSocketFactory;
120127
private SSLParameters sslParameters;
121128
private HostnameVerifier hostnameVerifier;
129+
private SslOptions sslOptions;
122130
private RedisProtocol redisProtocol = DEFAULT_PROTOCOL;
123131

124132
public Builder connectionTimeoutMillis(int connectionTimeoutMillis) {
@@ -176,6 +184,11 @@ public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) {
176184
return this;
177185
}
178186

187+
public Builder sslOptions(SslOptions sslOptions) {
188+
this.sslOptions = sslOptions;
189+
return this;
190+
}
191+
179192
public Builder protocol(RedisProtocol redisProtocol) {
180193
this.redisProtocol = redisProtocol;
181194
return this;

java/client/src/main/java/redis/clients/jedis/Jedis.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,9 @@ public Jedis(String host, int port, JedisClientConfig config) {
153153
this.parentPool = null;
154154
this.config = config;
155155

156-
// Validate configuration
157-
ConfigurationMapper.validateConfiguration(config);
158-
159156
// Defer GlideClient creation until first Redis operation (lazy initialization)
160157
// This solves DataGrip compatibility issues with native library loading
158+
// Configuration validation happens during mapping when GlideClient is created
161159
this.glideClient = null;
162160
this.resourceId = null;
163161
this.lazyInitialized = false;
@@ -190,6 +188,14 @@ private synchronized void ensureInitialized() {
190188
this.resourceId = ResourceLifecycleManager.getInstance().registerResource(this);
191189
i++;
192190
this.lazyInitialized = true;
191+
} catch (ConfigurationMapper.JedisConfigurationException e) {
192+
// Enhanced error handling for configuration conversion issues
193+
throw new JedisConnectionException(
194+
"Failed to convert Jedis configuration to GLIDE: "
195+
+ e.getMessage()
196+
+ ". Please check your SSL/TLS certificate configuration or consider using PEM format"
197+
+ " certificates.",
198+
e);
193199
} catch (InterruptedException | ExecutionException e) {
194200
throw new JedisConnectionException("Failed to create GLIDE client", e);
195201
} catch (RuntimeException e) {
@@ -719,6 +725,15 @@ public void close() {
719725
throw new JedisException("Failed to close GLIDE client", e);
720726
}
721727
}
728+
729+
// Cleanup temporary certificate files created during configuration conversion
730+
try {
731+
ConfigurationMapper.cleanupTempFiles();
732+
} catch (Exception e) {
733+
// Log warning but don't fail the close operation
734+
System.err.println("Warning: Failed to cleanup temporary certificate files:");
735+
e.printStackTrace();
736+
}
722737
}
723738

724739
/**
@@ -6797,4 +6812,23 @@ public String brpoplpush(String source, String destination, int timeout) {
67976812
public byte[] brpoplpush(final byte[] source, final byte[] destination, int timeout) {
67986813
return blmove(source, destination, ListDirection.RIGHT, ListDirection.LEFT, timeout);
67996814
}
6815+
6816+
// Static initialization block for cleanup hooks
6817+
static {
6818+
// Add shutdown hook to cleanup temporary certificate files
6819+
Runtime.getRuntime()
6820+
.addShutdownHook(
6821+
new Thread(
6822+
() -> {
6823+
try {
6824+
ConfigurationMapper.cleanupTempFiles();
6825+
} catch (Exception e) {
6826+
// Ignore exceptions during shutdown
6827+
System.err.println(
6828+
"Warning: Failed to cleanup temporary certificate files during shutdown:");
6829+
e.printStackTrace();
6830+
}
6831+
},
6832+
"Jedis-Certificate-Cleanup"));
6833+
}
68006834
}

java/client/src/main/java/redis/clients/jedis/JedisPool.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ public JedisPool(
126126
this.availableConnections = new LinkedBlockingQueue<>();
127127
this.poolId = ResourceLifecycleManager.getInstance().registerResource(this);
128128

129-
// Validate configuration
130-
ConfigurationMapper.validateConfiguration(config);
129+
// Configuration validation happens during mapping when connections are created
131130
}
132131

133132
/**
@@ -192,8 +191,8 @@ protected void returnResource(Jedis jedis) {
192191
jedis.getGlideClient().close();
193192
} catch (Exception e) {
194193
// Log error but don't throw - we're in cleanup mode
195-
System.err.println(
196-
"Warning: Failed to close Jedis connection when pool queue full: " + e.getMessage());
194+
System.err.println("Warning: Failed to close Jedis connection when pool queue full:");
195+
e.printStackTrace();
197196
}
198197
}
199198
} else if (jedis != null) {
@@ -204,7 +203,8 @@ protected void returnResource(Jedis jedis) {
204203
jedis.getGlideClient().close();
205204
} catch (Exception e) {
206205
// Log error but continue
207-
System.err.println("Error closing returned connection: " + e.getMessage());
206+
System.err.println("Error closing returned connection:");
207+
e.printStackTrace();
208208
}
209209
}
210210
}
@@ -240,7 +240,8 @@ public void close() {
240240
jedis.getGlideClient().close();
241241
} catch (Exception e) {
242242
// Log error but continue closing other connections
243-
System.err.println("Error closing connection: " + e.getMessage());
243+
System.err.println("Error closing connection:");
244+
e.printStackTrace();
244245
}
245246
}
246247

java/client/src/main/java/redis/clients/jedis/ResourceLifecycleManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ private void closeQuietly(AutoCloseable resource) {
160160
resource.close();
161161
} catch (Exception e) {
162162
// Log the error but don't throw
163-
System.err.println("Error closing resource: " + e.getMessage());
163+
System.err.println("Error closing resource:");
164+
e.printStackTrace();
164165
}
165166
}
166167
}

0 commit comments

Comments
 (0)