Skip to content

Commit ed81639

Browse files
committed
JedisConnection.close() no longer throws exceptions.
We now ensure proper exception handling in close methods to avoid resource leaks. Also, exceptions during connection close are no longer thrown to ensure proper resource cleanup behavior and API design. Closes #2356
1 parent 714f0e5 commit ed81639

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
import java.util.function.Function;
4040
import java.util.function.Supplier;
4141

42+
import org.apache.commons.logging.Log;
43+
import org.apache.commons.logging.LogFactory;
44+
4245
import org.springframework.core.convert.converter.Converter;
4346
import org.springframework.dao.DataAccessException;
4447
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -72,6 +75,8 @@
7275
*/
7376
public class JedisConnection extends AbstractRedisConnection {
7477

78+
private final Log LOGGER = LogFactory.getLog(getClass());
79+
7580
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new FallbackExceptionTranslationStrategy(
7681
JedisExceptionConverter.INSTANCE);
7782

@@ -300,8 +305,13 @@ public void close() throws DataAccessException {
300305
super.close();
301306

302307
JedisSubscription subscription = this.subscription;
303-
if (subscription != null) {
304-
subscription.close();
308+
try {
309+
if (subscription != null) {
310+
subscription.close();
311+
}
312+
} catch (Exception ex) {
313+
LOGGER.debug("Cannot terminate subscription", ex);
314+
} finally {
305315
this.subscription = null;
306316
}
307317

@@ -312,21 +322,27 @@ public void close() throws DataAccessException {
312322
}
313323

314324
// else close the connection normally (doing the try/catch dance)
315-
Exception exc = null;
325+
316326
try {
317327
jedis.quit();
318328
} catch (Exception ex) {
319-
exc = ex;
329+
LOGGER.debug("Failed to QUIT during close", ex);
320330
}
331+
321332
try {
322333
jedis.disconnect();
323334
} catch (Exception ex) {
324-
exc = ex;
335+
LOGGER.debug("Failed to disconnect during close", ex);
325336
}
337+
}
326338

327-
if (exc != null) {
328-
throw convertJedisAccessException(exc);
339+
private Exception handleCloseException(@Nullable Exception exceptionToThrow, Exception cause) {
340+
341+
if (exceptionToThrow == null) {
342+
return cause;
329343
}
344+
345+
return exceptionToThrow;
330346
}
331347

332348
@Override

src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.redis.connection.jedis;
1717

1818
import static org.assertj.core.api.Assertions.*;
19+
import static org.mockito.Mockito.*;
1920

2021
import redis.clients.jedis.JedisPoolConfig;
2122

@@ -47,6 +48,7 @@
4748
import org.springframework.data.redis.test.condition.EnabledOnRedisSentinelAvailable;
4849
import org.springframework.test.context.ContextConfiguration;
4950
import org.springframework.test.context.junit.jupiter.SpringExtension;
51+
import org.springframework.test.util.ReflectionTestUtils;
5052

5153
/**
5254
* Integration test of {@link JedisConnection}
@@ -339,6 +341,31 @@ void testPoolNPE() {
339341
factory2.destroy();
340342
}
341343

344+
@Test // GH-2356
345+
void closeWithFailureShouldReleaseConnection() {
346+
347+
JedisPoolConfig config = new JedisPoolConfig();
348+
config.setMaxTotal(1);
349+
350+
JedisConnectionFactory factory = new JedisConnectionFactory(config);
351+
factory.setUsePool(true);
352+
factory.setHostName(SettingsUtils.getHost());
353+
factory.setPort(SettingsUtils.getPort());
354+
factory.afterPropertiesSet();
355+
356+
RedisConnection conn = factory.getConnection();
357+
358+
JedisSubscription subscriptionMock = mock(JedisSubscription.class);
359+
doThrow(new IllegalStateException()).when(subscriptionMock).close();
360+
ReflectionTestUtils.setField(conn, "subscription", subscriptionMock);
361+
362+
conn.close();
363+
364+
// Make sure we don't end up with broken connection
365+
factory.getConnection().dbSize();
366+
factory.destroy();
367+
}
368+
342369
@SuppressWarnings("unchecked")
343370
@Test // DATAREDIS-285
344371
void testExecuteShouldConvertArrayReplyCorrectly() {

0 commit comments

Comments
 (0)