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?
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;
}
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.
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!