7

According to this answer, one RedisTemplate cannot support multiple serializers for values. So I want to create multiple RedisTemplates for different needs, specifically one for string actions and one for object to JSON serializations, to be used in RedisCacheManager. I'm using Spring Boot and the current RedisTemplate is autowired, I'm wondering what's the correct way to declare a second RedisTemplate instance sharing the same Jedis connection factory but has its own serializers?

Tried something like this in two different components,

Component 1 declares,

    @Autowired
    private RedisTemplate redisTemplate;

    redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(Instance.class));

Component 2 declares,

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

In this case the two templates actually are the same. Traced into Spring code and found component 1's template got resolved to autoconfigured stringRedisTemplate.

Manually calling RedisTemplate's contructor and then its afterPropertiesSet() won't work either as it complains no connection factory can be found.

I know this request probably is no big difference from defining another bean in a Spring app but not sure with the current Spring-Data-Redis integration what's the best way for me to do. Please help, thanks.

Community
  • 1
  • 1
Derek
  • 1,085
  • 2
  • 20
  • 36

1 Answers1

13

you can follow two ways how to use multiple RedisTemplates within one Spring Boot application:

  1. Named bean injection with @Autowired @Qualifier("beanname") RedisTemplate myTemplate and create the bean with @Bean(name = "beanname").
  2. Type-safe injection by specifying type parameters on RedisTemplate (e.g. @Autowired RedisTemplate<byte[], byte[]> byteTemplate and @Autowired RedisTemplate<String, String> stringTemplate).

Here's the code to create two different:

@Configuration
public class Config {

    @Bean
    public RedisTemplate<String, String> stringTemplate(RedisConnectionFactory redisConnectionFactory) {

        RedisTemplate<String, String> stringTemplate = new RedisTemplate<>();
        stringTemplate.setConnectionFactory(redisConnectionFactory);
        stringTemplate.setDefaultSerializer(new StringRedisSerializer());

        return stringTemplate;
    }

    @Bean
    public RedisTemplate<byte[], byte[]> byteTemplate(RedisConnectionFactory redisConnectionFactory) {

        RedisTemplate<byte[], byte[]> byteTemplate = new RedisTemplate<>();
        byteTemplate.setConnectionFactory(redisConnectionFactory);

        return byteTemplate;
    }

}

HTH, Mark

mp911de
  • 17,546
  • 2
  • 55
  • 95
  • Thanks a lot, this solves my problem. A following up question is when I declare a bean like this, how Spring knows to pass in the desired RedisConnectionFactory for me? This is probably due to me still getting familiar with Spring mechanism, and appreciate it if you can educate me on that. – Derek Feb 22 '16 at 06:26
  • When there's only one connection factory, no worries. If there are multiple, you have to qualify them again, otherwise you'll end up with `NoUniqueBeanDefinitionException`. – mp911de Feb 22 '16 at 06:43
  • Excuse me why do you think you need .afterPropertiesSet invocation on a @Bean-created instance? Since it's a normal bean, I'd expect it to follow normal lifecycle which includes automatically called afterPropertiesSet. – Maksim Gumerov Apr 17 '22 at 07:42