Skip to content

Missing field and property annotations do not allow conditional conversion [DATAMONGO-889] #1815

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
spring-projects-issues opened this issue Mar 21, 2014 · 1 comment
Assignees
Labels
in: mapping Mapping and conversion infrastructure type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link

Emerson Farrugia opened DATAMONGO-889 and commented

This StackOverflow question got me curious about how to control conversion logic using an annotation.

I started digging around ConversionService and MappingMongoConverter code looking for a solution. I eventually landed on ConditionalGenericConverter, which I thought would let me solve conditional conversion using an annotation. The code to convert a Long to a Date based on a @Foo annotation would have looked like this...

public class ConditionalLongToDateConverter implements ConditionalGenericConverter {

    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {

        return sourceType.hasAnnotation(Foo.class);
    }

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(Long.class, Date.class));
    }

    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

        if (source == null) {
            return null;
        }

        return new Date((Long) source);
    }
}

which would have allowed the persistence of a POJO that looked like

public class MyDocument {
   @Id
   private String id;

   @Foo
   private Long timestamp; // gets persisted as a JS Date
}

I assumed the sourceType TypeDescriptor for property timestamp would contain the @Foo annotation, because of this constructor:

/**
 * Create a new type descriptor from a {@link Property}.
 * <p>Use this constructor when a source or target conversion point is a
 * property on a Java class.
 * @param property the property
 */
public TypeDescriptor(Property property) {
     Assert.notNull(property, "Property must not be null");
     this.resolvableType = ResolvableType.forMethodParameter(property.getMethodParameter());
     this.type = this.resolvableType.resolve(property.getType());
     this.annotations = nullSafeAnnotations(property.getAnnotations());
}

I registered the converter using CustomConversions from an AbstractMongoConfiguration subclass and thought I was done. But it all broke.

The problem is that MappingMongoConverter never really gets its hands on a TypeDescriptor for the properties to convert, and calls the GenericConversionService in a way that effectively discards the metadata of those properties. This happens specifically in getPotentiallyConvertedSimpleWrite(), but the code higher up the call stack doesn't help because it doesn't give that method TypeDescriptor arguments to work with either.

Is this intentional? I don't know how rare this use case is, but it seems like there's a lot of capability in Spring Core's conversion code that could be exposed to support smarter conversion if TypeDescriptors are propagated better


Affects: 1.4.1 (Codd SR1)

Issue Links:

4 votes, 5 watchers

@spring-projects-issues spring-projects-issues added type: enhancement A general enhancement in: mapping Mapping and conversion infrastructure labels Dec 30, 2020
@christophstrobl
Copy link
Member

resolved by #3596

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: mapping Mapping and conversion infrastructure type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants