Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Does Spring 4.3 Unwrap An Optional From Cache If It Was Empty

My team has been using the @Cachable annotation in Spring and caching Optional<> in Java. We just upgraded to Spring 4.3 and started getting errors because or caches do not allow nulls and Spring was unwrapping the Optional and attempting to put in null when it was empty.

I tried looking in the docs but I could not find anywhere that explains how Spring behaves when it goes to the cache, finds null and is supposed to return an Optional<>. Can anyone provide some context; will it convert it to an empty Optional or will it throw any error?

like image 958
Dave Avatar asked Apr 27 '18 13:04

Dave


People also ask

How does Spring handle cache?

To enable caching, Spring makes good use of annotations, much like enabling any other configuration level feature in the framework. Note: After we enable caching, for the minimal setup, we must register a cacheManager.

How do I evict all cache in spring?

Spring provides two ways to evict a cache, either by using the @CacheEvict annotation on a method, or by auto-wiring the CacheManger and clearing it by calling the clear() method.

How does @cachable work?

As the name implies, @Cacheable is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method.

What is the use of @cacheable annotation?

Annotation Interface Cacheable. Annotation indicating that the result of invoking a method (or all methods in a class) can be cached. Each time an advised method is invoked, caching behavior will be applied, checking whether the method has been already invoked for the given arguments.


2 Answers

A little bit late, I know. I found this question looking for the same problem.

I am not a native english speaker and was confused by the meaning of "unless". In the end I managed to solve it doing the opposite @Anand suggested:

unless = "#result == null"

like so:

@Cacheable(value = "clients", key = "#p0.concat(#p1)", unless = "#result == null")
Optional<Client> findByClientAndProfile(String idClient, String profile);
like image 146
marcellorvalle Avatar answered Oct 25 '22 09:10

marcellorvalle


Support for Optional was added to the Spring Cache Abstraction around version 4.3.3.RELEASE See the Conditional Caching section of this for an example.

The cache abstraction supports java.util.Optional, using its content as cached value only if it present. #result always refers to the business entity and never on a supported wrapper so the previous example can be rewritten as follows:

@Cacheable(cacheNames="book", condition="#name.length < 32", unless="#result.hardback")
public Optional<Book> findBook(String name)

Note that result still refers to Book and not Optional.

Also see this SO post.

like image 30
Michael Peacock Avatar answered Oct 25 '22 11:10

Michael Peacock