Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring data mongodb: access default POJO converter from within custom converter

I have spring data mongo custom converters setup via xml as follows

<mongo:mapping-converter id="mongoConverter" db-factory-ref="mongoDbFactory">
    <mongo:custom-converters>
        <mongo:converter ref="customWriteConverter" />
        <mongo:converter ref="customReadConverter" />
    </mongo:custom-converters>
</mongo:mapping-converter>

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg ref="mongoDbFactory"/>
    <constructor-arg ref="mongoConverter"/>
</bean>

<bean id="customWriteConverter" class="package.WriteConverter" />
<bean id="customReadConverter" class="package.ReadConverter" />

In the custom read/write converter, I would like to re-use spring-data-mongo's default pojo converter to save certain properties as subdocuments.

consider a simplified example -

class A {
    B b;
    String var1;
    int var2;
}

class B {
    String var3;
    String var4;
}

I want to handle conversion of class A using customWriteConverter and customReadConverter, but in my custom converters I also want to delegate conversion of class B back to spring-data-mongo's default POJO converter.

How can I do this? I have not been able to successfully autowire a MongoConverter or MongoTemplate into the custom converter since the MongoConverter/MongoTemplate bean creation is in progress when it tries to create the custom converter. Is it possible to get access to the default converter and use that from within the custom converter?

like image 381
ashutosh Avatar asked Sep 30 '14 11:09

ashutosh


People also ask

What is the difference between MongoOperations and MongoTemplate?

MongoTemplate provides a simple way for you to save, update, and delete your domain objects and map those objects to documents stored in MongoDB. You can save, update and delete the object as shown below. MongoOperations is the interface that MongoTemplate implements.

What is @document annotation in spring boot?

@Document is an annotation provided by Spring data project. It is used to identify a domain object, which is persisted to MongoDB. So you can use it to map a Java class into a collection inside MongoDB. If you don't use Spring Data, you don't need this annotation.

How does spring boot store JSON objects in MongoDB?

To store raw json object/array, all you have to do is to declare the type as "Object" in the Pojo and/or DTO level on your server side. The "Object" type will work with Spring Data and MapStruct too. Then on the client side, you can send your json data as a json data.

What is MongoTemplate?

MongoTemplate — MongoTemplate implements a set of ready-to-use APIs. A good choice for operations like update, aggregations, and others, MongoTemplate offers finer control over custom queries. MongoRepository — MongoRepository is used for basic queries that involve all or many fields of the document.


2 Answers

This method is used in MongoTemplate class to get a default converter.

private static final MongoConverter getDefaultMongoConverter(MongoDbFactory factory) {
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
    MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext());
    converter.afterPropertiesSet();
    return converter;
}

MappingMongoConverter is not final and so can be overridden for a specific purpose. As mentioned in my comment above, look at this question to maybe find out solution to your problem.

like image 79
Harsh Poddar Avatar answered Oct 13 '22 16:10

Harsh Poddar


If you are converting TO mongo database and want to default some conversions, you could do something like this:

    ...

    @Resource
    private ObjectFactory<MappingMongoConverter>
        mappingMongoConverterObjectFactory;

    private MappingMongoConverter
        mappingMongoConverter;

    ...

    //Otherwise, use default MappingMongoConverter
    //
    if (result == null)
        result =
            getMappingMongoConverter()
                .convertToMongoType(
                    value
                );

    ...

    MappingMongoConverter getMappingMongoConverter() {
        if (mappingMongoConverter == null)
            mappingMongoConverter =
                mappingMongoConverterObjectFactory.getObject();
        return
            mappingMongoConverter;
    }

The MappingMongoConverter cannot be directly @Resource (ed) in my case since it's in the process of being constructed when other converters are being built. So, Spring detects a circular reference. I am not sure if there is a better "lazy" method of doing this without all the run-around of ObjectFactory, getter method, and caching.

Now, if someone can figure out a method of defaulting to standard processing while going back (from DBObject to java Object) that would complete this circle.

like image 33
Alex Paransky Avatar answered Oct 13 '22 16:10

Alex Paransky