Answer a question

I have a Java class having an Instant type of member variable:

public class SomeRecord {
    private String someId;

    private Instant someInstant;

    // getters and setters
}

I am using MongoTemplate to update the someInstant field in database:

public SomeRecord updateSomeRecordBySomeId(final String someId, Object someInstant) {
        Query query = new Query();
        query.addCriteria(Criteria.where("someId").is(someId));

        Update update = new Update();
        update.set("someInstant", someInstant);

        return operations.findAndModify(query, update, new FindAndModifyOptions().returnNew(true), SomeRecord.class);
}

This works great if I am calling the method as:

updateSomeRecordBySomeId("SOME-ID", Instant.now()); persisting the field in DB as a Date type: "someInstant" : ISODate("2017-07-11T07:26:44.269Z")


Now the method may also be called as: updateSomeRecordBySomeId("SOME-ID", "2017-07-11T07:26:44.269Z");

In this case I get an exception as:

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.time.Instant]

which makes complete sense. (It updates the field in the DB as String though. "someInstant" : "2017-07-11T07:26:44.269Z")


So I added a converter as follows:

MongoConfig.java:

@Configuration
@ComponentScan(basePackages = {"dao package path here"})
public class MongoConfig {
    @Autowired
    private MongoDbFactory mongoDbFactory;

    @Bean
    public MongoTemplate mongoTemplate() {
        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory),
                new MongoMappingContext());

        converter.setCustomConversions(new CustomConversions(Collections.singletonList(new StringToInstantConverter())));

        return new MongoTemplate(mongoDbFactory, converter);
    }
}

StringToInstantConverter.java:

public class StringToInstantConverter implements Converter<String, Instant> {
    @Override
    public Instant convert(String utcString) {
        // TODO: Make it generic for any time-zone
        return Instant.parse(utcString);
    }
}

After adding the above converter I am not getting ConverterNotFoundException any longer, but the field someInstant is being persisted as plain string: "someInstant" : "2017-07-11T07:26:44.269Z"

And that's what my question is. I know that the converter is being identified that is the reason I am not getting the exception anymore. But why the converter is not converting the String to Instant? Why the field is being persisted as plain String? Is the converter supplied incorrect? How to write converter for this case?

Note:

  • I have simplified the code to focus on the actual problem. In actual the method does not receive the someInstant field as parameter. So writing overloaded method is not going to be applicable here. Also any kind of instanceOf check inside the method won't work for the actual scenario. So the focus is on the question why the conversion not happening?

  • The actual data-store for us is DocumentDB, but we use DocumentDB with MongoDB API(as Spring Data does not support DocumentDB) for our database operations.

Answers

Your update logic is written in type agnostic way: you can pass any object type (Integer, Long, Boolean, String, Date, etc.) and it will be persisted in DB by overriding the existing value/type with new value and new type. Note: document oriented databased like MongoDB have no fixed schema, so stored data can arbitrary change data types.

The issue you had before you introduced converter with ConverterNotFoundException was not during update action, but during retrieval of updated object and setting it into your Java bean model: Java class defined someInstant property to be of an Instant / Date type, but database supplied a String value.

After you introduced a converter the issue of reading was solved, but only for String and Date types. If you update the someInstant property with some boolean value, you'll get back to the issue to read the object and map it to you Java bean.

Logo

MongoDB社区为您提供最前沿的新闻资讯和知识内容

更多推荐