admin管理员组

文章数量:1400041

When I am inserting object to redis, I am using spring annotation and when I try to get the object I am using redis template implementation. While doing so, I am getting exception.

Below is the spring annotation based caching:

@CachePut(value = "API", key = "#key")
public Object upsert(String key, Object value) {
    return value;
}

@Cacheable(value = "API", key = "#key")
public Object get(String key) {
    return null;
}

Below is the redis template based implementation:

public Object getValue(String key) {
    ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
    return valueOperations.get(key);
}

public void setValue(String key, Object value) {
    ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
    valueOperations.set(key, value);
}

If I use @CachePut with redisTemplate.opsForValue().get(), I am getting excecption as:

Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('¬' (code 172)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (byte[])"��\u0000\u0005t\u0000\u0002US"; line: 1, column: 2]

If I use redisTemplate.opsForValue().set() with @Cacheable, I am getting exception as:

nested exception is .springframework.data.redis.serializer.SerializationException: Cannot deserialize; 
nested exception is .springframework.core.serializer.support.SerializationFailedException: 
Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; 
nested exception is java.io.StreamCorruptedException: 
invalid stream header: 22547275] with root cause

I am doing this experiment because I am working on a legacy project where spring-annotation based caching implementation is present. Now I have a usecase to do the bulk query for multiple keys. I want to use MGET using redis template, but it throws the first exception mentioned above, as its similar to redisTemplate.opsForValue().get():

protected List<Object> multiGet(List<String> keys) {
    List<Object> cachedDataList = new ArrayList<>();
    try {
        List<Object> cacheObjects = redisTemplate.opsForValue().multiGet(keys);

        if (cacheObjects != null) {
            cachedDataList.addAll(cacheObjects);
        } else {
            log.debug("getStateCacheDataBatch: null values for {}", keys);
        }
    } catch (Exception e) {
        log.error("Error while fetching batch state cached data for keys {}", keys, e);
    }
    return cachedDataList;
}

I have same config for both, so it should be using same for serialization.

@Bean
RedisTemplate<String, Object> redisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory) {
    final RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}

Need suugestion on this.

When I am inserting object to redis, I am using spring annotation and when I try to get the object I am using redis template implementation. While doing so, I am getting exception.

Below is the spring annotation based caching:

@CachePut(value = "API", key = "#key")
public Object upsert(String key, Object value) {
    return value;
}

@Cacheable(value = "API", key = "#key")
public Object get(String key) {
    return null;
}

Below is the redis template based implementation:

public Object getValue(String key) {
    ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
    return valueOperations.get(key);
}

public void setValue(String key, Object value) {
    ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
    valueOperations.set(key, value);
}

If I use @CachePut with redisTemplate.opsForValue().get(), I am getting excecption as:

Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('¬' (code 172)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (byte[])"��\u0000\u0005t\u0000\u0002US"; line: 1, column: 2]

If I use redisTemplate.opsForValue().set() with @Cacheable, I am getting exception as:

nested exception is .springframework.data.redis.serializer.SerializationException: Cannot deserialize; 
nested exception is .springframework.core.serializer.support.SerializationFailedException: 
Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; 
nested exception is java.io.StreamCorruptedException: 
invalid stream header: 22547275] with root cause

I am doing this experiment because I am working on a legacy project where spring-annotation based caching implementation is present. Now I have a usecase to do the bulk query for multiple keys. I want to use MGET using redis template, but it throws the first exception mentioned above, as its similar to redisTemplate.opsForValue().get():

protected List<Object> multiGet(List<String> keys) {
    List<Object> cachedDataList = new ArrayList<>();
    try {
        List<Object> cacheObjects = redisTemplate.opsForValue().multiGet(keys);

        if (cacheObjects != null) {
            cachedDataList.addAll(cacheObjects);
        } else {
            log.debug("getStateCacheDataBatch: null values for {}", keys);
        }
    } catch (Exception e) {
        log.error("Error while fetching batch state cached data for keys {}", keys, e);
    }
    return cachedDataList;
}

I have same config for both, so it should be using same for serialization.

@Bean
RedisTemplate<String, Object> redisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory) {
    final RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
    return template;
}

Need suugestion on this.

Share Improve this question asked Mar 25 at 20:26 HappsHapps 1258 bronze badges 3
  • There already is a Redis based implementation for the cache, why implement your own? I get the feeling something is missing here. – M. Deinum Commented Mar 25 at 20:51
  • @M.Deinum As I mentioned, in my legacy project CachePut, Cacheable annotation is present for caching. Now I want to implement the multiGet, as there is no annotion available for the same, hence I am using redisTemplate.opsForValue().multiGet(keys). But it is throwing the exception – Happs Commented Mar 25 at 21:02
  • Those annotations are from Spring afaik unless you have some AOP etc. that does something with those annotations. – M. Deinum Commented Mar 26 at 8:01
Add a comment  | 

1 Answer 1

Reset to default 0

I found the solution.

The annotation(CachePut, Cacheable) are from Spring and they are using JdkSerializationRedisSerializer for serializing the object. And I have configured redisTemplate with GenericJackson2JsonRedisSerializer.

If I use CachePut to store an object and redisTemplate to retrieve it, an exception will be thrown due to a compatibility mismatch between the two serializers.

To resolve I have configured redisTemplate with JdkSerializationRedisSerializer and it worked.

@Bean("customRedisTemplate")
RedisTemplate<String, Object> customRedisTemplate(@Autowired RedisConnectionFactory redisConnectionFactory) {
    final RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new JdkSerializationRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    template.setHashValueSerializer(new JdkSerializationRedisSerializer());
    return template;
}

本文标签: Spring Declarative Annotationbased Caching compatibity with Redis Template ImplementationStack Overflow