SasaFajkovic
SasaFajkovic

Reputation: 425

Spring boot cache evict not working from another thread

I can't understand why cache evict is not working in my scenario. I have an application that has a scheduled service in it and has MVC for user to click some stuff.

@Cacheable(value = "applicationToken")
public Optional<String> getToken() {
    return settingsRepository.getToken();
}

@CacheEvict(value = "applicationToken", allEntries = true)
public void evictApplicationTokenCache() {
    log.info("Evicting token cache.");
}

public void updateToken(String token) {
    log.info("Updating token.");

    settingsRepository.updateToken(token);
    evictApplicationTokenCache();
}

The method getToken() is called inside the scheduled service and when I tried some test to evict cache from there it worked. However, on the MVC side, if the user updates the token, the method updateToken() gets called and although it goes inside the evictApplicationTokenCache(), on the next retrieval of the token, I still get the same token and it doesn't step into the method getToken() to actually grab the token from the repository.

The only relation I found is that the threads are different for the MVN call and for the Scheduled call. From what I know, the cache should live on the context level, not the thread level. Therefore, it shouldn't matter which thread asks for the cache to be evicted.

Upvotes: 2

Views: 3581

Answers (2)

Marwen Mighri
Marwen Mighri

Reputation: 76

methods annotated with @Cacheable or @CacheEvict will be executed using AOP. and as the aspect is applied to a proxy surrounding the bean, the direct call to the bean will not fire evict cache... So make sure :

1 - you are calling the method annotated with @EvictCache from another Spring context bean.

2 - or use the cache manger bean

...

@Autowired
CacheManager cacheManager;

...
    
Optional.ofNullable(cacheManager.getCache("THE_CACHE_NAME"))
.ifPresent(
    cache -> cache.evictIfPresent("THE_KEY"));

Upvotes: 0

Santiago Medina
Santiago Medina

Reputation: 579

It seems that the updateToken() and evictApplicationTokenCache() methods are in the same class.

In that case, the @CacheEvict annotation will be ignored, because cache handling is implemented by interceptors that are only involved when you call a method from one component to a different (injected) component.

If that's the situation, you can move the evictApplicationTokenCache() method to a helper @Component, or put the @CacheEvict annotation on the updateToken() method.

Upvotes: 1

Related Questions