Search code examples
javaspring-bootspring-cache

Spring @Cacheable annotation for same method in different service


I have implemented the standard redis caching template in a Spring boot application as per the following article:

What I have is two different services that get a list of objects:

@RequestMapping("/admin/test/list")
public String testCache() {

    List<Cocktail> cocktails = cocktailsService.list();
    List<Ingredient> ingredients = ingredientsService.list();

    return "index";
}

Note: that the method name and signature is the same (i.e. list() ) but they both have different cache names as such:

// CocktailService
@Cacheable(value = “COCKTAILS”)
public List<Cocktail> list() {
    return repository.findAll();
}

// IngredientsService
@Cacheable(value = “INGREDIENTS”)
public List<Ingredient> list() {
    return repository.findAll();
}

The Problem

Even thou the cache name is different the method is always returning the list from the cache as there is no distinction at method level when generating the keys.

Possible Solutions

I know three solutions could be:

  1. Change the method name
  2. Write a custom KeyGenerator
  3. Set Cache SpEL to make use of #root.target such as:

    @Cacheable(value=”COCKTAILS”, key="{#root.targetClass}") @Cacheable(value=”INGREDIENTS”, key="{#root.targetClass}")

Question

But surly there must be a better way or not?


Solution

  • There is an issue in the article you've followed. When creating your CacheManager bean, you need to invoke cacheManager.setUsePrefix(true);, only then the cache names COCKTAILS and INGREDIENTS will be used as Redis cache key discriminator.

    Here is how you should declare your cache manager bean:

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
    
        // Number of seconds before expiration. Defaults to unlimited (0)
        cacheManager.setDefaultExpiration(300);
        cacheManager.setUsePrefix(true);
        return cacheManager;
    }