JedisConnection
instance.
*
- * @param jedis Jedis entity
+ * @param jedis Jedis entity, must not be {@literal null}.
*/
public JedisConnection(Jedis jedis) {
this(jedis, null, 0);
@@ -190,17 +194,34 @@ public JedisConnection(Jedis jedis) {
/**
* Constructs a new JedisConnection
instance backed by a jedis pool.
*
- * @param jedis
- * @param pool can be null, if no pool is used
+ * @param jedis must not be {@literal null}.
+ * @param pool may be {@literal null}, if no pool is used.
+ * @param dbIndex
*/
public JedisConnection(Jedis jedis, Pool+ * Connection references allow executing Redis commands even if the original connection is closed. This is required if + * operations hold a reference to this {@link JedisConnection} and are executed after this connection was + * closed/released back to the pool. + *
+ * Creating connection references after closing this connection requires the {@code connectionFactory} to be set.
+ *
+ * @return a {@link JedisConnectionReference} pointing to an active {@link JedisConnection}.
+ */
+ private JedisConnectionReference getOrCreateConnectionReference() {
+
+ if (!closed) {
+ return new JedisConnectionReference(this);
+ }
+
+ if (connectionFactory == null) {
+ throw new IllegalStateException(
+ "Cannot obtain a Jedis connection: Connection closed and no connection factory reference provided");
+ }
+
+ return new JedisConnectionFactoryReference(connectionFactory);
}
+ /**
+ * Connection reference for {@link Jedis}. Connection references can be released to clean up resources, if necessary.
+ *
+ * @author Mark Paluch
+ * @since 1.8
+ */
+ private static class JedisConnectionReference {
+
+ final Jedis jedis;
+ final JedisConnection jedisConnection;
+
+ JedisConnectionReference(JedisConnection jedisConnection) {
+
+ this.jedisConnection = jedisConnection;
+ this.jedis = jedisConnection.jedis;
+ }
+
+ public void release() {
+ doRelease();
+ }
+
+ /**
+ * Customization hook for cleaning up resources on when calling {@link #release()}.
+ */
+ void doRelease() {
+ }
+ }
+
+ /**
+ * {@link JedisConnectionReference} implementation to obtain a connection from a {@link RedisConnectionFactory}.
+ * Connections are release when {@link #release() releasing} this reference.
+ *
+ * @author Mark Paluch
+ * @since 1.8
+ */
+ private static class JedisConnectionFactoryReference extends JedisConnectionReference {
+
+ JedisConnectionFactoryReference(RedisConnectionFactory redisConnectionFactory) {
+ super((JedisConnection) redisConnectionFactory.getConnection());
+ }
+
+ @Override
+ void doRelease() {
+ jedisConnection.close();
+ }
+ }
}
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 4db269dafe..c04b0da61b 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
@@ -341,8 +341,8 @@ public RedisConnection getConnection() {
}
Jedis jedis = fetchJedisConnector();
- JedisConnection connection = (usePool ? new JedisConnection(jedis, pool, dbIndex)
- : new JedisConnection(jedis, null, dbIndex));
+ JedisConnection connection = (usePool ? new JedisConnection(jedis, pool, this, dbIndex)
+ : new JedisConnection(jedis, null, this, dbIndex));
connection.setConvertPipelineAndTxResults(convertPipelineAndTxResults);
return postProcessConnection(connection);
}
diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java
index 64615097c7..c9c0f8b3a2 100644
--- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java
+++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2015 the original author or authors.
+ * Copyright 2011-2016 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.
@@ -16,12 +16,17 @@
package org.springframework.data.redis.connection.jedis;
-import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
@@ -45,6 +50,8 @@
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.connection.StringRedisConnection.StringTuple;
+import org.springframework.data.redis.core.Cursor;
+import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.test.util.RedisSentinelRule;
import org.springframework.data.redis.test.util.RedisSentinelRule.SentinelsAvailable;
import org.springframework.data.redis.test.util.RelaxedJUnit4ClassRunner;
@@ -62,6 +69,7 @@
* @author Thomas Darimont
* @author Christoph Strobl
* @author David Liu
+ * @author Mark Paluch
*/
@RunWith(RelaxedJUnit4ClassRunner.class)
@ContextConfiguration
@@ -416,4 +424,103 @@ public void zRangeByScoreTest() {
assertEquals("two", new String(zRangeByScore.iterator().next()));
}
+
+ /**
+ * @see DATAREDIS-531
+ */
+ @Test
+ public void scanShouldOperateOnActiveConnection() throws IOException {
+
+ connection.set("key", "value");
+
+ Cursor