7

I'm using Caffeine cache to store data received from an external system.

LoadingCache<String, String> clientCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(id -> {
  System.out.println("Generating new value for " + id);
  if (id.equalsIgnoreCase("1")) {
    return null;
  }
  return new Date().toString();
});

System.out.println(clientCache.get("1"));
System.out.println(clientCache.get("1"));
System.out.println(clientCache.get("2"));
System.out.println(clientCache.get("3"));

This resulted,

Generating new value for 1
null
Generating new value for 1
null
Generating new value for 2
Wed May 20 17:11:01 IST 2020
Generating new value for 3
Wed May 20 17:11:01 IST 2020
Wed May 20 17:11:01 IST 2020

Caffeine is not saving null values in cache. How to store nulls in Caffeine?

Santosh Hegde
  • 3,420
  • 10
  • 35
  • 51
  • 4
    I don't know Caffeine but I'd guess that it can't distinguish between `null` meaning "I tried but got null" and "I didn't try yet". Maybe you could use `Optional` for the values instead, i.e. instead of returning `null` you return `Optional.empty()`. Of course you'd then have to deal with the optionals then but that might improve your code or at least would be easy to adapt to the current logic with a `orElse(null)`. – Thomas May 20 '20 at 11:49
  • 1
    @Thomas good observation. Just like `Map.computeIfAbsent` a null return value indicates that it cannot be stored, so a subsequent call will try to recompute. – Ben Manes May 20 '20 at 19:13

1 Answers1

13

From this issue report:

The cache does not allow storing null values. If you perform a computation and return null then this indicates the data doesn't exist and the caller receives null.

In addition, it advises:

Optional is a good technique for negative caching.

Joe
  • 29,416
  • 12
  • 68
  • 88