Skip to content

Commit e133703

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 23c3d4a commit e133703

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
@@ -28,6 +28,9 @@
2828
import java.util.function.Function;
2929
import java.util.function.Supplier;
3030

31+
import org.apache.commons.logging.Log;
32+
import org.apache.commons.logging.LogFactory;
33+
3134
import org.springframework.core.convert.converter.Converter;
3235
import org.springframework.dao.DataAccessException;
3336
import org.springframework.dao.InvalidDataAccessApiUsageException;
@@ -60,6 +63,8 @@
6063
*/
6164
public class JedisConnection extends AbstractRedisConnection {
6265

66+
private final Log LOGGER = LogFactory.getLog(getClass());
67+
6368
private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION = new FallbackExceptionTranslationStrategy(
6469
JedisConverters.exceptionConverter());
6570

@@ -332,8 +337,13 @@ public void close() throws DataAccessException {
332337
super.close();
333338

334339
JedisSubscription subscription = this.subscription;
335-
if (subscription != null) {
336-
subscription.close();
340+
try {
341+
if (subscription != null) {
342+
subscription.close();
343+
}
344+
} catch (Exception ex) {
345+
LOGGER.debug("Cannot terminate subscription", ex);
346+
} finally {
337347
this.subscription = null;
338348
}
339349

@@ -344,21 +354,27 @@ public void close() throws DataAccessException {
344354
}
345355

346356
// else close the connection normally (doing the try/catch dance)
347-
Exception exc = null;
357+
348358
try {
349359
jedis.quit();
350360
} catch (Exception ex) {
351-
exc = ex;
361+
LOGGER.debug("Failed to QUIT during close", ex);
352362
}
363+
353364
try {
354365
jedis.disconnect();
355366
} catch (Exception ex) {
356-
exc = ex;
367+
LOGGER.debug("Failed to disconnect during close", ex);
357368
}
369+
}
358370

359-
if (exc != null) {
360-
throw convertJedisAccessException(exc);
371+
private Exception handleCloseException(@Nullable Exception exceptionToThrow, Exception cause) {
372+
373+
if (exceptionToThrow == null) {
374+
return cause;
361375
}
376+
377+
return exceptionToThrow;
362378
}
363379

364380
/*

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}
@@ -340,6 +342,31 @@ void testPoolNPE() {
340342
factory2.destroy();
341343
}
342344

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

0 commit comments

Comments
 (0)