Skip to content

[Bug Report] TypeResolver create a new ObjectMapper instance, ignoring custom configurations #3101

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

Closed
swtalk opened this issue Feb 7, 2025 · 1 comment
Assignees
Labels
status: superseded An issue that has been superseded by another

Comments

@swtalk
Copy link

swtalk commented Feb 7, 2025

📌 Summary

  • GenericJackson2JsonRedisSerializer.TypeResolver currently creates a new ObjectMapper instead of using an existing one.
  • This leads to issues where users cannot apply custom configurations like StreamReadConstraints for handling large JSON strings.
  • Even when explicitly setting ObjectMapper with maxStringLength = 100MB, the TypeResolver still enforces a 20MB limit, causing deserialization failures.

🔍 Steps to Reproduce

  1. Configure a custom ObjectMapper with StreamReadConstraints.maxStringLength = 100MB
  2. Use GenericJackson2JsonRedisSerializer for Redis serialization
  3. Store a large JSON object (e.g., 50MB) in Redis
  4. Attempt to retrieve the JSON using RedisTemplate or @Cacheable
  5. Observe that TypeResolver creates a new ObjectMapper, which applies a 20MB limit, leading to:
    Could not read JSON:String value length (20054016) exceeds the maximum allowed (20000000, from `StreamReadConstraints.getMaxStringLength()`)
    

🚀 Expected Behavior

  • TypeResolver should use the configured ObjectMapper instead of creating a new one internally.
  • Custom StreamReadConstraints.maxStringLength = 100MB should be respected when deserializing Redis data.

🛠 Suggested Fix

  • Modify TypeResolver to accept an ObjectMapper instance as a constructor argument.
  • If null, it should fall back to a default instance.

📎 Relevant Code (Current Issue)

static class TypeResolver {
    private final ObjectMapper mapper = new ObjectMapper(); // ⚠️ Always creates a new ObjectMapper
    private final Supplier<TypeFactory> typeFactory;
    private final Supplier<String> hintName;

    TypeResolver(Supplier<TypeFactory> typeFactory, Supplier<String> hintName) {
        this.typeFactory = typeFactory;
        this.hintName = hintName;
    }

    protected JavaType resolveType(byte[] source, Class<?> type) throws IOException {
        JsonNode root = mapper.readTree(source);
        JsonNode jsonNode = root.get(hintName.get());

        if (jsonNode instanceof TextNode && jsonNode.asText() != null) {
            return typeFactory.get().constructFromCanonical(jsonNode.asText());
        }
        return constructType(type);
    }
}

✅ Suggested Fix

private final ObjectMapper mapper;

TypeResolver(Supplier<TypeFactory> typeFactory, Supplier<String> hintName, ObjectMapper objectMapper) {
    this.typeFactory = typeFactory;
    this.hintName = hintName;
    this.mapper = (objectMapper != null) ? objectMapper : new ObjectMapper();
}

🌍 Environment

  • Spring Boot: 3.3.6
  • Jackson: 2.17.3
  • Spring Data Redis: Latest

📢 Additional Context

This issue causes Redis deserialization failures when handling large JSON payloads. Users configuring a custom ObjectMapper expect their settings to be respected, but TypeResolver currently overrides them by always creating a new instance. Fixing this will ensure better configurability and prevent unexpected SerializationException errors.


@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 7, 2025
@mp911de mp911de self-assigned this Feb 10, 2025
@mp911de
Copy link
Member

mp911de commented Feb 10, 2025

Care to upgrade to Spring Data Redis 3.4 or newer? We propagate a configured ObjectMapper instead of creating a new one (see #2981).

@mp911de mp911de closed this as not planned Won't fix, can't repro, duplicate, stale Feb 10, 2025
@mp911de mp911de added status: superseded An issue that has been superseded by another and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded An issue that has been superseded by another
Projects
None yet
Development

No branches or pull requests

3 participants