diff --git a/.gitignore b/.gitignore index 0699953e0..de8921796 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ target bin build +bin .gradle .springBeans .ant-targets-build.xml diff --git a/docs/src/reference/docbook/reference/redis-messaging.xml b/docs/src/reference/docbook/reference/redis-messaging.xml index ea53d6ba5..7bfbc8508 100644 --- a/docs/src/reference/docbook/reference/redis-messaging.xml +++ b/docs/src/reference/docbook/reference/redis-messaging.xml @@ -162,6 +162,7 @@ template.convertAndSend("hello!", "world");]]> ... <beans> + The listener topic can be either a channel (e.g. topic="chatroom") or a pattern (e.g. topic="*room") The example above uses the Redis namespace to declare the message listener container and automatically register the POJOs as listeners. The full blown, beans definition is displayed below: diff --git a/docs/src/reference/docbook/reference/redis.xml b/docs/src/reference/docbook/reference/redis.xml index 98d4a8eff..df2ece116 100644 --- a/docs/src/reference/docbook/reference/redis.xml +++ b/docs/src/reference/docbook/reference/redis.xml @@ -18,7 +18,7 @@ Redis Requirements SDKV requires Redis 2.0 or above (Redis 2.2 is recommended) and Java SE 6.0 or above. In terms of language bindings (or connectors), SDKV integrates with Jedis, - JRedis and RJC, three popular open source Java libraries for Redis. + JRedis and RJC, three popular open source Java libraries for Redis. If you are aware of any other connector that we should be integrating is, please send us feedback. @@ -144,6 +144,36 @@ + +
+ Configuring RJC connector + + RJC is the third, open-source connector supported by SDKV through the + org.springframework.data.keyvalue.redis.connection.rjc package. + + Similar to the other connectors, a typical RJC configuration can looks like this: + + + + + +]]> + + As one can note, the configuration is quite similar to the Jredis or Jedis one. + + Currently, RJC does not have support for binary keys. This forces the RjcConnection to perform encoding internally + (through base64 schema). In practice, this means it's safe to read/write arbitrary data however + the Redis key stored values will differ from the decoded ones, even in the simplest cases, since everything (no matter the format) is encoded. This will not be + the case for Redis values. + This issue is currently being addressed in the RJC project and once fixed, will be incorporated by Spring Data Redis. + + +
diff --git a/spring-data-redis/.classpath b/spring-data-redis/.classpath index 954aad0d1..67688ee1b 100644 --- a/spring-data-redis/.classpath +++ b/spring-data-redis/.classpath @@ -27,7 +27,7 @@ - + diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/DefaultStringRedisConnection.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/DefaultStringRedisConnection.java index 04484b29f..61b973ed3 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/DefaultStringRedisConnection.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/DefaultStringRedisConnection.java @@ -516,16 +516,32 @@ public class DefaultStringRedisConnection implements StringRedisConnection { return delegate.zRangeByScore(key, min, max); } - public Set zRangeByScoreWithScore(byte[] key, double min, double max, long offset, long count) { - return delegate.zRangeByScoreWithScore(key, min, max, offset, count); + public Set zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { + return delegate.zRangeByScoreWithScores(key, min, max, offset, count); } - public Set zRangeByScoreWithScore(byte[] key, double min, double max) { - return delegate.zRangeByScoreWithScore(key, min, max); + public Set zRangeByScoreWithScores(byte[] key, double min, double max) { + return delegate.zRangeByScoreWithScores(key, min, max); } - public Set zRangeWithScore(byte[] key, long start, long end) { - return delegate.zRangeWithScore(key, start, end); + public Set zRangeWithScores(byte[] key, long start, long end) { + return delegate.zRangeWithScores(key, start, end); + } + + public Set zRevRangeByScore(byte[] key, double min, double max, long offset, long count) { + return delegate.zRevRangeByScore(key, min, max, offset, count); + } + + public Set zRevRangeByScore(byte[] key, double min, double max) { + return delegate.zRevRangeByScore(key, min, max); + } + + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { + return delegate.zRevRangeByScoreWithScores(key, min, max, offset, count); + } + + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max) { + return delegate.zRevRangeByScoreWithScores(key, min, max); } public Long zRank(byte[] key, byte[] value) { @@ -548,8 +564,8 @@ public class DefaultStringRedisConnection implements StringRedisConnection { return delegate.zRevRange(key, start, end); } - public Set zRevRangeWithScore(byte[] key, long start, long end) { - return delegate.zRevRangeWithScore(key, start, end); + public Set zRevRangeWithScores(byte[] key, long start, long end) { + return delegate.zRevRangeWithScores(key, start, end); } public Long zRevRank(byte[] key, byte[] value) { @@ -1058,18 +1074,18 @@ public class DefaultStringRedisConnection implements StringRedisConnection { } @Override - public Set zRangeByScoreWithScore(String key, double min, double max, long offset, long count) { - return deserializeTuple(delegate.zRangeByScoreWithScore(serialize(key), min, max, offset, count)); + public Set zRangeByScoreWithScores(String key, double min, double max, long offset, long count) { + return deserializeTuple(delegate.zRangeByScoreWithScores(serialize(key), min, max, offset, count)); } @Override - public Set zRangeByScoreWithScore(String key, double min, double max) { - return deserializeTuple(delegate.zRangeByScoreWithScore(serialize(key), min, max)); + public Set zRangeByScoreWithScores(String key, double min, double max) { + return deserializeTuple(delegate.zRangeByScoreWithScores(serialize(key), min, max)); } @Override - public Set zRangeWithScore(String key, long start, long end) { - return deserializeTuple(delegate.zRangeWithScore(serialize(key), start, end)); + public Set zRangeWithScores(String key, long start, long end) { + return deserializeTuple(delegate.zRangeWithScores(serialize(key), start, end)); } @Override @@ -1098,8 +1114,8 @@ public class DefaultStringRedisConnection implements StringRedisConnection { } @Override - public Set zRevRangeWithScore(String key, long start, long end) { - return deserializeTuple(delegate.zRevRangeWithScore(serialize(key), start, end)); + public Set zRevRangeWithScores(String key, long start, long end) { + return deserializeTuple(delegate.zRevRangeWithScores(serialize(key), start, end)); } @Override diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/RedisZSetCommands.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/RedisZSetCommands.java index eacc7de72..ff6073b8c 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/RedisZSetCommands.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/RedisZSetCommands.java @@ -54,19 +54,27 @@ public interface RedisZSetCommands { Set zRange(byte[] key, long begin, long end); - Set zRangeWithScore(byte[] key, long begin, long end); - - Set zRevRange(byte[] key, long begin, long end); - - Set zRevRangeWithScore(byte[] key, long begin, long end); + Set zRangeWithScores(byte[] key, long begin, long end); Set zRangeByScore(byte[] key, double min, double max); - Set zRangeByScoreWithScore(byte[] key, double min, double max); + Set zRangeByScoreWithScores(byte[] key, double min, double max); Set zRangeByScore(byte[] key, double min, double max, long offset, long count); - Set zRangeByScoreWithScore(byte[] key, double min, double max, long offset, long count); + Set zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count); + + Set zRevRange(byte[] key, long begin, long end); + + Set zRevRangeWithScores(byte[] key, long begin, long end); + + Set zRevRangeByScore(byte[] key, double min, double max); + + Set zRevRangeByScoreWithScores(byte[] key, double min, double max); + + Set zRevRangeByScore(byte[] key, double min, double max, long offset, long count); + + Set zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count); Long zCount(byte[] key, double min, double max); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/StringRedisConnection.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/StringRedisConnection.java index 28886d595..fc7c170aa 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/StringRedisConnection.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/StringRedisConnection.java @@ -181,19 +181,19 @@ public interface StringRedisConnection extends RedisConnection { Set zRange(String key, long start, long end); - Set zRangeWithScore(String key, long start, long end); + Set zRangeWithScores(String key, long start, long end); Set zRevRange(String key, long start, long end); - Set zRevRangeWithScore(String key, long start, long end); + Set zRevRangeWithScores(String key, long start, long end); Set zRangeByScore(String key, double min, double max); - Set zRangeByScoreWithScore(String key, double min, double max); + Set zRangeByScoreWithScores(String key, double min, double max); Set zRangeByScore(String key, double min, double max, long offset, long count); - Set zRangeByScoreWithScore(String key, double min, double max, long offset, long count); + Set zRangeByScoreWithScores(String key, double min, double max, long offset, long count); Long zCount(String key, double min, double max); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisConnection.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisConnection.java index 0d751765a..363e7c920 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisConnection.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisConnection.java @@ -40,7 +40,6 @@ import redis.clients.jedis.BinaryTransaction; import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; -import redis.clients.jedis.Protocol; import redis.clients.jedis.SortingParams; import redis.clients.jedis.Transaction; import redis.clients.jedis.ZParams; @@ -194,7 +193,7 @@ public class JedisConnection implements RedisConnection { @Override public List closePipeline() { if (pipeline != null) { - List execute = pipeline.execute(); + List execute = pipeline.syncAndReturnAll(); if (execute != null && !execute.isEmpty()) { return execute; } @@ -270,8 +269,7 @@ public class JedisConnection implements RedisConnection { public Long dbSize() { try { if (isQueueing()) { - transaction.dbSize(); - return null; + throw new UnsupportedOperationException(); } if (isPipelined()) { throw new UnsupportedOperationException(); @@ -287,8 +285,7 @@ public class JedisConnection implements RedisConnection { public void flushDb() { try { if (isQueueing()) { - transaction.flushDB(); - return; + throw new UnsupportedOperationException(); } if (isPipelined()) { throw new UnsupportedOperationException(); @@ -303,8 +300,7 @@ public class JedisConnection implements RedisConnection { public void flushAll() { try { if (isQueueing()) { - transaction.flushAll(); - return; + throw new UnsupportedOperationException(); } if (isPipelined()) { throw new UnsupportedOperationException(); @@ -478,8 +474,7 @@ public class JedisConnection implements RedisConnection { public String ping() { try { if (isQueueing()) { - transaction.ping(); - return null; + throw new UnsupportedOperationException(); } if (isPipelined()) { throw new UnsupportedOperationException(); @@ -651,8 +646,7 @@ public class JedisConnection implements RedisConnection { public byte[] randomKey() { try { if (isQueueing()) { - transaction.randomBinaryKey(); - return null; + throw new UnsupportedOperationException(); } if (isPipelined()) { throw new UnsupportedOperationException(); @@ -701,8 +695,7 @@ public class JedisConnection implements RedisConnection { public void select(int dbIndex) { try { if (isQueueing()) { - transaction.select(dbIndex); - return; + throw new UnsupportedOperationException(); } if (isPipelined()) { throw new UnsupportedOperationException(); @@ -1024,8 +1017,6 @@ public class JedisConnection implements RedisConnection { public Boolean getBit(byte[] key, long offset) { try { if (isQueueing()) { - // transaction.getbit(key, (int) offset); - // return null; throw new UnsupportedOperationException(); } if (isPipelined()) { @@ -1041,8 +1032,6 @@ public class JedisConnection implements RedisConnection { public void setBit(byte[] key, long offset, boolean value) { try { if (isQueueing()) { - // transaction.setbit(key, (int) offset, JedisUtils.asBit(value)); - // return; throw new UnsupportedOperationException(); } if (isPipelined()) { @@ -1056,14 +1045,25 @@ public class JedisConnection implements RedisConnection { @Override public void setRange(byte[] key, byte[] value, long start) { - throw new UnsupportedOperationException(); + try { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + jedis.setrange(key, start, value); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } } @Override public Long strLen(byte[] key) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.strlen(key); + return null; } if (isPipelined()) { pipeline.strlen(key); @@ -1117,15 +1117,11 @@ public class JedisConnection implements RedisConnection { public List bLPop(int timeout, byte[]... keys) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.blpop(JedisUtils.bXPopArgs(timeout, keys)); + return null; } if (isPipelined()) { - final List args = new ArrayList(); - for (final byte[] arg : keys) { - args.add(arg); - } - args.add(Protocol.toByteArray(timeout)); - pipeline.blpop(args.toArray(new byte[args.size()][])); + pipeline.blpop(JedisUtils.bXPopArgs(timeout, keys)); return null; } return jedis.blpop(timeout, keys); @@ -1138,15 +1134,10 @@ public class JedisConnection implements RedisConnection { public List bRPop(int timeout, byte[]... keys) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.brpop(JedisUtils.bXPopArgs(timeout, keys)); } if (isPipelined()) { - final List args = new ArrayList(); - for (final byte[] arg : keys) { - args.add(arg); - } - args.add(Protocol.toByteArray(timeout)); - pipeline.brpop(args.toArray(new byte[args.size()][])); + pipeline.brpop(JedisUtils.bXPopArgs(timeout, keys)); return null; } return jedis.brpop(timeout, keys); @@ -1176,9 +1167,8 @@ public class JedisConnection implements RedisConnection { public Long lInsert(byte[] key, Position where, byte[] pivot, byte[] value) { try { if (isQueueing()) { - // transaction.linsert(key, JedisUtils.convertPosition(where), pivot, value); - // return null; - throw new UnsupportedOperationException(); + transaction.linsert(key, JedisUtils.convertPosition(where), pivot, value); + return null; } if (isPipelined()) { pipeline.linsert(key, JedisUtils.convertPosition(where), pivot, value); @@ -1330,7 +1320,8 @@ public class JedisConnection implements RedisConnection { public byte[] bRPopLPush(int timeout, byte[] srcKey, byte[] dstKey) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.brpoplpush(srcKey, dstKey, timeout); + return null; } if (isPipelined()) { pipeline.brpoplpush(srcKey, dstKey, timeout); @@ -1346,7 +1337,8 @@ public class JedisConnection implements RedisConnection { public Long lPushX(byte[] key, byte[] value) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.lpushx(key, value); + return null; } if (isPipelined()) { pipeline.lpushx(key, value); @@ -1362,7 +1354,8 @@ public class JedisConnection implements RedisConnection { public Long rPushX(byte[] key, byte[] value) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.rpushx(key, value); + return null; } if (isPipelined()) { pipeline.rpushx(key, value); @@ -1659,7 +1652,8 @@ public class JedisConnection implements RedisConnection { public Long zCount(byte[] key, double min, double max) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zcount(key, min, max); + return null; } if (isQueueing()) { pipeline.zcount(key, min, max); @@ -1691,11 +1685,13 @@ public class JedisConnection implements RedisConnection { @Override public Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) { try { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } ZParams zparams = new ZParams().weights(weights).aggregate( redis.clients.jedis.ZParams.Aggregate.valueOf(aggregate.name())); + + if (isQueueing()) { + transaction.zinterstore(destKey, zparams, sets); + return null; + } if (isPipelined()) { pipeline.zinterstore(destKey, zparams, sets); return null; @@ -1710,7 +1706,8 @@ public class JedisConnection implements RedisConnection { public Long zInterStore(byte[] destKey, byte[]... sets) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zinterstore(destKey, sets); + return null; } if (isQueueing()) { pipeline.zinterstore(destKey, sets); @@ -1740,7 +1737,7 @@ public class JedisConnection implements RedisConnection { } @Override - public Set zRangeWithScore(byte[] key, long start, long end) { + public Set zRangeWithScores(byte[] key, long start, long end) { try { if (isQueueing()) { transaction.zrangeWithScores(key, (int) start, (int) end); @@ -1760,7 +1757,8 @@ public class JedisConnection implements RedisConnection { public Set zRangeByScore(byte[] key, double min, double max) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zrangeByScore(key, min, max); + return null; } if (isPipelined()) { pipeline.zrangeByScore(key, min, max); @@ -1773,10 +1771,11 @@ public class JedisConnection implements RedisConnection { } @Override - public Set zRangeByScoreWithScore(byte[] key, double min, double max) { + public Set zRangeByScoreWithScores(byte[] key, double min, double max) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zrangeByScoreWithScores(key, min, max); + return null; } if (isPipelined()) { pipeline.zrangeByScoreWithScores(key, min, max); @@ -1789,16 +1788,17 @@ public class JedisConnection implements RedisConnection { } @Override - public Set zRevRangeWithScore(byte[] key, long start, long end) { + public Set zRevRangeWithScores(byte[] key, long start, long end) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); - } - if (isPipelined()) { - pipeline.zrangeByScoreWithScores(key, (int) start, (int) end); + transaction.zrevrangeWithScores(key, (int) start, (int) end); return null; } - return JedisUtils.convertJedisTuple(jedis.zrangeByScoreWithScores(key, (int) start, (int) end)); + if (isPipelined()) { + pipeline.zrevrangeWithScores(key, (int) start, (int) end); + return null; + } + return JedisUtils.convertJedisTuple(jedis.zrevrangeWithScores(key, (int) start, (int) end)); } catch (Exception ex) { throw convertJedisAccessException(ex); } @@ -1808,7 +1808,8 @@ public class JedisConnection implements RedisConnection { public Set zRangeByScore(byte[] key, double min, double max, long offset, long count) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zrangeByScore(key, min, max, (int) offset, (int) count); + return null; } if (isPipelined()) { pipeline.zrangeByScore(key, min, max, (int) offset, (int) count); @@ -1821,10 +1822,11 @@ public class JedisConnection implements RedisConnection { } @Override - public Set zRangeByScoreWithScore(byte[] key, double min, double max, long offset, long count) { + public Set zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zrangeByScoreWithScores(key, min, max, (int) offset, (int) count); + return null; } if (isPipelined()) { pipeline.zrangeByScoreWithScores(key, min, max, (int) offset, (int) count); @@ -1836,6 +1838,66 @@ public class JedisConnection implements RedisConnection { } } + @Override + public Set zRevRangeByScore(byte[] key, double min, double max, long offset, long count) { + try { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + throw new UnsupportedOperationException(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + @Override + public Set zRevRangeByScore(byte[] key, double min, double max) { + try { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + throw new UnsupportedOperationException(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + @Override + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { + try { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + throw new UnsupportedOperationException(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + @Override + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max) { + try { + if (isQueueing()) { + throw new UnsupportedOperationException(); + } + if (isPipelined()) { + throw new UnsupportedOperationException(); + } + throw new UnsupportedOperationException(); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + @Override public Long zRank(byte[] key, byte[] value) { try { @@ -1874,7 +1936,8 @@ public class JedisConnection implements RedisConnection { public Long zRemRange(byte[] key, long start, long end) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zremrangeByRank(key, (int) start, (int) end); + return null; } if (isPipelined()) { pipeline.zremrangeByRank(key, (int) start, (int) end); @@ -1890,7 +1953,8 @@ public class JedisConnection implements RedisConnection { public Long zRemRangeByScore(byte[] key, double min, double max) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zremrangeByScore(key, min, max); + return null; } if (isPipelined()) { pipeline.zremrangeByScore(key, min, max); @@ -1956,11 +2020,13 @@ public class JedisConnection implements RedisConnection { @Override public Long zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) { try { - if (isQueueing()) { - throw new UnsupportedOperationException(); - } ZParams zparams = new ZParams().weights(weights).aggregate( redis.clients.jedis.ZParams.Aggregate.valueOf(aggregate.name())); + + if (isQueueing()) { + transaction.zunionstore(destKey, zparams, sets); + return null; + } if (isPipelined()) { pipeline.zunionstore(destKey, zparams, sets); return null; @@ -1975,7 +2041,8 @@ public class JedisConnection implements RedisConnection { public Long zUnionStore(byte[] destKey, byte[]... sets) { try { if (isQueueing()) { - throw new UnsupportedOperationException(); + transaction.zunionstore(destKey, sets); + return null; } if (isPipelined()) { pipeline.zunionstore(destKey, sets); @@ -2206,7 +2273,8 @@ public class JedisConnection implements RedisConnection { throw new UnsupportedOperationException(); } if (isPipelined()) { - throw new UnsupportedOperationException(); + pipeline.publish(channel, message); + return null; } return jedis.publish(channel, message); } catch (Exception ex) { diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisUtils.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisUtils.java index 06b0011da..f02e30fd8 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisUtils.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jedis/JedisUtils.java @@ -19,8 +19,10 @@ package org.springframework.data.keyvalue.redis.connection.jedis; import java.io.IOException; import java.io.StringReader; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -40,6 +42,7 @@ import org.springframework.data.keyvalue.redis.connection.SortParameters.Range; import org.springframework.util.Assert; import redis.clients.jedis.BinaryJedisPubSub; +import redis.clients.jedis.Protocol; import redis.clients.jedis.SortingParams; import redis.clients.jedis.BinaryClient.LIST_POSITION; import redis.clients.jedis.exceptions.JedisConnectionException; @@ -218,4 +221,13 @@ public abstract class JedisUtils { return result; } + + static byte[][] bXPopArgs(int timeout, byte[]... keys) { + final List args = new ArrayList(); + for (final byte[] arg : keys) { + args.add(arg); + } + args.add(Protocol.toByteArray(timeout)); + return args.toArray(new byte[args.size()][]); + } } \ No newline at end of file diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jredis/JredisConnection.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jredis/JredisConnection.java index ada3441e1..00433eee2 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jredis/JredisConnection.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/jredis/JredisConnection.java @@ -886,9 +886,8 @@ public class JredisConnection implements RedisConnection { } @Override - public Set zRangeWithScore(byte[] key, long start, long end) { + public Set zRangeWithScores(byte[] key, long start, long end) { throw new UnsupportedOperationException(); - } @Override @@ -901,7 +900,7 @@ public class JredisConnection implements RedisConnection { } @Override - public Set zRangeByScoreWithScore(byte[] key, double min, double max) { + public Set zRangeByScoreWithScores(byte[] key, double min, double max) { throw new UnsupportedOperationException(); } @@ -911,7 +910,27 @@ public class JredisConnection implements RedisConnection { } @Override - public Set zRangeByScoreWithScore(byte[] key, double min, double max, long offset, long count) { + public Set zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { + throw new UnsupportedOperationException(); + } + + @Override + public Set zRevRangeByScore(byte[] key, double min, double max, long offset, long count) { + throw new UnsupportedOperationException(); + } + + @Override + public Set zRevRangeByScore(byte[] key, double min, double max) { + throw new UnsupportedOperationException(); + } + + @Override + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { + throw new UnsupportedOperationException(); + } + + @Override + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max) { throw new UnsupportedOperationException(); } @@ -961,7 +980,7 @@ public class JredisConnection implements RedisConnection { } @Override - public Set zRevRangeWithScore(byte[] key, long start, long end) { + public Set zRevRangeWithScores(byte[] key, long start, long end) { throw new UnsupportedOperationException(); } diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/rjc/RjcConnection.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/rjc/RjcConnection.java index 5b9c739a1..1176fc57d 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/rjc/RjcConnection.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/connection/rjc/RjcConnection.java @@ -1547,7 +1547,7 @@ public class RjcConnection implements RedisConnection { } @Override - public Set zRangeWithScore(byte[] key, long start, long end) { + public Set zRangeWithScores(byte[] key, long start, long end) { String stringKey = RjcUtils.decode(key); try { @@ -1578,41 +1578,6 @@ public class RjcConnection implements RedisConnection { } } - @Override - public Set zRangeByScoreWithScore(byte[] key, double min, double max) { - String stringKey = RjcUtils.decode(key); - String minString = Double.toString(min); - String maxString = Double.toString(max); - - try { - if (isPipelined()) { - pipeline.zrangeByScoreWithScores(stringKey, minString, maxString); - return null; - } - return RjcUtils.convertElementScore(session.zrangeByScoreWithScores(stringKey, minString, maxString)); - } catch (Exception ex) { - throw convertRjcAccessException(ex); - } - } - - @Override - public Set zRevRangeWithScore(byte[] key, long start, long end) { - String stringKey = RjcUtils.decode(key); - String minString = Long.toString(start); - String maxString = Long.toString(end); - - try { - - if (isPipelined()) { - pipeline.zrangeByScoreWithScores(stringKey, minString, maxString); - return null; - } - return RjcUtils.convertElementScore(session.zrangeByScoreWithScores(stringKey, minString, maxString)); - } catch (Exception ex) { - throw convertRjcAccessException(ex); - } - } - @Override public Set zRangeByScore(byte[] key, double min, double max, long offset, long count) { String stringKey = RjcUtils.decode(key); @@ -1631,8 +1596,79 @@ public class RjcConnection implements RedisConnection { } } + @Override - public Set zRangeByScoreWithScore(byte[] key, double min, double max, long offset, long count) { + public Set zRevRangeByScore(byte[] key, double min, double max, long offset, long count) { + String stringKey = RjcUtils.decode(key); + String minString = Double.toString(min); + String maxString = Double.toString(max); + + try { + if (isPipelined()) { + pipeline.zrevrangeByScore(stringKey, minString, maxString, (int) offset, (int) count); + return null; + } + return RjcUtils.convertToSet(session.zrevrangeByScore(stringKey, minString, maxString, (int) offset, + (int) count)); + } catch (Exception ex) { + throw convertRjcAccessException(ex); + } + } + + @Override + public Set zRevRangeByScore(byte[] key, double min, double max) { + String stringKey = RjcUtils.decode(key); + String minString = Double.toString(min); + String maxString = Double.toString(max); + + try { + if (isPipelined()) { + pipeline.zrevrangeByScore(stringKey, minString, maxString); + return null; + } + return RjcUtils.convertToSet(session.zrevrangeByScore(stringKey, minString, maxString)); + } catch (Exception ex) { + throw convertRjcAccessException(ex); + } + } + + @Override + public Set zRangeByScoreWithScores(byte[] key, double min, double max) { + String stringKey = RjcUtils.decode(key); + String minString = Double.toString(min); + String maxString = Double.toString(max); + + try { + if (isPipelined()) { + pipeline.zrangeByScoreWithScores(stringKey, minString, maxString); + return null; + } + return RjcUtils.convertElementScore(session.zrangeByScoreWithScores(stringKey, minString, maxString)); + } catch (Exception ex) { + throw convertRjcAccessException(ex); + } + } + + @Override + public Set zRevRangeWithScores(byte[] key, long start, long end) { + String stringKey = RjcUtils.decode(key); + String minString = Long.toString(start); + String maxString = Long.toString(end); + + try { + + if (isPipelined()) { + pipeline.zrevrangeByScoreWithScores(stringKey, minString, maxString); + return null; + } + return RjcUtils.convertElementScore(session.zrevrangeByScoreWithScores(stringKey, minString, maxString)); + } catch (Exception ex) { + throw convertRjcAccessException(ex); + } + } + + @Override + public Set zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { String stringKey = RjcUtils.decode(key); String minString = Double.toString(min); String maxString = Double.toString(max); @@ -1649,6 +1685,44 @@ public class RjcConnection implements RedisConnection { } } + + @Override + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) { + String stringKey = RjcUtils.decode(key); + String minString = Double.toString(min); + String maxString = Double.toString(max); + + try { + + if (isPipelined()) { + pipeline.zrevrangeByScoreWithScores(stringKey, minString, maxString, (int) offset, (int) count); + return null; + } + return RjcUtils.convertElementScore(session.zrevrangeByScoreWithScores(stringKey, minString, maxString, + (int) offset, (int) count)); + } catch (Exception ex) { + throw convertRjcAccessException(ex); + } + } + + @Override + public Set zRevRangeByScoreWithScores(byte[] key, double min, double max) { + String stringKey = RjcUtils.decode(key); + String minString = Double.toString(min); + String maxString = Double.toString(max); + + try { + + if (isPipelined()) { + pipeline.zrevrangeByScoreWithScores(stringKey, minString, maxString); + return null; + } + return RjcUtils.convertElementScore(session.zrevrangeByScoreWithScores(stringKey, minString, maxString)); + } catch (Exception ex) { + throw convertRjcAccessException(ex); + } + } + @Override public Long zRank(byte[] key, byte[] value) { String stringKey = RjcUtils.decode(key); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/AbstractOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/AbstractOperations.java index ccaeedfe4..1b15b4747 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/AbstractOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/AbstractOperations.java @@ -17,11 +17,14 @@ package org.springframework.data.keyvalue.redis.core; import java.util.Collection; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.springframework.data.keyvalue.redis.connection.RedisConnection; +import org.springframework.data.keyvalue.redis.connection.RedisZSetCommands.Tuple; +import org.springframework.data.keyvalue.redis.core.ZSetOperations.TypedTuple; import org.springframework.data.keyvalue.redis.serializer.RedisSerializer; import org.springframework.data.keyvalue.redis.serializer.SerializationUtils; import org.springframework.util.Assert; @@ -136,6 +139,15 @@ abstract class AbstractOperations { return SerializationUtils.deserialize(rawValues, valueSerializer); } + @SuppressWarnings("unchecked") + Set> deserializeTupleValues(Set rawValues) { + Set> set = new LinkedHashSet>(rawValues.size()); + for (Tuple rawValue : rawValues) { + set.add(new DefaultTypedTuple(valueSerializer.deserialize(rawValue.getValue()), rawValue.getScore())); + } + return set; + } + @SuppressWarnings("unchecked") List deserializeValues(List rawValues) { return SerializationUtils.deserialize(rawValues, valueSerializer); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundZSetOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundZSetOperations.java index 2ba5783d4..162e9dd51 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundZSetOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundZSetOperations.java @@ -19,6 +19,8 @@ package org.springframework.data.keyvalue.redis.core; import java.util.Collection; import java.util.Set; +import org.springframework.data.keyvalue.redis.core.ZSetOperations.TypedTuple; + /** * ZSet (or SortedSet) operations bound to a certain key. @@ -39,6 +41,16 @@ public interface BoundZSetOperations extends BoundKeyOperations { Set reverseRange(long start, long end); + Set reverseRangeByScore(double min, double max); + + Set> rangeWithScores(long start, long end); + + Set> rangeByScoreWithScores(double min, double max); + + Set> reverseRangeWithScores(long start, long end); + + Set> reverseRangeByScoreWithScores(double min, double max); + void removeRange(long start, long end); void removeRangeByScore(double min, double max); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundZSetOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundZSetOperations.java index 71590d863..60f847bc5 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundZSetOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundZSetOperations.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Set; import org.springframework.data.keyvalue.redis.connection.DataType; +import org.springframework.data.keyvalue.redis.core.ZSetOperations.TypedTuple; /** * Default implementation for {@link BoundZSetOperations}. @@ -76,6 +77,31 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.rangeByScore(getKey(), min, max); } + @Override + public Set> rangeByScoreWithScores(double min, double max) { + return ops.rangeByScoreWithScores(getKey(), min, max); + } + + @Override + public Set> rangeWithScores(long start, long end) { + return ops.rangeWithScores(getKey(), start, end); + } + + @Override + public Set reverseRangeByScore(double min, double max) { + return ops.reverseRangeByScore(getKey(), min, max); + } + + @Override + public Set> reverseRangeByScoreWithScores(double min, double max) { + return ops.reverseRangeByScoreWithScores(getKey(), min, max); + } + + @Override + public Set> reverseRangeWithScores(long start, long end) { + return ops.reverseRangeWithScores(getKey(), start, end); + } + @Override public Long rank(Object o) { return ops.rank(getKey(), o); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultListOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultListOperations.java index b6c67936f..2349f58ec 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultListOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultListOperations.java @@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.data.keyvalue.redis.connection.RedisConnection; import org.springframework.data.keyvalue.redis.connection.RedisListCommands.Position; +import org.springframework.util.CollectionUtils; /** * Default implementation of {@link ListOperations}. @@ -59,7 +60,8 @@ class DefaultListOperations extends AbstractOperations implements Li return execute(new ValueDeserializingRedisCallback(key) { @Override protected byte[] inRedis(byte[] rawKey, RedisConnection connection) { - return connection.bLPop(tm, rawKey).get(0); + List lPop = connection.bLPop(tm, rawKey); + return (CollectionUtils.isEmpty(lPop) ? null : lPop.get(1)); } }, true); } @@ -153,7 +155,8 @@ class DefaultListOperations extends AbstractOperations implements Li return execute(new ValueDeserializingRedisCallback(key) { @Override protected byte[] inRedis(byte[] rawKey, RedisConnection connection) { - return connection.bRPop(tm, rawKey).get(0); + List bRPop = connection.bRPop(tm, rawKey); + return (CollectionUtils.isEmpty(bRPop) ? null : bRPop.get(1)); } }, true); } diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultTypedTuple.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultTypedTuple.java new file mode 100644 index 000000000..fc23e6d79 --- /dev/null +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultTypedTuple.java @@ -0,0 +1,50 @@ +/* + * Copyright 2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.keyvalue.redis.core; + +import org.springframework.data.keyvalue.redis.core.ZSetOperations.TypedTuple; + +/** + * Default implementation of TypedTuple. + * + * @author Costin Leau + */ +class DefaultTypedTuple implements TypedTuple { + + private final Double score; + private final V value; + + /** + * Constructs a new DefaultTypedTuple instance. + * + * @param value + * @param score + */ + public DefaultTypedTuple(V value, Double score) { + this.score = score; + this.value = value; + } + + @Override + public Double getScore() { + return score; + } + + @Override + public V getValue() { + return value; + } +} diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultZSetOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultZSetOperations.java index 154163fe7..c0198d010 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultZSetOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultZSetOperations.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.Set; import org.springframework.data.keyvalue.redis.connection.RedisConnection; +import org.springframework.data.keyvalue.redis.connection.RedisZSetCommands.Tuple; /** * Default implementation of {@link ZSetOperations}. @@ -76,7 +77,6 @@ class DefaultZSetOperations extends AbstractOperations implements ZS }, true); } - @SuppressWarnings("unchecked") @Override public Set range(K key, final long start, final long end) { final byte[] rawKey = rawKey(key); @@ -91,7 +91,48 @@ class DefaultZSetOperations extends AbstractOperations implements ZS return deserializeValues(rawValues); } - @SuppressWarnings("unchecked") + @Override + public Set reverseRange(K key, final long start, final long end) { + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + @Override + public Set doInRedis(RedisConnection connection) { + return connection.zRevRange(rawKey, start, end); + } + }, true); + + return deserializeValues(rawValues); + } + + @Override + public Set> rangeWithScores(K key, final long start, final long end) { + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + @Override + public Set doInRedis(RedisConnection connection) { + return connection.zRangeWithScores(rawKey, start, end); + } + }, true); + + return deserializeTupleValues(rawValues); + } + + @Override + public Set> reverseRangeWithScores(K key, final long start, final long end) { + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + @Override + public Set doInRedis(RedisConnection connection) { + return connection.zRevRangeWithScores(rawKey, start, end); + } + }, true); + + return deserializeTupleValues(rawValues); + } + @Override public Set rangeByScore(K key, final double min, final double max) { final byte[] rawKey = rawKey(key); @@ -106,6 +147,50 @@ class DefaultZSetOperations extends AbstractOperations implements ZS return deserializeValues(rawValues); } + + @Override + public Set reverseRangeByScore(K key, final double min, final double max) { + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + @Override + public Set doInRedis(RedisConnection connection) { + return connection.zRevRangeByScore(rawKey, min, max); + } + }, true); + + return deserializeValues(rawValues); + } + + @Override + public Set> rangeByScoreWithScores(K key, final double min, final double max) { + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + @Override + public Set doInRedis(RedisConnection connection) { + return connection.zRangeByScoreWithScores(rawKey, min, max); + } + }, true); + + return deserializeTupleValues(rawValues); + } + + @Override + public Set> reverseRangeByScoreWithScores(K key, final double min, final double max) { + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + @Override + public Set doInRedis(RedisConnection connection) { + return connection.zRevRangeByScoreWithScores(rawKey, min, max); + + } + }, true); + + return deserializeTupleValues(rawValues); + } + @Override public Long rank(K key, Object o) { final byte[] rawKey = rawKey(key); @@ -171,21 +256,6 @@ class DefaultZSetOperations extends AbstractOperations implements ZS }, true); } - @SuppressWarnings("unchecked") - @Override - public Set reverseRange(K key, final long start, final long end) { - final byte[] rawKey = rawKey(key); - - Set rawValues = execute(new RedisCallback>() { - @Override - public Set doInRedis(RedisConnection connection) { - return connection.zRevRange(rawKey, start, end); - } - }, true); - - return deserializeValues(rawValues); - } - @Override public Double score(K key, Object o) { final byte[] rawKey = rawKey(key); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java index eb9c1d398..cdf6f4364 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java @@ -87,18 +87,6 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation public RedisTemplate() { } - /** - * Constructs a new RedisTemplate instance and automatically initializes the template. - * If other parameters need to be set, it is recommended to use {@link #setConnectionFactory(RedisConnectionFactory)} instead. - * - * @param connectionFactory connection factory for creating new connections - */ - public RedisTemplate(RedisConnectionFactory connectionFactory) { - this.setConnectionFactory(connectionFactory); - afterPropertiesSet(); - } - - @Override public void afterPropertiesSet() { super.afterPropertiesSet(); @@ -126,11 +114,6 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation if (defaultUsed) { Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized"); } - - valueOps = new DefaultValueOperations(this); - listOps = new DefaultListOperations(this); - setOps = new DefaultSetOperations(this); - zSetOps = new DefaultZSetOperations(this); } @Override @@ -754,11 +737,17 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation @Override public ValueOperations opsForValue() { + if (valueOps == null) { + valueOps = new DefaultValueOperations(this); + } return valueOps; } @Override public ListOperations opsForList() { + if (listOps == null) { + listOps = new DefaultListOperations(this); + } return listOps; } @@ -774,6 +763,9 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation @Override public SetOperations opsForSet() { + if (setOps == null) { + setOps = new DefaultSetOperations(this); + } return setOps; } @@ -784,6 +776,9 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation @Override public ZSetOperations opsForZSet() { + if (zSetOps == null) { + zSetOps = new DefaultZSetOperations(this); + } return zSetOps; } diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/StringRedisTemplate.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/StringRedisTemplate.java index 90b22c2d0..29db41807 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/StringRedisTemplate.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/StringRedisTemplate.java @@ -36,6 +36,8 @@ public class StringRedisTemplate extends RedisTemplate { /** * Constructs a new StringRedisTemplate instance. + * {@link #setConnectionFactory(RedisConnectionFactory)} and {@link #afterPropertiesSet()} still need to be called. + * */ public StringRedisTemplate() { RedisSerializer stringSerializer = new StringRedisSerializer(); @@ -46,7 +48,7 @@ public class StringRedisTemplate extends RedisTemplate { } /** - * Constructs a new StringRedisTemplate instance. + * Constructs a new StringRedisTemplate instance ready to be used. * * @param connectionFactory connection factory for creating new connections */ diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/ZSetOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/ZSetOperations.java index 221138af9..87bf0784c 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/ZSetOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/ZSetOperations.java @@ -26,6 +26,15 @@ import java.util.Set; */ public interface ZSetOperations { + /** + * Typed ZSet tuple. + */ + public interface TypedTuple { + V getValue(); + + Double getScore(); + } + void intersectAndStore(K key, K otherKey, K destKey); void intersectAndStore(K key, Collection otherKeys, K destKey); @@ -36,9 +45,19 @@ public interface ZSetOperations { Set range(K key, long start, long end); + Set reverseRange(K key, long start, long end); + + Set> rangeWithScores(K key, long start, long end); + + Set> reverseRangeWithScores(K key, long start, long end); + Set rangeByScore(K key, double min, double max); - Set reverseRange(K key, long start, long end); + Set reverseRangeByScore(K key, double min, double max); + + Set> rangeByScoreWithScores(K key, double min, double max); + + Set> reverseRangeByScoreWithScores(K key, double min, double max); Boolean add(K key, V value, double score); @@ -61,4 +80,4 @@ public interface ZSetOperations { Long size(K key); RedisOperations getOperations(); -} +} \ No newline at end of file diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicInteger.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicInteger.java index 79e5b523e..ca33798ba 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicInteger.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicInteger.java @@ -87,43 +87,6 @@ public class RedisAtomicInteger extends Number implements Serializable, BoundKey } } - /** - * Constructs a new RedisAtomicInteger instance. Uses as initial value - * the data from the backing store (sets the counter to 0 if no value is found). - * - * Use {@link #RedisAtomicInteger(String, RedisOperations, int)} to set the counter to a certain value - * as an alternative constructor or {@link #set(int)}. - * - * Note that integers need to be properly serialized so that Redis can recognized the values as numeric and thus modify their value. - * - * @param redisCounter - * @param operations - */ - public RedisAtomicInteger(String redisCounter, RedisOperations operations) { - this.key = redisCounter; - this.operations = operations.opsForValue(); - this.generalOps = operations; - if (this.operations.get(redisCounter) == null) { - set(0); - } - } - - /** - * Constructs a new RedisAtomicInteger instance with the given initial value. - * - * Note that integers need to be properly serialized so that Redis can recognized the values as numeric and thus modify their value. - * - * @param redisCounter - * @param operations - * @param initialValue - */ - public RedisAtomicInteger(String redisCounter, RedisOperations operations, int initialValue) { - this.key = redisCounter; - this.operations = operations.opsForValue(); - this.generalOps = operations; - this.operations.set(redisCounter, initialValue); - } - /** * Get the current value. * diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicLong.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicLong.java index 9da634b3e..36502c489 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicLong.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/atomic/RedisAtomicLong.java @@ -87,42 +87,6 @@ public class RedisAtomicLong extends Number implements Serializable, BoundKeyOpe } } - /** - * Constructs a new RedisAtomicLong instance. Uses as initial value - * the data from the backing store (sets the counter to 0 if no value is found). - * - * Use {@link #RedisAtomicLong(String, RedisOperations, long)} to set the counter to a certain value - * as an alternative constructor or {@link #set(long)}. - * - * Note that longs need to be properly serialized so that Redis can recognized the values as numeric and thus modify their value. - * - * @param redisCounter - * @param operations - */ - public RedisAtomicLong(String redisCounter, RedisOperations operations) { - this.key = redisCounter; - this.operations = operations.opsForValue(); - this.generalOps = operations; - if (this.operations.get(redisCounter) == null) { - set(0); - } - } - - /** - * Constructs a new RedisAtomicLong instance with the given initial value. - * - * Note that longs need to be properly serialized so that Redis can recognized the values as numeric and thus modify their value. - * - * @param redisCounter - * @param operations - * @param initialValue - */ - public RedisAtomicLong(String redisCounter, RedisOperations operations, long initialValue) { - this.key = redisCounter; - this.operations = operations.opsForValue(); - this.operations.set(redisCounter, initialValue); - } - /** * Gets the current value. * diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/CollectionUtils.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/CollectionUtils.java index e98c8287a..1e4ee5fea 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/CollectionUtils.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/CollectionUtils.java @@ -76,6 +76,7 @@ abstract class CollectionUtils { static Boolean renameIfAbsent(final K key, final K newKey, RedisOperations operations) { return operations.execute(new SessionCallback() { + @SuppressWarnings("unchecked") @Override public Boolean execute(RedisOperations operations) throws DataAccessException { List exec = null; diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/DefaultRedisZSet.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/DefaultRedisZSet.java index 4794aae99..3da68a34d 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/DefaultRedisZSet.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/DefaultRedisZSet.java @@ -23,6 +23,7 @@ import java.util.Set; import org.springframework.data.keyvalue.redis.connection.DataType; import org.springframework.data.keyvalue.redis.core.BoundZSetOperations; import org.springframework.data.keyvalue.redis.core.RedisOperations; +import org.springframework.data.keyvalue.redis.core.ZSetOperations.TypedTuple; /** * Default implementation for {@link RedisZSet}. @@ -118,6 +119,31 @@ public class DefaultRedisZSet extends AbstractRedisCollection implements R return boundZSetOps.rangeByScore(min, max); } + @Override + public Set reverseRangeByScore(double min, double max) { + return boundZSetOps.reverseRangeByScore(min, max); + } + + @Override + public Set> rangeByScoreWithScores(double min, double max) { + return boundZSetOps.rangeByScoreWithScores(min, max); + } + + @Override + public Set> rangeWithScores(long start, long end) { + return boundZSetOps.rangeWithScores(start, end); + } + + @Override + public Set> reverseRangeByScoreWithScores(double min, double max) { + return boundZSetOps.reverseRangeByScoreWithScores(min, max); + } + + @Override + public Set> reverseRangeWithScores(long start, long end) { + return boundZSetOps.reverseRangeWithScores(start, end); + } + @Override public RedisZSet remove(long start, long end) { boundZSetOps.removeRange(start, end); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisCollectionFactoryBean.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisCollectionFactoryBean.java index 0f0fa8249..2ea8086f2 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisCollectionFactoryBean.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisCollectionFactoryBean.java @@ -98,6 +98,7 @@ public class RedisCollectionFactoryBean implements InitializingBean, BeanNameAwa } } + @SuppressWarnings("unchecked") private RedisStore createStore(DataType dt) { switch (dt) { case LIST: diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisZSet.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisZSet.java index 0d6c24221..437fa5f09 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisZSet.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/support/collections/RedisZSet.java @@ -21,6 +21,8 @@ import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedSet; +import org.springframework.data.keyvalue.redis.core.ZSetOperations.TypedTuple; + /** * Redis ZSet (or sorted set (by weight)). Acts as a {@link SortedSet} based on the given priorities or weights associated with each item. *

@@ -44,6 +46,16 @@ public interface RedisZSet extends RedisCollection, Set { Set rangeByScore(double min, double max); + Set reverseRangeByScore(double min, double max); + + Set> rangeWithScores(long start, long end); + + Set> reverseRangeWithScores(long start, long end); + + Set> rangeByScoreWithScores(double min, double max); + + Set> reverseRangeByScoreWithScores(double min, double max); + RedisZSet remove(long start, long end); RedisZSet removeByScore(double min, double max); diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/connection/AbstractConnectionIntegrationTests.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/connection/AbstractConnectionIntegrationTests.java index 875d65b79..79266a5ec 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/connection/AbstractConnectionIntegrationTests.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/connection/AbstractConnectionIntegrationTests.java @@ -189,7 +189,6 @@ public abstract class AbstractConnectionIntegrationTests { } // pub sub test - @Test public void testPubSub() throws Exception { @@ -263,7 +262,7 @@ public abstract class AbstractConnectionIntegrationTests { public void run() { // sleep 1 second to let the registration happen try { - Thread.currentThread().sleep(1000); + Thread.currentThread().sleep(2000); } catch (InterruptedException ex) { throw new RuntimeException(ex); } @@ -301,7 +300,7 @@ public abstract class AbstractConnectionIntegrationTests { public void run() { // sleep 1 second to let the registration happen try { - Thread.currentThread().sleep(1000); + Thread.currentThread().sleep(1500); } catch (InterruptedException ex) { throw new RuntimeException(ex); } diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/listener/PubSubTestParams.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/listener/PubSubTestParams.java index cba742c7f..bac0d731b 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/listener/PubSubTestParams.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/listener/PubSubTestParams.java @@ -47,7 +47,9 @@ public class PubSubTestParams { jedisConnFactory.afterPropertiesSet(); RedisTemplate stringTemplate = new StringRedisTemplate(jedisConnFactory); - RedisTemplate personTemplate = new RedisTemplate(jedisConnFactory); + RedisTemplate personTemplate = new RedisTemplate(); + personTemplate.setConnectionFactory(jedisConnFactory); + personTemplate.afterPropertiesSet(); // create RJC @@ -58,7 +60,9 @@ public class PubSubTestParams { rjcConnFactory.afterPropertiesSet(); RedisTemplate stringTemplateRJC = new StringRedisTemplate(rjcConnFactory); - RedisTemplate personTemplateRJC = new RedisTemplate(rjcConnFactory); + RedisTemplate personTemplateRJC = new RedisTemplate(); + personTemplateRJC.setConnectionFactory(rjcConnFactory); + personTemplateRJC.afterPropertiesSet(); return Arrays.asList(new Object[][] { { stringFactory, stringTemplate }, { personFactory, personTemplate }, diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/CollectionTestParams.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/CollectionTestParams.java index e320a974e..4464c94ae 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/CollectionTestParams.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/CollectionTestParams.java @@ -24,6 +24,7 @@ import org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionF import org.springframework.data.keyvalue.redis.connection.jredis.JredisConnectionFactory; import org.springframework.data.keyvalue.redis.connection.rjc.RjcConnectionFactory; import org.springframework.data.keyvalue.redis.core.RedisTemplate; +import org.springframework.data.keyvalue.redis.core.StringRedisTemplate; import org.springframework.data.keyvalue.redis.serializer.JacksonJsonRedisSerializer; import org.springframework.data.keyvalue.redis.serializer.OxmSerializer; import org.springframework.oxm.xstream.XStreamMarshaller; @@ -56,20 +57,26 @@ public abstract class CollectionTestParams { jedisConnFactory.afterPropertiesSet(); - RedisTemplate stringTemplate = new RedisTemplate(jedisConnFactory); - RedisTemplate personTemplate = new RedisTemplate(jedisConnFactory); + RedisTemplate stringTemplate = new StringRedisTemplate(jedisConnFactory); + RedisTemplate personTemplate = new RedisTemplate(); + personTemplate.setConnectionFactory(jedisConnFactory); + personTemplate.afterPropertiesSet(); RedisTemplate xstreamStringTemplate = new RedisTemplate(); xstreamStringTemplate.setConnectionFactory(jedisConnFactory); xstreamStringTemplate.setDefaultSerializer(serializer); xstreamStringTemplate.afterPropertiesSet(); - RedisTemplate xstreamPersonTemplate = new RedisTemplate(jedisConnFactory); + RedisTemplate xstreamPersonTemplate = new RedisTemplate(); + xstreamPersonTemplate.setConnectionFactory(jedisConnFactory); xstreamPersonTemplate.setValueSerializer(serializer); + xstreamPersonTemplate.afterPropertiesSet(); // json - RedisTemplate jsonPersonTemplate = new RedisTemplate(jedisConnFactory); + RedisTemplate jsonPersonTemplate = new RedisTemplate(); + jsonPersonTemplate.setConnectionFactory(jedisConnFactory); jsonPersonTemplate.setValueSerializer(jsonSerializer); + jsonPersonTemplate.afterPropertiesSet(); // jredis JredisConnectionFactory jredisConnFactory = new JredisConnectionFactory(); @@ -80,18 +87,25 @@ public abstract class CollectionTestParams { jredisConnFactory.afterPropertiesSet(); - RedisTemplate stringTemplateJR = new RedisTemplate(jredisConnFactory); - RedisTemplate personTemplateJR = new RedisTemplate(jredisConnFactory); + RedisTemplate stringTemplateJR = new StringRedisTemplate(jredisConnFactory); + RedisTemplate personTemplateJR = new RedisTemplate(); + personTemplateJR.setConnectionFactory(jredisConnFactory); + personTemplateJR.afterPropertiesSet(); RedisTemplate xstreamStringTemplateJR = new RedisTemplate(); xstreamStringTemplateJR.setConnectionFactory(jredisConnFactory); xstreamStringTemplateJR.setDefaultSerializer(serializer); xstreamStringTemplateJR.afterPropertiesSet(); - RedisTemplate xstreamPersonTemplateJR = new RedisTemplate(jredisConnFactory); + RedisTemplate xstreamPersonTemplateJR = new RedisTemplate(); xstreamPersonTemplateJR.setValueSerializer(serializer); - RedisTemplate jsonPersonTemplateJR = new RedisTemplate(jredisConnFactory); - jsonPersonTemplate.setValueSerializer(jsonSerializer); + xstreamPersonTemplateJR.setConnectionFactory(jredisConnFactory); + xstreamPersonTemplateJR.afterPropertiesSet(); + + RedisTemplate jsonPersonTemplateJR = new RedisTemplate(); + jsonPersonTemplateJR.setValueSerializer(jsonSerializer); + jsonPersonTemplateJR.setConnectionFactory(jredisConnFactory); + jsonPersonTemplateJR.afterPropertiesSet(); // rjc @@ -101,8 +115,10 @@ public abstract class CollectionTestParams { rjcConnFactory.setHostName(SettingsUtils.getHost()); rjcConnFactory.afterPropertiesSet(); - RedisTemplate stringTemplateRJC = new RedisTemplate(rjcConnFactory); - RedisTemplate personTemplateRJC = new RedisTemplate(rjcConnFactory); + RedisTemplate stringTemplateRJC = new StringRedisTemplate(rjcConnFactory); + RedisTemplate personTemplateRJC = new RedisTemplate(); + personTemplateRJC.setConnectionFactory(rjcConnFactory); + personTemplateRJC.afterPropertiesSet(); RedisTemplate xstreamStringTemplateRJC = new RedisTemplate(); xstreamStringTemplateRJC.setConnectionFactory(rjcConnFactory); diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisMapTests.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisMapTests.java index 12efc9fc9..e9807ef68 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisMapTests.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisMapTests.java @@ -65,13 +65,13 @@ public class RedisMapTests extends AbstractRedisMapTests { JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory(); jedisConnFactory.setUsePool(false); - jedisConnFactory.setPort(SettingsUtils.getPort()); jedisConnFactory.setHostName(SettingsUtils.getHost()); - jedisConnFactory.afterPropertiesSet(); - RedisTemplate genericTemplate = new RedisTemplate(jedisConnFactory); + RedisTemplate genericTemplate = new RedisTemplate(); + genericTemplate.setConnectionFactory(jedisConnFactory); + genericTemplate.afterPropertiesSet(); RedisTemplate xstreamGenericTemplate = new RedisTemplate(); xstreamGenericTemplate.setConnectionFactory(jedisConnFactory); @@ -92,7 +92,10 @@ public class RedisMapTests extends AbstractRedisMapTests { jredisConnFactory.setHostName(SettingsUtils.getHost()); jredisConnFactory.afterPropertiesSet(); - RedisTemplate genericTemplateJR = new RedisTemplate(jredisConnFactory); + RedisTemplate genericTemplateJR = new RedisTemplate(); + genericTemplateJR.setConnectionFactory(jredisConnFactory); + genericTemplateJR.afterPropertiesSet(); + RedisTemplate xGenericTemplateJR = new RedisTemplate(); xGenericTemplateJR.setConnectionFactory(jredisConnFactory); xGenericTemplateJR.setDefaultSerializer(serializer); @@ -114,7 +117,10 @@ public class RedisMapTests extends AbstractRedisMapTests { rjcConnFactory.setHostName(SettingsUtils.getHost()); rjcConnFactory.afterPropertiesSet(); - RedisTemplate genericTemplateRJC = new RedisTemplate(jredisConnFactory); + RedisTemplate genericTemplateRJC = new RedisTemplate(); + genericTemplateRJC.setConnectionFactory(rjcConnFactory); + genericTemplateRJC.afterPropertiesSet(); + RedisTemplate xGenericTemplateRJC = new RedisTemplate(); xGenericTemplateRJC.setConnectionFactory(rjcConnFactory); xGenericTemplateRJC.setDefaultSerializer(serializer); diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisPropertiesTests.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisPropertiesTests.java index 8053fde02..b8e058e05 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisPropertiesTests.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/support/collections/RedisPropertiesTests.java @@ -233,7 +233,7 @@ public class RedisPropertiesTests extends RedisMapTests { jedisConnFactory.afterPropertiesSet(); - RedisTemplate genericTemplate = new RedisTemplate(jedisConnFactory); + RedisTemplate genericTemplate = new StringRedisTemplate(jedisConnFactory); RedisTemplate xstreamGenericTemplate = new RedisTemplate(); xstreamGenericTemplate.setConnectionFactory(jedisConnFactory); @@ -254,7 +254,7 @@ public class RedisPropertiesTests extends RedisMapTests { jredisConnFactory.setHostName(SettingsUtils.getHost()); jredisConnFactory.afterPropertiesSet(); - RedisTemplate genericTemplateJR = new RedisTemplate(jredisConnFactory); + RedisTemplate genericTemplateJR = new StringRedisTemplate(jredisConnFactory); RedisTemplate xGenericTemplateJR = new RedisTemplate(); xGenericTemplateJR.setConnectionFactory(jredisConnFactory); xGenericTemplateJR.setDefaultSerializer(serializer); @@ -276,7 +276,7 @@ public class RedisPropertiesTests extends RedisMapTests { rjcConnFactory.setHostName(SettingsUtils.getHost()); rjcConnFactory.afterPropertiesSet(); - RedisTemplate genericTemplateRJC = new RedisTemplate(jredisConnFactory); + RedisTemplate genericTemplateRJC = new StringRedisTemplate(jredisConnFactory); RedisTemplate xGenericTemplateRJC = new RedisTemplate(); xGenericTemplateRJC.setConnectionFactory(rjcConnFactory); xGenericTemplateRJC.setDefaultSerializer(serializer);