Skip to content

@CompositeProperty converter rejected when entity field uses parameterized generic type #3035

@dpkass

Description

@dpkass

When an entity field is declared as a parameterized type (e.g. LocalizedValue<String>), a matching Neo4jPersistentPropertyToMapConverter<String, LocalizedValue<String>> is rejected with:

The property type [...].LocalizedValue<java.lang.String> created by [...].LocalizedValueMapConverter
used on name in [...].OrganizationUnit doesn't match the actual property type

If the converter is changed to use the raw type (LocalizedValue), it works.

Versions
• Spring Data Neo4j: 7.5.2
• Spring Data Commons: 3.5.2
• Spring Data REST: 4.5.2
• Spring Boot: 3.5.4
• Neo4j Java Driver: 5.28.9
• Java: 21

Minimal example

Domain value type

package com.example.localized;

public class LocalizedValue<T> {
  // internally holds Map<Locale,T>; getters omitted for brevity
}

Converter (fails)

public class LocalizedValueMapConverter
    implements Neo4jPersistentPropertyToMapConverter<String, LocalizedValue<String>> {

  @Override public Map<String, Value> decompose(LocalizedValue<String> lv, Neo4jConversionService cs) { ... }
  @Override public LocalizedValue<String> compose(Map<String, Value> src, Neo4jConversionService cs) { ... }
}

Entity

@Node
public class OrganizationUnit {
  @Id @GeneratedValue Long id;

  @CompositeProperty(converter = LocalizedValueMapConverter.class, prefix = "name")
  private LocalizedValue<String> name;

  // getters/setters use the same parameterized type
}

Observed

  • Throws IllegalArgumentException above.
  • Neo4jMappingContext appears to resolve the property type as raw LocalizedValue, so the parameterized converter is considered a mismatch.
  • I tried a Converter with Neo4jPersistentPropertyToMapConverter<String, LocalizedValue<T>> aswell, same issue.

Workarounds

• Make the converter raw:

class LocalizedValueMapConverter
    implements Neo4jPersistentPropertyToMapConverter<String, LocalizedValue> { ... }

(Works, but loses compile-time type safety.)

Expected

  • A converter targeting LocalizedValue<String> should match a field declared as LocalizedValue<String>.

Happy to provide a tiny reproducer repo if helpful.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions