Uploaded image for project: 'Spring Data Redis'
  1. Spring Data Redis
  2. DATAREDIS-993

Object serialization as HashValue with StreamOperations

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.2 M4 (Moore)
    • Fix Version/s: 2.2 RC2 (Moore)
    • Component/s: Core
    • Labels:
      None

      Description

      Given a ReactiveStreamOperations<String, String, DummyObject>, configured that way : 

      @Bean
      public ReactiveStreamOperations<String, String, DummyObject> createReactiveStreamOperationsForDummyObject(final ReactiveRedisConnectionFactory factory) {
        final StringRedisSerializer stringRedisSerializer = StringRedisSerializer.UTF_8;
        final Jackson2JsonRedisSerializer<DummyObject> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(DummyObject.class);
      
        final RedisSerializationContext.RedisSerializationContextBuilder<String, DummyObject> contextBuilder = RedisSerializationContext.newSerializationContext(stringRedisSerializer);
        final RedisSerializationContext<String, DummyObject> context = contextBuilder.hashValue(jsonRedisSerializer).build();
      
        return new ReactiveRedisTemplate<>(factory, context).opsForStream();
      }
      

       

      Record serialization is done here : DefaultReactiveStreamOperations.serializeRecordFields

      And calls DefaultReactiveStreamOperations.rawHashKey and DefaultReactiveStreamOperations.rawValue

      Where HashKey and HashValue distinct serializers are properly called.

       

       

       

      However, with a StreamOperations<String, String, DummyObject>, configured that way :

      @Bean
      public StreamOperations<String, String, DummyObject> createStreamOperationsForDummyObject(final RedisConnectionFactory factory) {
        final StringRedisSerializer stringSerializer = StringRedisSerializer.UTF_8;
        final Jackson2JsonRedisSerializer<DummyObject> jsonSerializer = new Jackson2JsonRedisSerializer<>(DummyObject.class);
      
        final RedisTemplate<String, DummyObject> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setDefaultSerializer(stringSerializer);
        template.setHashValueSerializer(jsonSerializer);
        template.afterPropertiesSet();
      
        return template.opsForStream();
      }

      Serialization fails and return 

      java.lang.ClassCastException: com.dummy.model.DummyObject cannot be cast to [B
      org.springframework.data.redis.connection.stream.StreamSerialization.serialize(StreamSerialization.java:39)
      

      Record serialization is done here :
      MapRecord.serialize

      And use fieldSerializer for both HashKey and HashValue serialization, even if its input parameters are streamSerializer, fieldSerializer and valueSerializer.

      Such usage is done here :
      DefaultStreamOperations.add

      The fix only consists to use valueSerializer for HashValue serialization rather than fieldSerializer.

       

      I'm linking to this ticket a short (and improvable) PR for this issue.  

        Attachments

          Activity

            People

            • Assignee:
              mp911de Mark Paluch
              Reporter:
              RBSpring Romain Beghi
              Last updater:
              Mark Paluch
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: