I know it's quite late but today I just faced this problem and I thought maybe it's better to share it here.
Since MongoTemplate (and its default converters) are initialized after our custom-converters, it's not possible to inject those directly into our converters, but we can access those by implementing ApplicationContextAware
in our converters.
After accessing to mongoTemplate, we can delegate the read/write conversion to it by calling mongoTemplate.getConverter().read
and mongoTemplate.getConverter().write
methods respectively.
Let's examine an example. Assume we have two POJOs:
public class Outer {
public String var1;
public int var2;
public Inner inner;
}
public class Inner {
public String var3;
public String var4;
}
The WriteConverter could be something like this:
import org.bson.Document;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
@Component
public class CustomWriteConverter implements Converter<Outer, Document>, ApplicationContextAware {
private ApplicationContext applicationContext;
private MongoTemplate mongoTemplate;
@Override
public Document convert(Outer source) {
if (mongoTemplate == null) {
this. mongoTemplate = applicationContext.getBean(MongoTemplate.class);
}
// do some custom stuff
Document document = new Document();
document.put("var1", source.var1);
document.put("var2", source.var2);
Document inner = new Document();
mongoTemplate.getConverter().write(source.inner, inner);
document.put("inner", inner);
return document;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
And the ReadConverter:
import org.bson.Document;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
@Component
public class CustomReadConverter implements Converter<Document, Outer>, ApplicationContextAware {
private ApplicationContext applicationContext;
private MongoTemplate mongoTemplate;
@Override
public Outer convert(Document source) {
if (mongoTemplate == null) {
this. mongoTemplate = applicationContext.getBean(MongoTemplate.class);
}
// do some custom stuff
Outer outer = new Outer();
outer.var1 = source.getString("var1");
outer.var2 = source.getInteger("var2");
Inner inner = mongoTemplate.getConverter().read(Inner.class, (Document) source.get("inner"));
outer.inner = inner;
return outer;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
The mongoTemplate could be initialized by multiple threads (because it's in a race condition), but since it has a scope of singleton, there would be no problem.
Now the only thing to do is to register our converters.