spring-data-neo4j
spring-data-neo4j copied to clipboard
@CompositeProperty converter rejected when entity field uses parameterized generic type
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
IllegalArgumentExceptionabove. - 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 asLocalizedValue<String>.
Happy to provide a tiny reproducer repo if helpful.