Skip to content

Commit b3b471d

Browse files
onobcmp911de
authored andcommitted
Annotate ValueOperations.get(…) methods with @Nullable.
This commit annotates the return values of several GET related `ValueOperations` methods with `@Nullable` to reflect the fact that null values are returned when non-existent keys are passed in. Resolves: #3223 Original pull request: #3244 Signed-off-by: Chris Bono <chris.bono@broadcom.com>
1 parent 4da4960 commit b3b471d

File tree

3 files changed

+59
-23
lines changed

3 files changed

+59
-23
lines changed

src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* @author Christoph Strobl
3939
* @author Jiahe Cai
4040
* @author Ehsan Alemzadeh
41+
* @author Chris Bono
4142
*/
4243
class DefaultValueOperations<K, V> extends AbstractOperations<K, V> implements ValueOperations<K, V> {
4344

@@ -46,37 +47,33 @@ class DefaultValueOperations<K, V> extends AbstractOperations<K, V> implements V
4647
}
4748

4849
@Override
49-
public V get(Object key) {
50+
public @Nullable V get(Object key) {
5051
return execute(valueCallbackFor(key, DefaultedRedisConnection::get));
5152
}
5253

53-
@Nullable
5454
@Override
55-
public V getAndDelete(K key) {
55+
public @Nullable V getAndDelete(K key) {
5656
return execute(valueCallbackFor(key, DefaultedRedisConnection::getDel));
5757
}
5858

59-
@Nullable
6059
@Override
61-
public V getAndExpire(K key, long timeout, TimeUnit unit) {
60+
public @Nullable V getAndExpire(K key, long timeout, TimeUnit unit) {
6261
return execute(
6362
valueCallbackFor(key, (connection, rawKey) -> connection.getEx(rawKey, Expiration.from(timeout, unit))));
6463
}
6564

66-
@Nullable
6765
@Override
68-
public V getAndExpire(K key, Duration timeout) {
66+
public @Nullable V getAndExpire(K key, Duration timeout) {
6967
return execute(valueCallbackFor(key, (connection, rawKey) -> connection.getEx(rawKey, Expiration.from(timeout))));
7068
}
7169

72-
@Nullable
7370
@Override
74-
public V getAndPersist(K key) {
71+
public @Nullable V getAndPersist(K key) {
7572
return execute(valueCallbackFor(key, (connection, rawKey) -> connection.getEx(rawKey, Expiration.persistent())));
7673
}
7774

7875
@Override
79-
public V getAndSet(K key, V newValue) {
76+
public @Nullable V getAndSet(K key, V newValue) {
8077

8178
byte[] rawValue = rawValue(newValue);
8279
return execute(valueCallbackFor(key, (connection, rawKey) -> connection.getSet(rawKey, rawValue)));
@@ -139,7 +136,7 @@ public String get(K key, long start, long end) {
139136
}
140137

141138
@Override
142-
public List<V> multiGet(Collection<K> keys) {
139+
public List<@Nullable V> multiGet(Collection<K> keys) {
143140

144141
if (keys.isEmpty()) {
145142
return Collections.emptyList();
@@ -212,16 +209,16 @@ public void set(K key, V value, long timeout, TimeUnit unit) {
212209
}
213210

214211
@Override
215-
public V setGet(K key, V value, long timeout, TimeUnit unit) {
212+
public @Nullable V setGet(K key, V value, long timeout, TimeUnit unit) {
216213
return doSetGet(key, value, Expiration.from(timeout, unit));
217214
}
218215

219216
@Override
220-
public V setGet(K key, V value, Duration duration) {
217+
public @Nullable V setGet(K key, V value, Duration duration) {
221218
return doSetGet(key, value, Expiration.from(duration));
222219
}
223220

224-
private V doSetGet(K key, V value, Expiration duration) {
221+
private @Nullable V doSetGet(K key, V value, Expiration duration) {
225222

226223
byte[] rawValue = rawValue(value);
227224
return execute(new ValueDeserializingRedisCallback(key) {

src/main/java/org/springframework/data/redis/core/ValueOperations.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.jspecify.annotations.NonNull;
2525
import org.jspecify.annotations.NullUnmarked;
26+
import org.jspecify.annotations.Nullable;
2627
import org.springframework.data.redis.connection.BitFieldSubCommands;
2728
import org.springframework.util.Assert;
2829

@@ -34,6 +35,7 @@
3435
* @author Mark Paluch
3536
* @author Jiahe Cai
3637
* @author Marcin Grzejszczak
38+
* @author Chris Bono
3739
*/
3840
@NullUnmarked
3941
public interface ValueOperations<K, V> {
@@ -60,7 +62,7 @@ public interface ValueOperations<K, V> {
6062
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
6163
* @since 3.5
6264
*/
63-
V setGet(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit unit);
65+
@Nullable V setGet(@NonNull K key, @NonNull V value, long timeout, @NonNull TimeUnit unit);
6466

6567
/**
6668
* Set the {@code value} and expiration {@code timeout} for {@code key}. Return the old string stored at key, or
@@ -74,7 +76,7 @@ public interface ValueOperations<K, V> {
7476
* @see <a href="https://redis.io/commands/set">Redis Documentation: SET</a>
7577
* @since 3.5
7678
*/
77-
V setGet(@NonNull K key, @NonNull V value, @NonNull Duration duration);
79+
@Nullable V setGet(@NonNull K key, @NonNull V value, @NonNull Duration duration);
7880

7981
/**
8082
* Set the {@code value} and expiration {@code timeout} for {@code key}.
@@ -226,7 +228,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
226228
* @return {@literal null} when key does not exist or used in pipeline / transaction.
227229
* @see <a href="https://redis.io/commands/get">Redis Documentation: GET</a>
228230
*/
229-
V get(Object key);
231+
@Nullable V get(Object key);
230232

231233
/**
232234
* Return the value at {@code key} and delete the key.
@@ -236,7 +238,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
236238
* @see <a href="https://redis.io/commands/getdel">Redis Documentation: GETDEL</a>
237239
* @since 2.6
238240
*/
239-
V getAndDelete(@NonNull K key);
241+
@Nullable V getAndDelete(@NonNull K key);
240242

241243
/**
242244
* Return the value at {@code key} and expire the key by applying {@code timeout}.
@@ -248,7 +250,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
248250
* @see <a href="https://redis.io/commands/getex">Redis Documentation: GETEX</a>
249251
* @since 2.6
250252
*/
251-
V getAndExpire(@NonNull K key, long timeout, @NonNull TimeUnit unit);
253+
@Nullable V getAndExpire(@NonNull K key, long timeout, @NonNull TimeUnit unit);
252254

253255
/**
254256
* Return the value at {@code key} and expire the key by applying {@code timeout}.
@@ -259,7 +261,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
259261
* @see <a href="https://redis.io/commands/getex">Redis Documentation: GETEX</a>
260262
* @since 2.6
261263
*/
262-
V getAndExpire(@NonNull K key, @NonNull Duration timeout);
264+
@Nullable V getAndExpire(@NonNull K key, @NonNull Duration timeout);
263265

264266
/**
265267
* Return the value at {@code key} and persist the key. This operation removes any TTL that is associated with
@@ -270,7 +272,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
270272
* @see <a href="https://redis.io/commands/getex">Redis Documentation: GETEX</a>
271273
* @since 2.6
272274
*/
273-
V getAndPersist(@NonNull K key);
275+
@Nullable V getAndPersist(@NonNull K key);
274276

275277
/**
276278
* Set {@code value} of {@code key} and return its old value.
@@ -279,7 +281,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
279281
* @return {@literal null} when key does not exist or used in pipeline / transaction.
280282
* @see <a href="https://redis.io/commands/getset">Redis Documentation: GETSET</a>
281283
*/
282-
V getAndSet(@NonNull K key, @NonNull V value);
284+
@Nullable V getAndSet(@NonNull K key, @NonNull V value);
283285

284286
/**
285287
* Get multiple {@code keys}. Values are in the order of the requested keys Absent field values are represented using
@@ -289,7 +291,7 @@ default Boolean setIfPresent(@NonNull K key, @NonNull V value, @NonNull Duration
289291
* @return {@literal null} when used in pipeline / transaction.
290292
* @see <a href="https://redis.io/commands/mget">Redis Documentation: MGET</a>
291293
*/
292-
List<V> multiGet(@NonNull Collection<@NonNull K> keys);
294+
List<@Nullable V> multiGet(@NonNull Collection<@NonNull K> keys);
293295

294296
/**
295297
* Increment an integer value stored as string value under {@code key} by one.

src/test/java/org/springframework/data/redis/core/DefaultValueOperationsIntegrationTests.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* @author Jiahe Cai
4747
* @author Mark Paluch
4848
* @author Hendrik Duerkop
49+
* @author Chris Bono
4950
*/
5051
@ParameterizedClass
5152
@MethodSource("testParams")
@@ -153,6 +154,21 @@ void testDecrementByLong() {
153154
assertThat(valueOps.get(key)).isEqualTo((Long) value - 5);
154155
}
155156

157+
@Test
158+
void testMultiGet() {
159+
160+
K key1 = keyFactory.instance();
161+
K key2 = keyFactory.instance();
162+
K noSuchKey = keyFactory.instance();
163+
V value1 = valueFactory.instance();
164+
V value2 = valueFactory.instance();
165+
166+
valueOps.set(key1, value1);
167+
valueOps.set(key2, value2);
168+
169+
assertThat(valueOps.multiGet(Arrays.asList(key1, noSuchKey, key2))).containsExactly(value1, null, value2);
170+
}
171+
156172
@Test
157173
void testMultiSetIfAbsent() {
158174

@@ -213,6 +229,9 @@ void testGetSet() {
213229
valueOps.set(key, value);
214230

215231
assertThat(valueOps.get(key)).isEqualTo(value);
232+
233+
K noSuchKey = keyFactory.instance();
234+
assertThat(valueOps.get(noSuchKey)).isNull();
216235
}
217236

218237
@Test // GH-2050
@@ -227,6 +246,9 @@ void testGetAndExpire() {
227246

228247
assertThat(valueOps.getAndExpire(key, Duration.ofSeconds(10))).isEqualTo(value1);
229248
assertThat(redisTemplate.getExpire(key)).isGreaterThan(1);
249+
250+
K noSuchKey = keyFactory.instance();
251+
assertThat(valueOps.getAndExpire(noSuchKey, Duration.ofSeconds(10))).isNull();
230252
}
231253

232254
@Test // GH-2050
@@ -240,6 +262,9 @@ void testGetAndPersist() {
240262

241263
assertThat(valueOps.getAndPersist(key)).isEqualTo(value1);
242264
assertThat(redisTemplate.getExpire(key)).isEqualTo(-1);
265+
266+
K noSuchKey = keyFactory.instance();
267+
assertThat(valueOps.getAndPersist(noSuchKey)).isNull();
243268
}
244269

245270
@Test // GH-2050
@@ -253,6 +278,9 @@ void testGetAndDelete() {
253278

254279
assertThat(valueOps.getAndDelete(key)).isEqualTo(value1);
255280
assertThat(redisTemplate.hasKey(key)).isFalse();
281+
282+
K noSuchKey = keyFactory.instance();
283+
assertThat(valueOps.getAndDelete(noSuchKey)).isNull();
256284
}
257285

258286
@Test
@@ -265,6 +293,9 @@ void testGetAndSet() {
265293
valueOps.set(key, value1);
266294

267295
assertThat(valueOps.getAndSet(key, value2)).isEqualTo(value1);
296+
297+
K noSuchKey = keyFactory.instance();
298+
assertThat(valueOps.getAndSet(noSuchKey, value2)).isNull();
268299
}
269300

270301
@Test
@@ -330,6 +361,9 @@ void testSetGetWithExpiration() {
330361

331362
assertThat(valueOps.setGet(key, value2, 1, TimeUnit.SECONDS)).isEqualTo(value1);
332363
assertThat(valueOps.get(key)).isEqualTo(value2);
364+
365+
K noSuchKey = keyFactory.instance();
366+
assertThat(valueOps.setGet(noSuchKey, value2, 1, TimeUnit.SECONDS)).isNull();
333367
}
334368

335369
@Test
@@ -343,6 +377,9 @@ void testSetGetWithExpirationDuration() {
343377

344378
assertThat(valueOps.setGet(key, value2, Duration.ofMillis(1000))).isEqualTo(value1);
345379
assertThat(valueOps.get(key)).isEqualTo(value2);
380+
381+
K noSuchKey = keyFactory.instance();
382+
assertThat(valueOps.setGet(noSuchKey, value2, Duration.ofMillis(1000))).isNull();
346383
}
347384

348385
@Test

0 commit comments

Comments
 (0)