23

How could I customize the MappingMongoConverter within my Spring-Boot-Application (1.3.2.RELEASE) without changing any of the mongo-stuff which is autoconfigured by spring-data?

My current solution is:

@Configuration
public class MongoConfig {

  @Autowired
  private MongoDbFactory mongoFactory;

  @Autowired
  private MongoMappingContext mongoMappingContext;

  @Bean
  public MappingMongoConverter mongoConverter() throws Exception {
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoFactory);
    MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
    //this is my customization
    mongoConverter.setMapKeyDotReplacement("_");
    mongoConverter.afterPropertiesSet();
    return mongoConverter;
  }
}

Is this the right way or do I break some stuff with this?
Or is there even a more simple way to set the mapKeyDotReplacement?

Mike Boddin
  • 1,241
  • 2
  • 12
  • 22

4 Answers4

13

That's the right way to do it. The auto-configured MappingMongoConverter is annotated with @ConditionalOnMissingBean(MongoConverter.class), so adding your own MappingMongoConverter bean will cause the auto-configuration to back off in favour of your custom converter.

One minor correction: there's no need for you to call mongoConverter.afterPropertiesSet(). The container will call that for you.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
13

Also there's shorter version:

@Autowired
void setMapKeyDotReplacement(MappingMongoConverter mappingMongoConverter) {
    mappingMongoConverter.setMapKeyDotReplacement("_");
}

Remember to put it into class that Spring will be aware of - e.g. class annotated with @Configuration

ZZ 5
  • 1,744
  • 26
  • 41
  • Thank you, it worked. needs to look into MappingMongoConverter – Lakshman Miani Mar 21 '19 at 10:24
  • Genuinely didn't know you could autowire methods with Beans as parameters. Crazy! Also, it worked! – David May 09 '23 at 06:18
  • I tried this solution today and it worked perfectly. Fixed the exception I was getting and did so in a super elegant way. Thank you a lot for this – Pmsmm Aug 26 '23 at 00:02
11

I have run into this issue in the latest version of spring boot. Your approach did not work for me or the accepted answer...my boot app seemed to ignore my custom mapping converter.

So what I did in the config class I autowired in the MappingMongoConverter that boot uses and then set the setMapKeyDotReplacement on that.

@Autowired
private MappingMongoConverter mongoConverter;

// Converts . into a mongo friendly char
@PostConstruct
public void setUpMongoEscapeCharacterConversion() {
    mongoConverter.setMapKeyDotReplacement("_");
}
David Billings
  • 366
  • 2
  • 9
  • 1
    There's no need for null check as you haven't specified dependency (`mongoConverter`) as optional – LoganMzz Sep 26 '17 at 11:57
  • 1
    For me solution started working after re-naming method to ``mappingMongoConverter``, because I am extending ``AbstractMongoConfiguration`` – heroin May 17 '18 at 11:03
0

We can use the default mapping converter inside the Mongo template and change what we need

/**
 * <p>
 * Gets default mapping converted that can be overiden based on the need.
 * This is the default mapping used inside mongo template when no custom converter is passed
 * </p>
 * @param factory
 * @return
 */
private static MongoConverter getDefaultMongoConverter(MongoDbFactory factory) {
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
    MongoCustomConversions conversions = new MongoCustomConversions(Collections.emptyList());
    MongoMappingContext mappingContext = new MongoMappingContext();
    mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
    mappingContext.afterPropertiesSet();
    MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext);
    converter.setCustomConversions(conversions);
    converter.setCodecRegistryProvider(factory);
    converter.afterPropertiesSet();
    return converter;
}


@Bean
@Primary
public MongoTemplate mongoTemplate() {
    MappingMongoConverter mappingMongoConverter = (MappingMongoConverter) getDefaultMongoConverter(mongoDbFactory());
    // custom key to map dot (.) with "__mongo_key__" when saving and replacing it with dot (.) again when it 
    // is retrieved
    mappingMongoConverter.setMapKeyDotReplacement("__mongo_key__");
    return new MongoTemplate(mongoDbFactory(), mappingMongoConverter);
}
Mukundhan
  • 3,284
  • 23
  • 36