diff --git a/pom.xml b/pom.xml
index f50aae9fff..c1f1ef6628 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.dataspring-data-redis
- 1.7.0.BUILD-SNAPSHOT
+ 1.7.0.DATAREDIS-469-SNAPSHOTSpring Data Redis
diff --git a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java
index 992cd1eeb6..d47c758094 100644
--- a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java
+++ b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicDouble.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2014 the original author or authors.
+ * Copyright 2013-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.
@@ -20,6 +20,7 @@
import java.util.Date;
import java.util.concurrent.TimeUnit;
+import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.BoundKeyOperations;
@@ -35,9 +36,11 @@
/**
* Atomic double backed by Redis. Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS
* operations.
- *
+ *
* @author Jennifer Hickey
* @author Thomas Darimont
+ * @author Christoph Strobl
+ * @author Mark Paluch
*/
public class RedisAtomicDouble extends Number implements Serializable, BoundKeyOperations {
@@ -49,7 +52,7 @@ public class RedisAtomicDouble extends Number implements Serializable, BoundKeyO
/**
* Constructs a new RedisAtomicDouble instance. Uses the value existing in Redis or 0 if none is found.
- *
+ *
* @param redisCounter redis counter
* @param factory connection factory
*/
@@ -59,7 +62,7 @@ public RedisAtomicDouble(String redisCounter, RedisConnectionFactory factory) {
/**
* Constructs a new RedisAtomicDouble instance.
- *
+ *
* @param redisCounter
* @param factory
* @param initialValue
@@ -94,7 +97,7 @@ private RedisAtomicDouble(String redisCounter, RedisConnectionFactory factory, D
/**
* Constructs a new RedisAtomicDouble instance. Uses the value existing in Redis or 0 if none is found.
- *
+ *
* @param redisCounter the redis counter
* @param template the template
* @see #RedisAtomicDouble(String, RedisConnectionFactory, double)
@@ -108,7 +111,7 @@ public RedisAtomicDouble(String redisCounter, RedisOperations te
* with appropriate {@link RedisSerializer} for the key and value. As an alternative one could use the
* {@link #RedisAtomicDouble(String, RedisConnectionFactory, Double)} constructor which uses appropriate default
* serializers.
- *
+ *
* @param redisCounter the redis counter
* @param template the template
* @param initialValue the initial value
@@ -139,16 +142,22 @@ private RedisAtomicDouble(String redisCounter, RedisOperations t
/**
* Gets the current value.
- *
+ *
* @return the current value
*/
public double get() {
- return operations.get(key);
+
+ Double value = operations.get(key);
+ if (value != null) {
+ return value.doubleValue();
+ }
+
+ throw new DataRetrievalFailureException(String.format("The key '%s' seems to no longer exist.", key));
}
/**
* Sets to the given value.
- *
+ *
* @param newValue the new value
*/
public void set(double newValue) {
@@ -157,17 +166,23 @@ public void set(double newValue) {
/**
* Atomically sets to the given value and returns the old value.
- *
+ *
* @param newValue the new value
* @return the previous value
*/
public double getAndSet(double newValue) {
- return operations.getAndSet(key, newValue);
+
+ Double value = operations.getAndSet(key, newValue);
+ if (value != null) {
+ return value.doubleValue();
+ }
+
+ return 0;
}
/**
* Atomically sets the value to the given updated value if the current value {@code ==} the expected value.
- *
+ *
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that the actual value was not equal to the expected value.
@@ -196,7 +211,7 @@ public Boolean execute(RedisOperations operations) {
/**
* Atomically increments by one the current value.
- *
+ *
* @return the previous value
*/
public double getAndIncrement() {
@@ -205,7 +220,7 @@ public double getAndIncrement() {
/**
* Atomically decrements by one the current value.
- *
+ *
* @return the previous value
*/
public double getAndDecrement() {
@@ -214,7 +229,7 @@ public double getAndDecrement() {
/**
* Atomically adds the given value to the current value.
- *
+ *
* @param delta the value to add
* @return the previous value
*/
@@ -224,7 +239,7 @@ public double getAndAdd(final double delta) {
/**
* Atomically increments by one the current value.
- *
+ *
* @return the updated value
*/
public double incrementAndGet() {
@@ -233,7 +248,7 @@ public double incrementAndGet() {
/**
* Atomically decrements by one the current value.
- *
+ *
* @return the updated value
*/
public double decrementAndGet() {
@@ -242,7 +257,7 @@ public double decrementAndGet() {
/**
* Atomically adds the given value to the current value.
- *
+ *
* @param delta the value to add
* @return the updated value
*/
@@ -252,7 +267,7 @@ public double addAndGet(double delta) {
/**
* Returns the String representation of the current value.
- *
+ *
* @return the String representation of the current value.
*/
public String toString() {
diff --git a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java
index 224460aace..a2e44270f6 100644
--- a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java
+++ b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicInteger.java
@@ -1,12 +1,12 @@
/*
- * Copyright 2011-2014 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.
* 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.
@@ -20,6 +20,7 @@
import java.util.Date;
import java.util.concurrent.TimeUnit;
+import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.BoundKeyOperations;
@@ -35,10 +36,12 @@
/**
* Atomic integer backed by Redis. Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS
* operations.
- *
+ *
* @see java.util.concurrent.atomic.AtomicInteger
* @author Costin Leau
* @author Thomas Darimont
+ * @author Christoph Strobl
+ * @author Mark Paluch
*/
public class RedisAtomicInteger extends Number implements Serializable, BoundKeyOperations {
@@ -50,7 +53,7 @@ public class RedisAtomicInteger extends Number implements Serializable, BoundKey
/**
* Constructs a new RedisAtomicInteger instance. Uses the value existing in Redis or 0 if none is found.
- *
+ *
* @param redisCounter redis counter
* @param factory connection factory
*/
@@ -60,7 +63,7 @@ public RedisAtomicInteger(String redisCounter, RedisConnectionFactory factory) {
/**
* Constructs a new RedisAtomicInteger instance.
- *
+ *
* @param redisCounter the redis counter
* @param factory the factory
* @param initialValue the initial value
@@ -71,7 +74,7 @@ public RedisAtomicInteger(String redisCounter, RedisConnectionFactory factory, i
/**
* Constructs a new RedisAtomicInteger instance. Uses the value existing in Redis or 0 if none is found.
- *
+ *
* @param redisCounter the redis counter
* @param template the template
* @see #RedisAtomicInteger(String, RedisConnectionFactory, int)
@@ -85,7 +88,7 @@ public RedisAtomicInteger(String redisCounter, RedisOperations
* with appropriate {@link RedisSerializer} for the key and value. As an alternative one could use the
* {@link #RedisAtomicInteger(String, RedisConnectionFactory, Integer)} constructor which uses appropriate default
* serializers.
- *
+ *
* @param redisCounter the redis counter
* @param template the template
* @param initialValue the initial value
@@ -137,16 +140,22 @@ private RedisAtomicInteger(String redisCounter, RedisOperations
/**
* Get the current value.
- *
+ *
* @return the current value
*/
public int get() {
- return Integer.valueOf(operations.get(key));
+
+ Integer value = operations.get(key);
+ if (value != null) {
+ return value.intValue();
+ }
+
+ throw new DataRetrievalFailureException(String.format("The key '%s' seems to no longer exist.", key));
}
/**
* Set to the given value.
- *
+ *
* @param newValue the new value
*/
public void set(int newValue) {
@@ -155,17 +164,23 @@ public void set(int newValue) {
/**
* Set to the give value and return the old value.
- *
+ *
* @param newValue the new value
* @return the previous value
*/
public int getAndSet(int newValue) {
- return operations.getAndSet(key, newValue);
+
+ Integer value = operations.getAndSet(key, newValue);
+ if (value != null) {
+ return value.intValue();
+ }
+
+ return 0;
}
/**
* Atomically set the value to the given updated value if the current value == the expected value.
- *
+ *
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that the actual value was not equal to the expected value.
@@ -194,7 +209,7 @@ public Boolean execute(RedisOperations operations) {
/**
* Atomically increment by one the current value.
- *
+ *
* @return the previous value
*/
public int getAndIncrement() {
@@ -203,7 +218,7 @@ public int getAndIncrement() {
/**
* Atomically decrement by one the current value.
- *
+ *
* @return the previous value
*/
public int getAndDecrement() {
@@ -212,7 +227,7 @@ public int getAndDecrement() {
/**
* Atomically add the given value to current value.
- *
+ *
* @param delta the value to add
* @return the previous value
*/
@@ -222,7 +237,7 @@ public int getAndAdd(final int delta) {
/**
* Atomically increment by one the current value.
- *
+ *
* @return the updated value
*/
public int incrementAndGet() {
@@ -231,7 +246,7 @@ public int incrementAndGet() {
/**
* Atomically decrement by one the current value.
- *
+ *
* @return the updated value
*/
public int decrementAndGet() {
@@ -240,7 +255,7 @@ public int decrementAndGet() {
/**
* Atomically add the given value to current value.
- *
+ *
* @param delta the value to add
* @return the updated value
*/
@@ -250,7 +265,7 @@ public int addAndGet(int delta) {
/**
* Returns the String representation of the current value.
- *
+ *
* @return the String representation of the current value.
*/
public String toString() {
diff --git a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java
index a2e738f361..2f78d25a15 100644
--- a/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java
+++ b/src/main/java/org/springframework/data/redis/support/atomic/RedisAtomicLong.java
@@ -1,12 +1,12 @@
/*
- * Copyright 2011-2014 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.
* 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.
@@ -20,6 +20,7 @@
import java.util.Date;
import java.util.concurrent.TimeUnit;
+import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.BoundKeyOperations;
@@ -35,10 +36,12 @@
/**
* Atomic long backed by Redis. Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS
* operations.
- *
+ *
* @see java.util.concurrent.atomic.AtomicLong
* @author Costin Leau
* @author Thomas Darimont
+ * @author Christoph Strobl
+ * @author Mark Paluch
*/
public class RedisAtomicLong extends Number implements Serializable, BoundKeyOperations {
@@ -50,7 +53,7 @@ public class RedisAtomicLong extends Number implements Serializable, BoundKeyOpe
/**
* Constructs a new RedisAtomicLong instance. Uses the value existing in Redis or 0 if none is found.
- *
+ *
* @param redisCounter redis counter
* @param factory connection factory
*/
@@ -60,7 +63,7 @@ public RedisAtomicLong(String redisCounter, RedisConnectionFactory factory) {
/**
* Constructs a new RedisAtomicLong instance.
- *
+ *
* @param redisCounter
* @param factory
* @param initialValue
@@ -95,7 +98,7 @@ private RedisAtomicLong(String redisCounter, RedisConnectionFactory factory, Lon
/**
* Constructs a new RedisAtomicLong instance. Uses the value existing in Redis or 0 if none is found.
- *
+ *
* @param redisCounter the redis counter
* @param template the template
* @see #RedisAtomicLong(String, RedisConnectionFactory, long)
@@ -114,7 +117,7 @@ public RedisAtomicLong(String redisCounter, RedisOperations templa
* As an alternative one could use the {@link #RedisAtomicLong(String, RedisConnectionFactory, Long)} constructor
* which uses appropriate default serializers, in this case {@link StringRedisSerializer} for the key and
* {@link GenericToStringSerializer} for the value.
- *
+ *
* @param redisCounter the redis counter
* @param template the template
* @param initialValue the initial value
@@ -145,16 +148,22 @@ private RedisAtomicLong(String redisCounter, RedisOperations templ
/**
* Gets the current value.
- *
+ *
* @return the current value
*/
public long get() {
- return operations.get(key);
+
+ Long value = operations.get(key);
+ if (value != null) {
+ return value.longValue();
+ }
+
+ throw new DataRetrievalFailureException(String.format("The key '%s' seems to no longer exist.", key));
}
/**
* Sets to the given value.
- *
+ *
* @param newValue the new value
*/
public void set(long newValue) {
@@ -163,17 +172,23 @@ public void set(long newValue) {
/**
* Atomically sets to the given value and returns the old value.
- *
+ *
* @param newValue the new value
* @return the previous value
*/
public long getAndSet(long newValue) {
- return operations.getAndSet(key, newValue);
+
+ Long value = operations.getAndSet(key, newValue);
+ if (value != null) {
+ return value.longValue();
+ }
+
+ return 0;
}
/**
* Atomically sets the value to the given updated value if the current value {@code ==} the expected value.
- *
+ *
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that the actual value was not equal to the expected value.
@@ -202,7 +217,7 @@ public Boolean execute(RedisOperations operations) {
/**
* Atomically increments by one the current value.
- *
+ *
* @return the previous value
*/
public long getAndIncrement() {
@@ -211,7 +226,7 @@ public long getAndIncrement() {
/**
* Atomically decrements by one the current value.
- *
+ *
* @return the previous value
*/
public long getAndDecrement() {
@@ -220,7 +235,7 @@ public long getAndDecrement() {
/**
* Atomically adds the given value to the current value.
- *
+ *
* @param delta the value to add
* @return the previous value
*/
@@ -230,7 +245,7 @@ public long getAndAdd(final long delta) {
/**
* Atomically increments by one the current value.
- *
+ *
* @return the updated value
*/
public long incrementAndGet() {
@@ -239,7 +254,7 @@ public long incrementAndGet() {
/**
* Atomically decrements by one the current value.
- *
+ *
* @return the updated value
*/
public long decrementAndGet() {
@@ -248,7 +263,7 @@ public long decrementAndGet() {
/**
* Atomically adds the given value to the current value.
- *
+ *
* @param delta the value to add
* @return the updated value
*/
@@ -258,7 +273,7 @@ public long addAndGet(long delta) {
/**
* Returns the String representation of the current value.
- *
+ *
* @return the String representation of the current value.
*/
public String toString() {
diff --git a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java
index 09d1bf7cae..b62e8d7eb8 100644
--- a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java
+++ b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicDoubleTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2014 the original author or authors.
+ * Copyright 2013-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.
@@ -30,6 +30,7 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.redis.ConnectionFactoryTracker;
import org.springframework.data.redis.RedisTestProfileValueSource;
import org.springframework.data.redis.connection.ConnectionUtils;
@@ -41,20 +42,30 @@
/**
* Integration test of {@link RedisAtomicDouble}
- *
+ *
* @author Jennifer Hickey
* @author Thomas Darimont
+ * @author Christoph Strobl
+ * @author Mark Paluch
*/
@RunWith(Parameterized.class)
public class RedisAtomicDoubleTests extends AbstractRedisAtomicsTests {
private RedisAtomicDouble doubleCounter;
-
private RedisConnectionFactory factory;
+ private RedisTemplate template;
public RedisAtomicDoubleTests(RedisConnectionFactory factory) {
- doubleCounter = new RedisAtomicDouble(getClass().getSimpleName() + ":double", factory);
+
+ this.doubleCounter = new RedisAtomicDouble(getClass().getSimpleName() + ":double", factory);
this.factory = factory;
+
+ this.template = new RedisTemplate();
+ this.template.setConnectionFactory(factory);
+ this.template.setKeySerializer(new StringRedisSerializer());
+ this.template.setValueSerializer(new GenericToStringSerializer(Double.class));
+ this.template.afterPropertiesSet();
+
ConnectionFactoryTracker.add(factory);
}
@@ -199,15 +210,42 @@ public void testShouldThrowExceptionIfRedisAtomicDoubleIsUsedWithRedisTemplateAn
@Test
public void testShouldBeAbleToUseRedisAtomicDoubleWithProperlyConfiguredRedisTemplate() {
- RedisTemplate template = new RedisTemplate();
- template.setConnectionFactory(factory);
- template.setKeySerializer(new StringRedisSerializer());
- template.setValueSerializer(new GenericToStringSerializer(Double.class));
- template.afterPropertiesSet();
-
RedisAtomicDouble ral = new RedisAtomicDouble("DATAREDIS-317.atomicDouble", template);
ral.set(32.23);
assertThat(ral.get(), is(32.23));
}
+
+ /**
+ * @see DATAREDIS-469
+ */
+ @Test
+ public void getThrowsExceptionWhenKeyHasBeenRemoved() {
+
+ expectedException.expect(DataRetrievalFailureException.class);
+ expectedException.expectMessage("'test' seems to no longer exist");
+
+ // setup double
+ RedisAtomicDouble test = new RedisAtomicDouble("test", factory, 1);
+ assertThat(test.get(), equalTo(1D)); // this passes
+
+ template.delete("test");
+
+ test.get();
+ }
+
+ /**
+ * @see DATAREDIS-469
+ */
+ @Test
+ public void getAndSetReturnsZeroWhenKeyHasBeenRemoved() {
+
+ // setup double
+ RedisAtomicDouble test = new RedisAtomicDouble("test", factory, 1);
+ assertThat(test.get(), equalTo(1D)); // this passes
+
+ template.delete("test");
+
+ assertThat(test.getAndSet(2), is(0D));
+ }
}
diff --git a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java
index bd28071ebf..1f7e3cff7d 100644
--- a/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java
+++ b/src/test/java/org/springframework/data/redis/support/atomic/RedisAtomicIntegerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2014 the original author or authors.
+ * Copyright 2013-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.
@@ -30,6 +30,7 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.redis.ConnectionFactoryTracker;
import org.springframework.data.redis.connection.ConnectionUtils;
import org.springframework.data.redis.connection.RedisConnection;
@@ -40,20 +41,31 @@
/**
* Integration test of {@link RedisAtomicInteger}
- *
+ *
* @author Costin Leau
* @author Jennifer Hickey
* @author Thomas Darimont
+ * @author Christoph Strobl
+ * @author Mark Paluch
*/
@RunWith(Parameterized.class)
public class RedisAtomicIntegerTests extends AbstractRedisAtomicsTests {
private RedisAtomicInteger intCounter;
private RedisConnectionFactory factory;
+ private RedisTemplate template;
public RedisAtomicIntegerTests(RedisConnectionFactory factory) {
- intCounter = new RedisAtomicInteger(getClass().getSimpleName() + ":int", factory);
+
+ this.intCounter = new RedisAtomicInteger(getClass().getSimpleName() + ":int", factory);
this.factory = factory;
+
+ this.template = new RedisTemplate();
+ this.template.setConnectionFactory(factory);
+ this.template.setKeySerializer(new StringRedisSerializer());
+ this.template.setValueSerializer(new GenericToStringSerializer(Integer.class));
+ this.template.afterPropertiesSet();
+
ConnectionFactoryTracker.add(factory);
}
@@ -75,7 +87,7 @@ public static Collection