Spring-session: Setting default serializer does not override template default serializer for redis

Created on 13 Dec 2016  路  4Comments  路  Source: spring-projects/spring-session

It requires explicit template creation as showed below:

RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(connectionFactory());
template.setDefaultSerializer(new CustomRedisSerializer());
template.afterPropertiesSet();

RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(template);
repository.setDefaultSerializer(new CustomRedisSerializer());

As you can see I wan't to override only default serializer. It would be great to be able to do:

 RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(connectionFactory());
 repository.setDefaultSerializer(new CustomRedisSerializer());
stack-overflow

Most helpful comment

@glapa sorry for the late follow up on this.

You shouldn't need to manually register RedisOperationsSessionRepository @Bean to achieve your desired setup. As suggested in the previous comment, please take a look at RedisHttpSessionConfiguration#defaultRedisSerializer and its usages.

You should reduce your configuration to something like this (based on your example):

@Configuration
@EnableRedisHttpSession
public class Redis {
     private final Environment env;

    @Autowired
    public Redis(Environment env) {
        this.env = env;
    }

    @Bean
    JedisConnectionFactory connectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(env.getProperty("redis.hostName", "localhost"));
        factory.setPort(Integer.parseInt(env.getProperty("redis.port", "1234")));
        factory.setUsePool(true);
        return factory;
    }

    @Bean
     RedisTemplate<String, Object> redisTemplate() {
        final RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericToStringSerializer<>( Object.class ));
        template.setValueSerializer(new GenericToStringSerializer<>( Object.class ));
        return template;
    }

    @Bean
    RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new CustomRedisSerializer();
    }
}

This will ensure that your CustomRedisSerializer @Bean named springSessionDefaultRedisSerializer will be configured both with Spring Sessions RedisTemplate (see here) and RedisOperationsSessionRepository's MessageListener implementation that handles session events (see here).

All 4 comments

If you use @EnableRedisHttpSession you need to register RedisSerializer<Object> @Bean named springSessionDefaultRedisSerializer, and it will get auto-configured with both RedisTemplate and RedisOperationsSessionRepository.

See RedisHttpSessionConfiguration#defaultRedisSerializer and its usages.

I do override it. My whole config file:

@Configuration
@EnableRedisHttpSession
public class Redis {
     private final Environment env;

    @Autowired
    public Redis(Environment env) {
        this.env = env;
    }

    @Bean
    JedisConnectionFactory connectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(env.getProperty("redis.hostName", "localhost"));
        factory.setPort(Integer.parseInt(env.getProperty("redis.port", "1234")));
        factory.setUsePool(true);
        return factory;
    }

    @Bean
    RedisOperationsSessionRepository sessionRepository() {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setConnectionFactory(connectionFactory());
        template.setDefaultSerializer(new CustomRedisSerializer());
        template.afterPropertiesSet();

        RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(template);
        repository.setDefaultSerializer(new CustomRedisSerializer());
        return repository;
    }

    @Bean
     RedisTemplate<String, Object> redisTemplate() {
        final RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericToStringSerializer<>( Object.class ));
        template.setValueSerializer(new GenericToStringSerializer<>( Object.class ));
        return template;
    }

    @Bean
    RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new CustomRedisSerializer();
    }
}

@glapa sorry for the late follow up on this.

You shouldn't need to manually register RedisOperationsSessionRepository @Bean to achieve your desired setup. As suggested in the previous comment, please take a look at RedisHttpSessionConfiguration#defaultRedisSerializer and its usages.

You should reduce your configuration to something like this (based on your example):

@Configuration
@EnableRedisHttpSession
public class Redis {
     private final Environment env;

    @Autowired
    public Redis(Environment env) {
        this.env = env;
    }

    @Bean
    JedisConnectionFactory connectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(env.getProperty("redis.hostName", "localhost"));
        factory.setPort(Integer.parseInt(env.getProperty("redis.port", "1234")));
        factory.setUsePool(true);
        return factory;
    }

    @Bean
     RedisTemplate<String, Object> redisTemplate() {
        final RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericToStringSerializer<>( Object.class ));
        template.setValueSerializer(new GenericToStringSerializer<>( Object.class ));
        return template;
    }

    @Bean
    RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new CustomRedisSerializer();
    }
}

This will ensure that your CustomRedisSerializer @Bean named springSessionDefaultRedisSerializer will be configured both with Spring Sessions RedisTemplate (see here) and RedisOperationsSessionRepository's MessageListener implementation that handles session events (see here).

Closing as answered. If you have additional questions or feel that your original question isn't properly answered, please re-open the issue.

Was this page helpful?
0 / 5 - 0 ratings