14

I am using RedisCacheManager to store my cache data in my spring-boot application. Default serializer seems to serialize everything into byte and deserialize from byte to appropriate java type.

However, I want to make the cache data be stored as json so that I can read it from none-java clients.

I found that switching from default one to other serializers such as Jackson2JsonRedisSerializer supposed to work. After doing this, deserialization phase fails.

pom.xml

 <dependency>
 <groupId>org.springframework.data</groupId>
 <artifactId>spring-data-redis</artifactId>
 </dependency>
 <dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
 </dependency>

CacheConfig.java

@Configuration
@EnableCaching
public class CacheConfig {
 @Bean
 public RedisConnectionFactory createRedisConnectionFactory() {
 JedisConnectionFactory factory = new JedisConnectionFactory();
 factory.setHostName("localhost");
 return factory;
 }
// SPRING-DATA-REDIS ALREADY PROVIDES A STRING REDIS TEMPLATE, SO THE FOLLOWING IS NOT NECESSARY
// @Bean
// public RedisTemplate<String, String> createRedisTemplate(RedisConnectionFactory factory) {
// RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
// redisTemplate.setConnectionFactory(factory);
// return redisTemplate;
// }
 @Bean
 public CacheManager redisCacheManager(RedisTemplate redisTemplate) {
 RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
 return cacheManager;
 }
}

Is there a way to store them in a pure JSON format and successfully deserialize from it?

asked Jan 26, 2017 at 14:24

3 Answers 3

22

add this in your configuration to explicitly set the jackson serializer in redis template.

public @Bean RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
 RedisTemplate<Object, Object> template = new RedisTemplate<>();
 template.setConnectionFactory(connectionFactory);
 template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
 template.setKeySerializer(new StringRedisSerializer());
 template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
 template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
 return template;
}
answered Jan 27, 2017 at 6:17
Sign up to request clarification or add additional context in comments.

4 Comments

I've already tried this but cache data in redis is still in bytes. like "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x01"
Have you checked with my updated answer? Let me know.
This doesn't works if we use CrudRepository patterns for persisting data?
This probably works for the older version of spring-data-redis however it doesn't work for the latest version ATM
14

As of spring-data-jpa:2.0.2.RELEASE at least, configuring the default redis template does not affect how the @Cacheable annotation family accesses redis. Anyway, since I'm using a redis template for more than that, it's not something I want to do.

This, however, isolates the configuration for the cache manager and works as expected:

@Configuration
@EnableCaching
public class RedisCacheManagerConfiguration {
 @Autowired
 private RedisConnectionFactory redisConnectionFactory;
 @Bean
 public CacheManager redisCacheManager() {
 RedisSerializationContext.SerializationPair<Object> jsonSerializer = 
 RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer());
 return RedisCacheManager.RedisCacheManagerBuilder
 .fromConnectionFactory(redisConnectionFactory)
 .cacheDefaults(
 RedisCacheConfiguration.defaultCacheConfig()
 .entryTtl(Duration.ofDays(1))
 .serializeValuesWith(jsonSerializer)
 )
 .build();
 }
}

It makes use of the generic Json serializer for Redis (GenericJackson2JsonRedisSerializer).

You can also configure other aspects of the cache manager, such as the time-to-live of the key in redis.

answered Oct 4, 2018 at 14:21

Comments

1

I managed to make this by defining RedisConnectionFactory

@Bean
public RedisConnectionFactory jedisPool()
{
 JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(new JedisPoolConfig());
 jedisConnectionFactory.setHostName("localhost");
 return jedisConnectionFactory;
}

and then using StringRedisTemplate

ValueOperations<String, String> ops = redisTemplate.opsForValue();
ops.set("key", "Json_string");

I hope this might help!

answered Jan 27, 2017 at 12:58

2 Comments

You are right, if you use redisTemplate directly, you have full control over data in and out. However, in my case, I use cache annotations such as @Cacheable, @Cacheput where cacheManager uses redisTemplate for cache operations.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.