SpringBoot Caching on Redis using JSON


SpringBoot Caching on Redis using JSON

This article presumes that reader is familiar with using SpringBoot Caching using Redis. Reader also knows that by default, this caching uses Java serialization and deserialization. i.e. your classes must implement Serializable. 
Then why would you want to save data as JSON in redis? It would spend time in serialization and deserialization. 
  => Ability to look into what is saved in cache (helpful in debugging)

Base understanding

  1. SpringBoot caching is provided by artifact "spring-boot-starter-cache". It uses in-memory caching by default.
  2. Redis caching is provided by "spring-boot-starter-data-redis" artifact. No extra configuration or code needed to connect to single node redis hosted on local. Just have @EnableCaching.
  3. "spring-boot-starter-data-redis" uses "Lettuce" driver by default. For "Jedis" driver you need to exclude Lettuce and include Jedis.
  4. Default serialization and deserialization mechanism is Java serialization and deserailization.

But I want JSON

Lets start with pom

    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-data-redis</artifactid>
    </dependency>

Do not have any redis related library other than this.

Now the configuration

    @Configuration
    @EnableCaching
    public class CacheConfig {
    
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
    
        @Bean
        public CacheManager redisCacheManager() {
            // Create JSON Redis Serializer to use
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.enable(JsonGenerator.Feature.IGNORE_UNKNOWN);
            objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
            objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
            GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
    
            // Configure RedisCacheManager
            RedisSerializationContext.SerializationPair jsonSerializer =
                    RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer);
            return RedisCacheManager.RedisCacheManagerBuilder
                    .fromConnectionFactory(redisConnectionFactory)
                    .cacheDefaults(
                            RedisCacheConfiguration.defaultCacheConfig()
                                    .entryTtl(Duration.ofDays(1))
                                    .serializeValuesWith(jsonSerializer)
                                    .disableCachingNullValues()
                    )
                    .build();
        }
    }

Note: ObjectMapper is jackson object mapper.

No one uses default ObjectMapper - as it doesn't satisfy our needs. I have had to always configure it.
But with Caching, we have an important configuration marked in RED. This tells Jackson that when serializing or deserializing use a "@class" field to tell what object you are serializing or deserializing.

A sample generated by my code is:


Note: I have no strong reason to use JSON format when serializing. But I struggled to find a proper example of how to use JSON as a serialization mechanism of redis caching for latest spring boot - 2.3.0.RELEASE.






Comments