Skip to content

Fixes #3179 – Restore _class metadata for collections in MappingRedisConverter #3188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

xyraclius
Copy link

Overview

This PR resolves a regression in Redis Stream serialization introduced in spring-data-redis 4.0.0-SNAPSHOT, where the _class metadata is no longer written when serializing collections. As a result, deserialization fails with:

java.lang.IllegalArgumentException: Value must not be null

The issue is tracked in GitHub issue #3179.


The Problem

In Spring Data Redis 3.5.1, when using ReactiveRedisTemplate to write and read a collection into a Redis Stream, the MappingRedisConverter correctly writes the _class metadata using the configured typeMapper. This metadata allows the deserializer to reconstruct the correct types during a read operation.

In 4.0.0-SNAPSHOT, an optimization for Collection types bypasses the call to typeMapper.writeType(...), resulting in the _class field being omitted. This omission breaks deserialization compatibility with existing data and behavior.


The Solution

To restore the previous behavior while preserving the new optimization, this PR adds the following line:

typeMapper.writeType(ClassUtils.getUserClass(source), sink.getBucket().getPath());

Before:

if (source instanceof Collection collection) {
    writeCollection(sink.getKeyspace(), "", collection, TypeInformation.of(Object.class), sink);
    return;
} 

After:

if (source instanceof Collection collection) {
    typeMapper.writeType(ClassUtils.getUserClass(source), sink.getBucket().getPath());
    writeCollection(sink.getKeyspace(), "", collection, TypeInformation.of(Object.class), sink);
    return;
}

This ensures _class metadata is written for collection values in Redis Streams, restoring compatibility with existing deserialization logic.

Test Coverage

This fix is already verified by the existing test case:

@Test // GH-2168, GH-3179
void writePlainList() { ... }

This test verifies that _class metadata is written when serializing collections.
It fails without the fix and passes once the metadata is correctly applied.


Related Issue


  • I have read the Spring Data contribution guidelines
  • I used the provided formatters and avoided submitting unrelated formatting changes
  • This fix is verified by an existing test case
  • I included a Signed-off-by trailer in the commit
  • I added myself as the author in the modified class header (if applicable)

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 24, 2025
…ections in MappingRedisConverter

Signed-off-by: Nabil Fawwaz Elqayyim <[email protected]>
@christophstrobl
Copy link
Member

christophstrobl commented Jul 31, 2025

Thank you @xyraclius for looking into this.

The type mapper unfortunately will try to create a persistent entity during the type lookup for the user type. This leads to InaccessibleObjectException when trying to resolve the persistence constructor. So I think we also need to make sure we do not create an entity for collection like types in first place within the RedisMappingContext.

We also might not need to preserve the user type in that detail. _class : java.util.List might be sufficient instead of having _class : java.util.Arrays$ArrayList. Since the read operation will create an ArrayList regardless of the actual type hint, leveraging CollectionFactory.createCollection sounds like the way to go there to get closer to the actual source type.

@christophstrobl christophstrobl self-assigned this Jul 31, 2025
@christophstrobl christophstrobl added status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-feedback We need additional information before we can continue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Regression in latest Redis Stream serialization (or deserialization)
3 participants