Spring Data MongoDB + JSR-310 or Java 8 new Date APIs

While saving an object containing the new Java 8 java.time.LocalDateTime, the following error is thrown :

org.springframework.core.convert.ConverterNotFoundException: 
	No converter found capable of converting 
               from type [java.time.LocalDateTime] to type [java.util.Date]

Tested

  1. Spring 4.3.2.RELEASE
  2. Spring Data MongoDB 1.9.2.RELEASE

Is Spring-data supporting the new Java 8 Date APIs (JSR-310)?

1. Spring Data + JSR-310

Yes, Spring-data supports the JSR-310 spec, with a custom convertor – Jsr310Converters, review the following code snippet :CustomConversions.java

package org.springframework.data.mongodb.core.convert;

public class CustomConversions {

 /**
  * Creates a new {@link CustomConversions} instance registering the given converters.
  * 
  * @param converters
  */
 public CustomConversions(List<?> converters) {

 //...
 List<Object> toRegister = new ArrayList<Object>();

 // Add user provided converters to make sure they can override the defaults
 toRegister.addAll(converters);
 toRegister.add(CustomToStringConverter.INSTANCE);
 toRegister.addAll(MongoConverters.getConvertersToRegister());
 toRegister.addAll(JodaTimeConverters.getConvertersToRegister());
 toRegister.addAll(GeoConverters.getConvertersToRegister());
 toRegister.addAll(Jsr310Converters.getConvertersToRegister());
 toRegister.addAll(ThreeTenBackPortConverters.getConvertersToRegister());

 for (Object c : toRegister) {
 registerConversion(c);
 }

 //...
 }

2. Solution

The above Jsr310Converters will be enabled if you declared a Spring managed bean for MappingMongoConverter, and pass as an argument for MongoTemplate, review the following MongoConfig example :MongoConfig.java

//...
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;

@Configuration
@ComponentScan(basePackages = {"com.mkyong.db"})
public class MongoConfig {

    //...
 @Autowired
 MongoDbFactory mongoDbFactory;
 
    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, getDefaultMongoConverter());
        return mongoTemplate;

    }

    @Bean
    public MappingMongoConverter getDefaultMongoConverter() throws Exception {

        MappingMongoConverter converter = new MappingMongoConverter(
                new DefaultDbRefResolver(mongoDbFactory), new MongoMappingContext());

        return converter;
    }

    //...

}

The MappingMongoConverter extends AbstractMongoConverter, and the AbstractMongoConverter is an InitializingBean. If this declared as a Spring managed bean via @Bean, the afterPropertiesSet() will be fired, and registered all the default convertors, including the Jsr310Converters

3. FAQs

If the MappingMongoConverter is not managed by Spring (init with a new keyword like below), you must call the .afterPropertiesSet() manually.MongoConfig.java

@Configuration
@ComponentScan(basePackages = {"com.mkyong.db"})
public class MongoConfig {

    @Autowired
    MongoDbFactory mongoDbFactory;

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        MappingMongoConverter converter = new MappingMongoConverter(
 new DefaultDbRefResolver(mongoDbFactory), new MongoMappingContext());

     //CALL THIS MANULLY, so that all the default convertors will be registered! 
 converter.afterPropertiesSet();

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);

        return mongoTemplate;

    }

 //...

References

  1. Github – Custom converters to spring-data-mongodb
  2. Spring IO – MappingMongoConverter JavaDoc
  3. Spring IO – CustomConversions JavaDoc
1 reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *