Skip to content

Instantly share code, notes, and snippets.

@harlanji
Created August 29, 2011 23:42
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save harlanji/1179718 to your computer and use it in GitHub Desktop.
Save harlanji/1179718 to your computer and use it in GitHub Desktop.
Best way to add custom converters to spring-data-mongodb?
MongoTemplate mongo = ...;
List<Converter> converters = new ArrayList<Converter>();
converters.add(new Converter<DBObject, Participant>() {
public Participant convert(DBObject s) {
throw new UnsupportedOperationException("Not supported yet 1.");
}
});
converters.add(new Converter<Participant, DBObject>() {
public DBObject convert(Participant s) {
throw new UnsupportedOperationException("Not supported yet 2.");
}
});
CustomConversions cc = new CustomConversions(converters);
((MappingMongoConverter)mongo.getConverter()).setCustomConversions(cc);
@greenlaw110
Copy link

Doesn't work for me. I have two converters which is configured in the mvc-dispatcher-servlet.xml as

<mongo:mapping-converter id="mappingConverter">
    <mongo:custom-converters>
        <mongo:converter>
            <bean class="com.pixolut.mrb.ob.models.ObCriteria.TypeWriteConverter"/>
        </mongo:converter>
        <mongo:converter>
            <bean class="com.pixolut.mrb.ob.models.ObCriteria.TypeReadConverter"/>
        </mongo:converter>
    </mongo:custom-converters>
</mongo:mapping-converter>

It works perfect as the app is running as servlet. However when I want to start the app in command line, I put the following code to configure mongotemplate:

public MongoTemplate mongo() {
    if (null != m_) return m_;
    MongoCredential mc = null;
    if (!S.empty(password)) {
        mc = MongoCredential.createMongoCRCredential(username, db, password.toCharArray());
    }
    try {
        ServerAddress svr = new ServerAddress(host, port);
        List<MongoCredential> credentials = null == mc ? null : C.list(mc);
        MongoClient client = new MongoClient(svr, credentials);
        m_ = new MongoTemplate(client, db);
        Converter[] ca = new Converter[]{new ObCriteria.TypeWriteConverter(), new ObCriteria.TypeReadConverter()};
        CustomConversions cc = new CustomConversions(Arrays.asList(ca));
        ((MappingMongoConverter)m_.getConverter()).setCustomConversions(cc);
        new MongoTemplateHolder().setMongoTemplate(m_);
    } catch (Exception e) {
        throw E.invalidConfiguration(e, "Error creating mongo client");
    }
    return m_;
}

I get the following error stack:

java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type com.mongodb.BasicDBList<java.lang.Object> to type java.util.EnumSet<?> for value '[ "OWNER"]'; nested exception is java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.EnumSet
        at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
        at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:169)
        at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:154)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1103)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$100(MappingMongoConverter.java:78)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1058)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getValueInternal(MappingMongoConverter.java:789)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:270)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:263)
        at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:261)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:263)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:237)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1109)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$100(MappingMongoConverter.java:78)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1058)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getValueInternal(MappingMongoConverter.java:789)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:270)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$1.doWithPersistentProperty(MappingMongoConverter.java:263)
        at org.springframework.data.mapping.model.BasicPersistentEntity.doWithProperties(BasicPersistentEntity.java:261)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:263)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:237)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:201)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:197)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:78)
        at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:2005)
        at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1699)
        at org.springframework.data.mongodb.core.MongoTemplate.findAll(MongoTemplate.java:1164)
        at com.pixolut.mrb.ob.cmd.UpdateOutboundFullTextIndex.handleEvent(UpdateOutboundFullTextIndex.java:28)
        at com.pixolut.mrb.ob.cmd.Main.main(Main.java:83)
        ... 6 more
Caused by: java.lang.IllegalArgumentException: Could not instantiate Collection type: java.util.EnumSet
        at org.springframework.core.CollectionFactory.createCollection(CollectionFactory.java:258)
        at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:66)
        at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35)
        ... 34 more

@greenlaw110
Copy link

Issue found! Need to call afterPropertiesSet(). Here is the new code that works:

public MongoTemplate mongo() {
    if (null != m_) return m_;
    MongoCredential mc = null;
    if (!S.empty(password)) {
        mc = MongoCredential.createMongoCRCredential(username, db, password.toCharArray());
    }
    try {
        ServerAddress svr = new ServerAddress(host, port);
        List<MongoCredential> credentials = null == mc ? null : C.list(mc);
        MongoClient client = new MongoClient(svr, credentials);
        m_ = new MongoTemplate(client, db);
        Converter[] ca = new Converter[]{new ObCriteria.TypeWriteConverter(), new ObCriteria.TypeReadConverter()};
        CustomConversions cc = new CustomConversions(Arrays.asList(ca));
        MappingMongoConverter mmc = (MappingMongoConverter)m_.getConverter();
        mmc.setCustomConversions(cc);
        mmc.afterPropertiesSet();
        new MongoTemplateHolder().setMongoTemplate(m_);
    } catch (Exception e) {
        throw E.invalidConfiguration(e, "Error creating mongo client");
    }
    return m_;
}

@vladmm
Copy link

vladmm commented Aug 12, 2016

@greenlaw110, good ideas, saved me a lot of debugging time

@elidzah
Copy link

elidzah commented Dec 10, 2016

save a lot of debugging also for me. Trying to set a CustomConversions on multiple database repositories. the interesting part is:

    m_ = new MongoTemplate(client, db);
    Converter[] ca = new Converter[]{new ObCriteria.TypeWriteConverter(), new ObCriteria.TypeReadConverter()};
    CustomConversions cc = new CustomConversions(Arrays.asList(ca));
    MappingMongoConverter mmc = (MappingMongoConverter)m_.getConverter();
    mmc.setCustomConversions(cc);
    mmc.afterPropertiesSet(); 

in Mongo Template override. My Template override looks like the following:

@Override
@Bean(name = "mongoCTGTEmplate")
public MongoTemplate mongoTemplate() throws Exception {
    MongoTemplate m_ = new MongoTemplate(this.mongo(), databaseCTG);

    MappingMongoConverter mmc = (MappingMongoConverter) m_.getConverter();
    mmc.setCustomConversions(this.customConversions());
    mmc.afterPropertiesSet();
    return m_;
}

I spent a lot of time on the web looking for the solution, and find it here! thanks ;)

@mpereira-dev
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment