J'essaie d'utiliser un convertisseur personnalisé avec spring-data-mongodb. Je veux le créer par programme, mais j'obtiens l'erreur suivante:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type org.joda.time.LocalDate to type Java.lang.String
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.Java:475)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.Java:175)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.Java:154)
....
....
Voici l'extrait de code défaillant:
Mongo mongo = new Mongo();
MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo, "database");
List<Converter> converters = new ArrayList<>();
converters.add(new LocalDateWriteConverter());
converters.add(new LocalDateReadConverter());
CustomConversions customConversions = new CustomConversions(converters);
MappingContext mappingContext = new SimpleMongoMappingContext();
MappingMongoConverter mappingMongoConverter = new MappingMongoConverter(mongoDbFactory, mappingContext);
mappingMongoConverter.setCustomConversions(customConversions);
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, mappingMongoConverter);
MongoDbEvent mongoEvent = new MongoDbEvent(new LocalDate(2012, 12, 8));
mongoTemplate.insert(mongoEvent);
Et voici mes classes de conversion:
class LocalDateReadConverter implements Converter<String, LocalDate> {
@Override
public LocalDate convert(String s) {
// Conversion code omitted.
}
}
class LocalDateWriteConverter implements Converter<LocalDate, String> {
@Override
public String convert(LocalDate localDate) {
// Conversion code omitted.
}
}
La classe que j'essaie de persister ressemble à ceci:
import org.joda.time.LocalDate;
public class MongoDbEvent {
private String id;
private LocalDate date;
public MongoDbEvent(LocalDate date) {
this.date = date;
}
public String getId() {
return id;
}
public LocalDate getDate() {
return date;
}
@Override
public String toString() {
return "MongoDbEvent{" +
"id='" + id + '\'' +
", date=" + date +
'}';
}
}
Cette réponse est peut-être un peu en retard pour l'OP, mais je viens de rencontrer le même problème aujourd'hui et j'ai trouvé une solution ...
Pour le configurer par programme, vous devez appeler MongoMappingConverter.afterPropertiesSet()
avant de l'utiliser. Je l'ai réalisé en lisant le code de MongoTemplate.getDefaultMongoConverter(MongoDbFactory)
.
Voici un exemple:
MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory, context);
converter.setTypeMapper(mapper);
converter.setCustomConversions(new CustomConversions(
Arrays.asList(
new TimeZoneReadConverter(),
new TimeZoneWriteConverter()
)
));
converter.afterPropertiesSet();
MongoTemplate template = new MongoTemplate(mongoDbFactory, converter);
Juste un avertissement. Je me débattais avec ce problème le spring-data-mongodb 1.5.1.RELEASE
using Java Configuration. Comme certaines classes ont changé, je poste ma solution.
Ajoutez la définition suivante dans votre classe de configuration annotée de @Configuration
:
@Bean
public Mongo mongo() throws Exception {
MongoPropertiesResolver resolver = mongoResolver();
return new MongoClient(resolver.getUrl());
}
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new SimpleMongoDbFactory(mongo(), "database");
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mongoConverter());
}
@Bean
public CustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(new TimeZoneReadConverter());
converters.add(new TimeZoneReadConverter());
return new CustomConversions(converters);
}
@Bean
public MappingMongoConverter mongoConverter() throws Exception {
MongoMappingContext mappingContext = new MongoMappingContext();
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
mongoConverter.setCustomConversions(customConversions());
return mongoConverter;
}
Comment personnaliser mongo avec des convertisseurs personnalisés est décrit ici en détail:
http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping-configuration
J'ai injecté les valeurs de configuration par défaut afin que je puisse bénéficier des paramètres de configuration application.properties.
@Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {
@Value("${spring.data.mongodb.database:test}")
String database;
@Value("${spring.data.mongodb.Host:localhost}:${spring.data.mongodb.port:27017}")
String Host;
@Override
protected String getDatabaseName() {
return database;
}
@Override
public Mongo mongo() throws Exception {
return new MongoClient(Host);
}
@Bean
@Override
public CustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
converterList.add(new MongoColorWriter());
converterList.add(new MongoColorReader());
return new CustomConversions(converterList);
}
}
Avec l'introduction du package Java.time dans Java 8, j'ai rencontré un problème similaire en utilisant les nouvelles classes LocalDate et LocalDateTime dans le nouveau package. Voici comment je l'ai résolu:
J'ai écrit un convertisseur pour les 4 de ces options de conversion:
Voici un exemple
public class DateToLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
@Override
public LocalDateTime convert(Date source) {
return source == null ? null : LocalDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
}
}
Ensuite, en incluant cela dans la configuration xml pour la connexion mongodb, j'ai pu travailler dans Java 8 dates avec mongodb (n'oubliez pas d'ajouter tous les convertisseurs):
<mongo:mapping-converter>
<mongo:custom-converters>
<mongo:converter>
<bean class="package.DateToLocalDateTimeConverter" />
</mongo:converter>
</mongo:custom-converters>
</mongo:mapping-converter>
Pour moi, il s'agissait d'enregistrer mon convertisseur en tant que lecteur au lieu d'écrivain. Pour résoudre ce problème, vous devez ajouter l'annotation @WritingConverter à votre classe de convertisseur
@Component
@WritingConverter
public class NoteWriterConverter implements Converter<Note, DBObject> {
@Override
public DBObject convert(Note source) {
DBObject obj = new BasicDBObject();
obj.put("title", source.getTitle());
obj.put("reviewDate", source.getReviewDate());
obj.removeField("_class");
return obj;
}
}
Puisque org.springframework.data:spring-data-commons:1.13.3.RELEASE
, voici comment créer par programmation un MongoTemplate
avec des convertisseurs personnalisés
public MongoTemplate mongoTemplate(String mongoUri) throws Exception {
MongoDbFactory factory = new SimpleMongoDbFactory(new MongoClientURI(mongoUri));
CustomConversions conversions = new CustomConversions(
Arrays.asList(new FooWriteConverter(), new FooReadConverter()));
MongoMappingContext mappingContext = new MongoMappingContext();
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);
mongoConverter.setCustomConversions(conversions);
mongoConverter.afterPropertiesSet();
return new MongoTemplate(factory, mongoConverter);
}
Les convertisseurs (implémentation omise)
class FooWriteConverter implements Converter<Foo, DBObject> { ... }
class FooReadConverter implements Converter<DBObject, Foo> { ... }