Actual caching of null values in retrieve(key, valueLoader)

See gh-31637
This commit is contained in:
Juergen Hoeller 2023-11-22 15:56:26 +01:00
parent 441e210533
commit 824bc09d11
3 changed files with 14 additions and 5 deletions

View File

@ -148,7 +148,14 @@ public class CaffeineCache extends AbstractValueAdaptingCache {
@SuppressWarnings("unchecked")
@Override
public <T> CompletableFuture<T> retrieve(Object key, Supplier<CompletableFuture<T>> valueLoader) {
return (CompletableFuture<T>) getAsyncCache().get(key, (k, e) -> valueLoader.get());
if (isAllowNullValues()) {
return (CompletableFuture<T>) getAsyncCache()
.get(key, (k, e) -> valueLoader.get().thenApply(this::toStoreValue))
.thenApply(this::fromStoreValue);
}
else {
return (CompletableFuture<T>) getAsyncCache().get(key, (k, e) -> valueLoader.get());
}
}
@Override

View File

@ -181,7 +181,9 @@ class CaffeineCacheManagerTests {
assertThat(cache1.retrieve("key3", () -> CompletableFuture.completedFuture("value3")).join())
.isEqualTo("value3");
cache1.evict("key3");
assertThat(cache1.retrieve("key3")).isNull();
assertThat(cache1.retrieve("key3", () -> CompletableFuture.completedFuture(null)).join()).isNull();
assertThat(cache1.retrieve("key3").join()).isEqualTo(new SimpleValueWrapper(null));
assertThat(cache1.retrieve("key3", () -> CompletableFuture.completedFuture(null)).join()).isNull();
}

View File

@ -151,10 +151,10 @@ public interface Cache {
* <p>If possible, implementations should ensure that the loading operation
* is synchronized so that the specified {@code valueLoader} is only called
* once in case of concurrent access on the same key.
* <p>Null values are generally not supported by this method. The provided
* {@link CompletableFuture} handle produces a value or raises an exception.
* If the {@code valueLoader} raises an exception, it will be propagated
* to the {@code CompletableFuture} handle returned from here.
* <p>Null values always indicate a user-level {@code null} value with this
* method. The provided {@link CompletableFuture} handle produces a value
* or raises an exception. If the {@code valueLoader} raises an exception,
* it will be propagated to the returned {@code CompletableFuture} handle.
* @param key the key whose associated value is to be returned
* @return the value to which this cache maps the specified key, contained
* within a {@link CompletableFuture} which will never be {@code null}.