cachingcollectionsredis

Cache with redis cache manager, redisTemplate and multiple serializers


I need to cache multiple types like:

public Country findCountry(String countryName)

and:

public List<Destination> findAllDestinations(String countryName)

I am using RedisCacheManager and RedisTemplate only support only one serializer.


Solution

  • It is solved now after some research.

    1. change spring-data-redis to 1.4.2.RELEASE
    2. extend RedisCacheManager with your class with cache map to serializer (cacheName->serializer) and caches names
    3. overrides the getCache method(Cache getCache(String name)) and based on cache name, set the serializer name in the redis template
    4. use your customized cache manager

    Example -

    public class CustomRedisCacheManager extends RedisCacheManager
    {
        public static final String CACHE_NAME_DEFAULT = "default";
        public static final String CACHE_NAME_COUNTRY = "country";
        public static final String CACHE_NAME_DESTINATIONS = "destinations";    
    
        private Map<String, RedisCache> redisCaches = new HashMap<>();
    
        public CustomRedisCacheManager(Map<String, RedisTemplate> redisTemplates)
        {
            super(redisTemplates.get(CACHE_NAME_DEFAULT), redisTemplates.keySet());
    
            redisTemplates.keySet().stream().forEach(cacheName ->    redisCaches.put(cacheName, new RedisCache(cacheName, null,   redisTemplates.get(cacheName), 0)));
        }
    
        @Override
        public Cache getCache(String cacheName)
        {
            return redisCaches.get(cacheName);
        }
    }
        
    @Configuration
    @EnableCaching
    public class RedisConfiguration extends CachingConfigurerSupport
    {    
        @Bean
        public JedisConnectionFactory jedisConnectionFactory()
        {
            JedisConnectionFactory factory = new JedisConnectionFactory();
            factory.setHostName(redisHostName);
            factory.setPort(redisPort);            
            factory.setTimeout(100);
    
            return factory;
        }
    
        @Bean
        public CacheManager cacheManager()
        {
            Map<String, RedisTemplate> templates = new HashMap<>();
            templates.put(CACHE_NAME_DEFAULT, getDefaultRedisTemplate());
            templates.put(CACHE_NAME_COUNTRY, getMetadataRedisTemplate());
            templates.put(CACHE_NAME_DESTINATIONS, getDestinationsRedisTemplate());        
    
            SabreRedisCacheManager sabreRedisCacheManager = new    SabreRedisCacheManager(templates);
    
            return sabreRedisCacheManager;
        }
    
        @Bean
        public RedisTemplate<Object, Object> getDefaultRedisTemplate()
        {
            return getBaseRedisTemplate();
        }
    
        @Bean
        public RedisTemplate<Object, Object> getCountryRedisTemplate()
        {
            RedisTemplate<Object, Object> redisTemplate = getBaseRedisTemplate();
            redisTemplate.setValueSerializer(jsonRedisSerializer(Country.class));
    
            return redisTemplate;
        }
    
        @Bean
        public RedisTemplate<Object, Object> getDestinationsRedisTemplate()
        {
            RedisTemplate<Object, Object> redisTemplate = getBaseRedisTemplate();
            redisTemplate.setValueSerializer(jsonRedisSerializer(TypeFactory.defaultInstance()
    .constructCollectionType(List.class, Destination.class)));
    
            return redisTemplate;
        }
        
        private RedisTemplate<Object, Object> getBaseRedisTemplate()
        {
            RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(jedisConnectionFactory());
            redisTemplate.setKeySerializer(stringRedisSerializer());
            redisTemplate.setHashKeySerializer(stringRedisSerializer());
            redisTemplate.setValueSerializer(jsonRedisSerializer(Object.class));
    
            return redisTemplate;
        }
        
        private Jackson2JsonRedisSerializer jsonRedisSerializer(Class type)
        {
            return jsonRedisSerializer(TypeFactory.defaultInstance().constructType(type));
        }
    
        private Jackson2JsonRedisSerializer jsonRedisSerializer(JavaType javaType)
        {
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(javaType);
            jackson2JsonRedisSerializer.setObjectMapper(new JsonObjectMapper());
        
            return jackson2JsonRedisSerializer;
        }
    }