Skip to content

Commit 4a6c3e8

Browse files
committed
Fix reactive retrieval of cached null value for empty Mono
Closes gh-31722
1 parent f77713b commit 4a6c3e8

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,13 +1068,13 @@ public Object findInCaches(CacheOperationContext context, Cache cache, Object ke
10681068
if (adapter.isMultiValue()) {
10691069
return adapter.fromPublisher(Flux.from(
10701070
Mono.fromFuture(cachedFuture)
1071-
.flatMap(value -> (Mono<?>) evaluate(Mono.just(unwrapCacheValue(value)), invoker, method, contexts)))
1071+
.flatMap(value -> (Mono<?>) evaluate(Mono.justOrEmpty(unwrapCacheValue(value)), invoker, method, contexts)))
10721072
.flatMap(v -> (v instanceof Iterable<?> iv ? Flux.fromIterable(iv) : Flux.just(v)))
10731073
.switchIfEmpty(Flux.defer(() -> (Flux<?>) evaluate(null, invoker, method, contexts))));
10741074
}
10751075
else {
10761076
return adapter.fromPublisher(Mono.fromFuture(cachedFuture)
1077-
.flatMap(value -> (Mono<?>) evaluate(Mono.just(unwrapCacheValue(value)), invoker, method, contexts))
1077+
.flatMap(value -> (Mono<?>) evaluate(Mono.justOrEmpty(unwrapCacheValue(value)), invoker, method, contexts))
10781078
.switchIfEmpty(Mono.defer(() -> (Mono) evaluate(null, invoker, method, contexts))));
10791079
}
10801080
}

spring-context/src/test/java/org/springframework/cache/CacheReproTests.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ void spr14235AdaptsToCompletableFuture() {
202202
assertThat(bean.findById("tb2").join()).isNotSameAs(tb);
203203
assertThat(cache.get("tb2")).isNull();
204204

205+
assertThat(bean.findByIdEmpty("").join()).isNull();
206+
assertThat(bean.findByIdEmpty("").join()).isNull();
207+
assertThat(cache.get("").get()).isNull();
208+
205209
context.close();
206210
}
207211

@@ -226,6 +230,10 @@ void spr14235AdaptsToCompletableFutureWithSync() throws Exception {
226230
assertThat(bean.findById("tb1").get()).isSameAs(tb);
227231
assertThat(cache.get("tb1").get()).isSameAs(tb);
228232

233+
assertThat(bean.findById("").join()).isNull();
234+
assertThat(bean.findById("").join()).isNull();
235+
assertThat(cache.get("").get()).isNull();
236+
229237
context.close();
230238
}
231239

@@ -257,6 +265,10 @@ void spr14235AdaptsToReactorMono() {
257265
assertThat(bean.findById("tb2").block()).isNotSameAs(tb);
258266
assertThat(cache.get("tb2")).isNull();
259267

268+
assertThat(bean.findByIdEmpty("").block()).isNull();
269+
assertThat(bean.findByIdEmpty("").block()).isNull();
270+
assertThat(cache.get("").get()).isNull();
271+
260272
context.close();
261273
}
262274

@@ -281,6 +293,10 @@ void spr14235AdaptsToReactorMonoWithSync() {
281293
assertThat(bean.findById("tb1").block()).isSameAs(tb);
282294
assertThat(cache.get("tb1").get()).isSameAs(tb);
283295

296+
assertThat(bean.findById("").block()).isNull();
297+
assertThat(bean.findById("").block()).isNull();
298+
assertThat(cache.get("").get()).isNull();
299+
284300
context.close();
285301
}
286302

@@ -312,6 +328,10 @@ void spr14235AdaptsToReactorFlux() {
312328
assertThat(bean.findById("tb2").collectList().block()).isNotEqualTo(tb);
313329
assertThat(cache.get("tb2")).isNull();
314330

331+
assertThat(bean.findByIdEmpty("").collectList().block()).isEmpty();
332+
assertThat(bean.findByIdEmpty("").collectList().block()).isEmpty();
333+
assertThat(cache.get("").get()).isEqualTo(Collections.emptyList());
334+
315335
context.close();
316336
}
317337

@@ -336,6 +356,10 @@ void spr14235AdaptsToReactorFluxWithSync() {
336356
assertThat(bean.findById("tb1").collectList().block()).isEqualTo(tb);
337357
assertThat(cache.get("tb1").get()).isEqualTo(tb);
338358

359+
assertThat(bean.findById("").collectList().block()).isEmpty();
360+
assertThat(bean.findById("").collectList().block()).isEmpty();
361+
assertThat(cache.get("").get()).isEqualTo(Collections.emptyList());
362+
339363
context.close();
340364
}
341365

@@ -568,6 +592,11 @@ public CompletableFuture<TestBean> findById(String id) {
568592
return CompletableFuture.completedFuture(new TestBean(id));
569593
}
570594

595+
@Cacheable(value = "itemCache")
596+
public CompletableFuture<TestBean> findByIdEmpty(String id) {
597+
return CompletableFuture.completedFuture(null);
598+
}
599+
571600
@CachePut(cacheNames = "itemCache", key = "#item.name")
572601
public CompletableFuture<TestBean> insertItem(TestBean item) {
573602
return CompletableFuture.completedFuture(item);
@@ -584,7 +613,7 @@ public static class Spr14235FutureServiceSync {
584613

585614
@Cacheable(value = "itemCache", sync = true)
586615
public CompletableFuture<TestBean> findById(String id) {
587-
return CompletableFuture.completedFuture(new TestBean(id));
616+
return CompletableFuture.completedFuture(id.isEmpty() ? null : new TestBean(id));
588617
}
589618

590619
@CachePut(cacheNames = "itemCache", key = "#item.name")
@@ -601,6 +630,11 @@ public Mono<TestBean> findById(String id) {
601630
return Mono.just(new TestBean(id));
602631
}
603632

633+
@Cacheable(value = "itemCache")
634+
public Mono<TestBean> findByIdEmpty(String id) {
635+
return Mono.empty();
636+
}
637+
604638
@CachePut(cacheNames = "itemCache", key = "#item.name")
605639
public Mono<TestBean> insertItem(TestBean item) {
606640
return Mono.just(item);
@@ -617,7 +651,7 @@ public static class Spr14235MonoServiceSync {
617651

618652
@Cacheable(value = "itemCache", sync = true)
619653
public Mono<TestBean> findById(String id) {
620-
return Mono.just(new TestBean(id));
654+
return (id.isEmpty() ? Mono.empty() : Mono.just(new TestBean(id)));
621655
}
622656

623657
@CachePut(cacheNames = "itemCache", key = "#item.name")
@@ -636,6 +670,11 @@ public Flux<TestBean> findById(String id) {
636670
return Flux.just(new TestBean(id), new TestBean(id + (counter++)));
637671
}
638672

673+
@Cacheable(value = "itemCache")
674+
public Flux<TestBean> findByIdEmpty(String id) {
675+
return Flux.empty();
676+
}
677+
639678
@CachePut(cacheNames = "itemCache", key = "#id")
640679
public Flux<TestBean> insertItem(String id, List<TestBean> item) {
641680
return Flux.fromIterable(item);
@@ -654,7 +693,7 @@ public static class Spr14235FluxServiceSync {
654693

655694
@Cacheable(value = "itemCache", sync = true)
656695
public Flux<TestBean> findById(String id) {
657-
return Flux.just(new TestBean(id), new TestBean(id + (counter++)));
696+
return (id.isEmpty() ? Flux.empty() : Flux.just(new TestBean(id), new TestBean(id + (counter++))));
658697
}
659698

660699
@CachePut(cacheNames = "itemCache", key = "#id")

0 commit comments

Comments
 (0)