Setup custom converters in Spring Data Mongo

14,404

Solution 1

Did you annotate your MongoConfig class with @Configuration ?

Your class MongoConfig need to be managed by the Spring BeanFactory to get callback afterPropertiesSet()( where conversions.registerConvertersIn(conversionService) is originally called ) automatically called

If you don't annotate you configuration bean you need to call afterPropertiesSet() yourself

Solution 2

In Spring Boot 2.x it's as simple as creating a registration bean that registers all of your converters:

@Configuration
public class Converters {

  @Bean
  public MongoCustomConversions mongoCustomConversions() {

    return new MongoCustomConversions(
        Arrays.asList(
            new MyClassToBytesConverter(),
            new BytesToMyClassConverter()));
  }
}

Then create your converter classes:

@WritingConverter
public class MyClassToBytesConverter implements Converter<MyClass, Binary> {

  @Override
  public Binary convert(MyClasssource) {
  // your code
  }
}
@ReadingConverter
public class BytesToMyClassConverter implements Converter<Binary, MyClass> {

  @Override
  public MyClass convert(Binary source) {
  /// your code
  }
}

Solution 3

Nothing worked for me but this.

While setting up mongoTemplate we need to tell to mongo db use the custom conversion:

@Bean
public MongoTemplate mongoTemplate() throws Exception {
    MongoTemplate mongoTemplate = new MongoTemplate(mongo(), mongoDatabase);
    MappingMongoConverter conv = (MappingMongoConverter) mongoTemplate.getConverter();
    // tell mongodb to use the custom converters
    conv.setCustomConversions(customConversions()); 
    conv.afterPropertiesSet();
    return mongoTemplate;
}

Follow this link for more details:

Solution 4

It took me one hour to figure out in the LATEST VERSION of spring data mongo, org.bson.Document should be used instead of com.mongodb.BasicDBObject. Here is an example:

@Component
@WritingConverter
public class UserModelConverter implements Converter<UserModel, Document> {

    @Override
    public Document convert(UserModel s) {
        Document obj = new Document();
        obj.put("firstName", "FirstName");
        obj.put("lastName", "LastName");

        obj.remove("_class");

        return obj;
    }
}
Share:
14,404
Konstantin Fedorov
Author by

Konstantin Fedorov

Updated on July 21, 2022

Comments

  • Konstantin Fedorov
    Konstantin Fedorov almost 2 years

    We are trying to setup our own Converters for Spring Data Mongo and having problems with it.

    Seems like Spring never calls for registerConvertersIn on CustomConversions and thus our custom converters added through overriden AbstractMongoConfiguration#customConversions never become part of conversion.

    We are using Spring Data Mongo 1.6.3, but it seems it could be a problem for 1.8.0 too (I've checked calls to CustomConversions#registerConvertersIn and found none.)

    I was able to fix this problem by calling CustomConversions#registerConvertersIn in custom MappingMongoConverter like this:

    class MongoConfig extends AbstractMongoConfiguration {
        @Bean
        @Override
        public MappingMongoConverter mappingMongoConverter() throws Exception {
            DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
            MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext()) {
                @Override
                public void setCustomConversions(CustomConversions conversions) {
                    super.setCustomConversions(conversions);
                    conversions.registerConvertersIn(conversionService);
                }
    
            };
            converter.setCustomConversions(customConversions());
            return converter;
        }
    }
    

    Is that a bug or we are doing something wrong?

    Found another work around: https://stackoverflow.com/a/14369998/4567261

  • ystan-
    ystan- almost 4 years
    i spent more than an hour before finding your post. thanks for this. i don't understand why this isn't published more widely and why BasicDBObject is not backwards-compatible with a deprecated warning. Very poor upgrade experience.
  • caprica
    caprica over 2 years
    Agreed. Wasted so much time until I found this answer, every guide I found uses BasicDBObject.