spring-data-redis icon indicating copy to clipboard operation
spring-data-redis copied to clipboard

Custom HashValueSerializer for RedisTemplate in redis stream happend ConversionFailedException!

Open sccassiel opened this issue 2 years ago • 4 comments

in my configclass,code show as below

@Bean
public GenericJackson2JsonRedisSerializer jsonRedisSerializer(
        Jackson2ObjectMapperBuilder objectMapperBuilder) {
    var objectMapper = objectMapperBuilder.build();
    GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
    objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
            ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    return new GenericJackson2JsonRedisSerializer(objectMapper);
}

@Bean
public RedisTemplate<String, Object> redisTemplate(
        RedisConnectionFactory redisConnectionFactory,
        GenericJackson2JsonRedisSerializer jsonRedisSerializer) {
    var template = new RedisTemplate<String, Object>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(RedisSerializer.string());
    template.setValueSerializer(jsonRedisSerializer);
    template.setHashKeySerializer(RedisSerializer.string());
    template.setHashValueSerializer(jsonRedisSerializer);
    return template;
}



public class ConsumerListener implements StreamListener<String, ObjectRecord<String, ModelMessageBO>> {
    private String group;
    private String topic;
    private RedisTemplate<String, Object> redisTemplate;
    private AbstractModelMessageHandler modelMessageHandler;
    public ModelJobConsumerListener(String topic, String group, RedisTemplate<String, Object> redisTemplate, AbstractModelMessageHandler modelMessageHandler) {
        this.topic = topic;
        this.group = group;
        this.redisTemplate = redisTemplate;
        this.modelMessageHandler = modelMessageHandler;
    }


  @Override
  public void onMessage(ObjectRecord message) {
     Object value=message.getValue();
  }

}

If i use template.setHashValueSerializer(jsonRedisSerializer),an ConversionFailedException occurs. But i use template.setHashValueSerializer(RedisSerializer.string()) ,it working normally. Is it a bug🐛? Thank you.

sccassiel avatar Aug 26 '22 10:08 sccassiel

Please provide a Minimimal Reproducable Example, preferable as a Github repository.

schauder avatar Aug 29 '22 14:08 schauder

Please provide a Minimimal Reproducable Example, preferable as a Github repository.

you can run demo: https://github.com/sccassiel/demo ,please!

sccassiel avatar Aug 30 '22 15:08 sccassiel

Hash- and stream serializers are used to serialize keys and values into Map-like structures. With Redis Streams, objects are decomposed into properties and the actual property values get serialized with the serializer. Converting a String into JSON doesn't make really sense as the result doesn't represent the intention.

127.0.0.1:6379> xrange stream-key - +
1) 1) "1666094363234-0"
   2) 1) "_class"
      2) "\"Y29tLmV4YW1wbGUuZGVtby5iby5NZXNzYWdlQk8=\""
      3) "id"
      4) "\"MQ==\""
      5) "message"
      6) "\"dGVzdCBtZXNzYWdl\""

mp911de avatar Oct 18 '22 12:10 mp911de

It is a bit unfortunate that Jackson renders byte arrays as Base64, and we cannot read those back in. I'll take this item to the team to see whether we can improve.

mp911de avatar Oct 18 '22 12:10 mp911de