FalconIA
FalconIA

Reputation: 91

Collisions may occur when using Spring @Cacheable and SimpleKeyGenerator

When I use @Cacheable and call different method with same parameter, it generated a same key. SimpleKeyGenerator generated key without cache names.

I use spring-boot 1.3.2 with spring 4.2.4.

Here is a sample:

@Component
public static class CacheableTestClass {

    @Cacheable(cacheNames = "test-cacheproxy-echo1")
    public String echo1(String text) {
        return text;
    }

    @Cacheable(cacheNames = "test-cacheproxy-echo2")
    public String echo2(String text) {
        return "Another " + text;
    }
}

And run a test:

assertEquals("OK", cacheableTestClass.echo1("OK"));
assertEquals("Another OK", cacheableTestClass.echo2("OK")); // Failure: expected 'Another OK', actual 'OK'.

So, is there a way to resolve this issue? Thanks a lot.

Update

Here is my CacheManager configuration.

@Bean
@ConditionalOnMissingBean(name = "cacheRedisTemplate")
public RedisTemplate<Object, Object> cacheRedisTemplate(
        RedisConnectionFactory redisConnectionFactory)
        throws UnknownHostException {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    template.setHashKeySerializer(template.getKeySerializer());
    return template;
}

@Bean
public RedisCacheManager cacheManager(@Qualifier("cacheRedisTemplate")  RedisTemplate<Object, Object> cacheRedisTemplate) {
    RedisCacheManager cacheManager = new RedisCacheManager(cacheRedisTemplate);
    cacheManager.setDefaultExpiration(
            redisCacheProperties().getDefaultExpiration());
    cacheManager.setExpires(redisCacheProperties().getExpires());
    return cacheManager;
}

Upvotes: 1

Views: 1187

Answers (1)

Stephane Nicoll
Stephane Nicoll

Reputation: 33151

This has nothing to do with SimpleKeyGenerator but this is a redis-specific issue that does not use the name of the cache as a discriminant for the key it uses to store the value.

You need to invoke setUsePrefix(true) on your RedisCacheManager. This is what Spring Boot does when it auto-configures the cache manager for you. Note that it should have been the default and we're discussing how we can improve the out-of-the-box experience in a future release

Upvotes: 4

Related Questions