Skip to content

Object serialization as HashValue with StreamOperations [DATAREDIS-993] #1564

@spring-projects-issues

Description

@spring-projects-issues

Romain Beghi opened DATAREDIS-993 and commented

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.  


Affects: 2.2 M4 (Moore)

Referenced from: pull request #455, and commits f77eccb, 548d8e7

Metadata

Metadata

Assignees

Labels

in: coreIssues in core supporttype: bugA general bug

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions