Affects: v6.1.1

@Cacheable throws a NullPointerException when the mentioned method returns a null value, whereas this behavior was not present in previous versions.

    @Cacheable(cacheNames = "history", key = "#userId+#videoUniquename")
    public Mono<History> findVideoLastHistory(String userId, String videoUniquename) {
        Sort sort = Sort.by(Sort.Direction.DESC, "lastModifiedDate");
        return historyRepository.findFirstByUserIdAndVideoUniqueName(userId, videoUniquename, sort);
    }
java.lang.NullPointerException: value
    at java.base/java.util.Objects.requireNonNull(Objects.java:259) ~[na:na]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.MonoFlatMap] :
    reactor.core.publisher.Mono.flatMap(Mono.java:3116)
    org.springframework.cache.interceptor.CacheAspectSupport$ReactiveCachingHandler.findInCaches(CacheAspectSupport.java:1077)
Error has been observed at the following site(s):
    *________Mono.flatMap ⇢ at org.springframework.cache.interceptor.CacheAspectSupport$ReactiveCachingHandler.findInCaches(CacheAspectSupport.java:1077)
    |_ Mono.switchIfEmpty ⇢ at org.springframework.cache.interceptor.CacheAspectSupport$ReactiveCachingHandler.findInCaches(CacheAspectSupport.java:1078)
    *________Mono.flatMap ⇢ at com.madwind.cinema.server.application.service.impl.UserServiceImpl.getVideoLastHistory(UserServiceImpl.java:115)

Comment From: jhoeller

I was able to reproduce a similar exception for a cache hit now, after the initial caching attempt. Could you please confirm that this happens for a cache hit and not for the initial cache lookup? So that the initial caching of the null value worked but a subsequent lookup of the cached null value fails? Or is your scenario even failing on the first attempt?

Comment From: jhoeller

This seems to be a simple oversight due to a missing unit test for the cache hit scenario with a cached null value. We need to use Mono.justOrEmpty there rather than Mono.just; this fix will be available in a 6.1.2 snapshot ASAP.

Comment From: madwind

I was able to reproduce a similar exception for a cache hit now, after the initial caching attempt. Could you please confirm that this happens for a cache hit and not for the initial cache lookup? So that the initial caching of the null value worked but a subsequent lookup of the cached null value fails? Or is your scenario even failing on the first attempt?

It failed after a cache hit, initial caching of the null value worked

2023-11-30T18:58:42.248+08:00 TRACE 16276 --- [ntLoopGroup-2-3] o.s.cache.interceptor.CacheInterceptor   : Creating cache entry for key '6128eebc2e8decfbb06be2722015xxxx' in cache(s) [history]
2023-11-30T18:58:55.528+08:00 TRACE 16276 --- [ntLoopGroup-2-1] o.s.cache.interceptor.CacheInterceptor   : Computed cache key '6128eebc2e8decfbb06be2722015xxxx' for operation Builder[public reactor.core.publisher.Mono com.madwind.cinema.server.application.service.impl.HistoryServiceImpl.findVideoLastHistory(java.lang.String,java.lang.String)] caches=[history] | key='#userId+#videoUniquename' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'
2023-11-30T18:58:55.528+08:00 TRACE 16276 --- [ntLoopGroup-2-1] o.s.cache.interceptor.CacheInterceptor   : Cache entry for key '6128eebc2e8decfbb06be2722015xxxx' found in cache(s) [history]
2023-11-30T18:58:55.529+08:00 ERROR 16276 --- [ntLoopGroup-2-1] s.g.e.ExceptionResolversExceptionHandler : Unresolved NullPointerException for executionId 2b5415ea-6419-8859-72a5-7f35098a826e

Comment From: jhoeller

Thanks for checking, then it's definitely the same scenario which should be fixed in the latest 6.1.2 snapshot now.