Spring Data, MongoDB, and Java 8
Utilizing the latest Spring frameworks to convert Java 8 dates inside of MongoDB, simplifying a once difficult conversion task. Great concise NoSQL and Java tutorial.
Join the DZone community and get the full member experience.
Join For FreeWhile 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] org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.time.LocalDateTime] to type [java.util.Date]
We are testing:
- 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 and 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 register 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
Published at DZone with permission of Yong Mook Kim, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments