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
- Spring 4.3.2.RELEASE
- 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
- Github – Custom converters to spring-data-mongodb
- Spring IO – MappingMongoConverter JavaDoc
- Spring IO – CustomConversions JavaDoc