How to set MongoDB ReadPreference in Spring MVC's contextConfigLocation

12,166

Solution 1

Expanding @Trisha's response in to an answer: "Do it in MongoTemplate programmatically" by setting the ReadPreference to SECONDARY.

MongoTemplate template = new MongoTemplate(...);
template.setReadPreference(com.mongodb.ReadPreference.SECONDARY);

Solution 2

Declare the following bean

<bean id="readPreferenceSecondary" class="com.mongodb.TaggableReadPreference.SecondaryReadPreference">
</bean>

and

you inject this in your mongotemplate

<bean id="mongoTemplateProdDb" class="org.springframework.data.mongodb.core.MongoTemplate" >
        <property name="readPreference" ref="readPreferenceSecondary"></property>
</bean>

Solution 3

In case you are using spring-data-mongodb and have some requirement to use multiple Read Preferences based on find query, you can create multiple Mongo Templates and/or Repositories like

    @EnableMongoRepositories(basePackages = {
            "com.you.repo.package" }, mongoTemplateRef = "mongoTemplateOne")    
    @Configuration
    public class MongoConfig {

    @Bean(name="mongoTemplateOne")
    public MongoTemplate getMongoTemplateOne() throws UnknownHostException {
        MongoTemplate templateOne = new MongoTemplate(new SimpleMongoDbFactory(new MongoClientURI("YOUR_MONGO_URL")));
        templateOne.setReadPreference(ReadPreference.secondaryPreferred());

        //setting WriteConcern but not relevant for this thread
        templateOne.setWriteConcernResolver(yourWriteConcernResolver());
        return templateOne;
    }

    @Bean(name = "mongoTemplateTwo")
    public MongoTemplate getMongoTemplateTwo() throws UnknownHostException {
        MongoTemplate templateTwo = new MongoTemplate(new SimpleMongoDbFactory(new MongoClientURI("YOUR_MONGO_URL")));
        templateTwo.setReadPreference(ReadPreference.secondaryPreferred());
        return templateTwo;
    }


    private WriteConcernResolver yourWriteConcernResolver() {
        return action -> {
            if (action.getCollectionName()
                    .equals("your_collecton")
                    && (action.getMongoActionOperation() == MongoActionOperation.SAVE
                            || action.getMongoActionOperation() == MongoActionOperation.UPDATE)) {
                return WriteConcern.MAJORITY;
            }
            return action.getDefaultWriteConcern();
        };
    }

Solution 4

In case you have more than one secondary (replica-set) you can be more specific and tell the mongo driver explicitly which of the secondaries you want to read from, using tags.

On the mongo side you run this command:

db.getMongo().setReadPref('secondaryPreferred',
                          [{"tagName":"TagVal1"},
                            {"tagName":"TagVal2"},
                            {}])

In the code it looks like this:

MongoTemplate template = new MongoTemplate(...)
template.setReadPreference(ReadPreference.secondaryPreferred("your DBObject that reflect your mongo tag names");

Hope it helps.

Share:
12,166
sorebrek
Author by

sorebrek

Programmer @ Davis, CA

Updated on June 17, 2022

Comments

  • sorebrek
    sorebrek almost 2 years

    I am connecting to a MongoDB sharding server via mongodb java driver in Spring MVC. I am using the following versions:

    • spring-webmvc-3.2.1.RELEASE
    • mongo-java-driver/2.10.0/mongo-java-driver-2.10.0
    • spring-data-mongodb-1.2.0.RELEASE

    My Mongo options are set in the contextConfigLocation file mvc-dispatcher-servlet.xml

    <mongo:mongo host="mongo.sample.com" port="30000">
         <mongo:options auto-connect-retry="true"
                        slave-ok="true"/>
    </mongo:mongo>
    

    It works pretty well, but the slave-ok is deprecated by come.MongoDB.ReadPreference. I just wonder if there is any way to set the readPreference for Spring MVC in the contextConfiLocation file.