Skip to content

Commit 824bc09

Browse files
committed
Actual caching of null values in retrieve(key, valueLoader)
See gh-31637
1 parent 441e210 commit 824bc09

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

spring-context-support/src/main/java/org/springframework/cache/caffeine/CaffeineCache.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,14 @@ public CompletableFuture<?> retrieve(Object key) {
148148
@SuppressWarnings("unchecked")
149149
@Override
150150
public <T> CompletableFuture<T> retrieve(Object key, Supplier<CompletableFuture<T>> valueLoader) {
151-
return (CompletableFuture<T>) getAsyncCache().get(key, (k, e) -> valueLoader.get());
151+
if (isAllowNullValues()) {
152+
return (CompletableFuture<T>) getAsyncCache()
153+
.get(key, (k, e) -> valueLoader.get().thenApply(this::toStoreValue))
154+
.thenApply(this::fromStoreValue);
155+
}
156+
else {
157+
return (CompletableFuture<T>) getAsyncCache().get(key, (k, e) -> valueLoader.get());
158+
}
152159
}
153160

154161
@Override

spring-context-support/src/test/java/org/springframework/cache/caffeine/CaffeineCacheManagerTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ void asyncMode() {
181181
assertThat(cache1.retrieve("key3", () -> CompletableFuture.completedFuture("value3")).join())
182182
.isEqualTo("value3");
183183
cache1.evict("key3");
184+
assertThat(cache1.retrieve("key3")).isNull();
184185
assertThat(cache1.retrieve("key3", () -> CompletableFuture.completedFuture(null)).join()).isNull();
186+
assertThat(cache1.retrieve("key3").join()).isEqualTo(new SimpleValueWrapper(null));
185187
assertThat(cache1.retrieve("key3", () -> CompletableFuture.completedFuture(null)).join()).isNull();
186188
}
187189

spring-context/src/main/java/org/springframework/cache/Cache.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ default CompletableFuture<?> retrieve(Object key) {
151151
* <p>If possible, implementations should ensure that the loading operation
152152
* is synchronized so that the specified {@code valueLoader} is only called
153153
* once in case of concurrent access on the same key.
154-
* <p>Null values are generally not supported by this method. The provided
155-
* {@link CompletableFuture} handle produces a value or raises an exception.
156-
* If the {@code valueLoader} raises an exception, it will be propagated
157-
* to the {@code CompletableFuture} handle returned from here.
154+
* <p>Null values always indicate a user-level {@code null} value with this
155+
* method. The provided {@link CompletableFuture} handle produces a value
156+
* or raises an exception. If the {@code valueLoader} raises an exception,
157+
* it will be propagated to the returned {@code CompletableFuture} handle.
158158
* @param key the key whose associated value is to be returned
159159
* @return the value to which this cache maps the specified key, contained
160160
* within a {@link CompletableFuture} which will never be {@code null}.

0 commit comments

Comments
 (0)