badCoder
badCoder

Reputation: 121

@Cacheable annotation working not properly in Spring

I encountered a strange behaviour while using @Cacheable annotation in Spring. I have a method marked as @Cacheable and that returns Map:

//dao layer
@Cacheable(value = "Cache1")
public Map<String, String> getNamesByDateAndCurrency(LocalDate date, String currency) {
    // Returns some map
}

I call this method from the following method and change the map using the retainAll() method:

//service layer
@Autowired
private DaoImpl dao;
...
@Cacheable( value = "Cache2")
public List<Integer> getUUIDs(Integer requestNumber, Set<String> set) {
   //some code..
   Map<String, String> names = dao.getNamesByDateAndCurrency(params..);
   names.keySet().retainAll(set);
   //some other code, no any changes of map in further
}

dao.getNamesByDateAndCurrency(params..) expression returns, as expected, the cached data if I call this method a second time with the same parameters.

The problem is that the getNamesByDateAndCurrency method is caching the data changed after performing the retainAll method.

My question is why an external action (retainAll) method affects the cached response? Why hasn't it returned original data from getNamesByDateAndCurrency method?

Thanks in advance!

Upvotes: 0

Views: 1529

Answers (1)

Henri
Henri

Reputation: 5711

Spring cache stores the result in the cache by reference. Then, the caching framework used (Ehcache in your case I think) will store the result according to its configuration. Most frameworks will store it by reference by default because it is much faster.

You have 2 solutions:

  1. Code in an immutable way. So when receiving the map, instead of modifying it in place, just create a copy. You can make sure of it by wrapping the result in a Collections.unmodifiableMap
  2. Tell Ehcache to store by value. This is a bit more involved because you need to be able to copy the value. But it will work transparently

Note that whether you are storing data on the heap, on disks or clustered, it would work as expected by default. Because all these options require to copy the key and the value. Only on-heap has a "by reference" storage optimization.

Upvotes: 1

Related Questions