Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

greenlaw110 commented Dec 23, 2014

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

This comment has been minimized.

Copy link

greenlaw110 commented Dec 23, 2014

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

This comment has been minimized.

Copy link

vladmm commented Aug 12, 2016

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

@elidzah

This comment has been minimized.

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

This comment has been minimized.

Copy link

mpereira-dev commented Sep 22, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.