0

I have 2 servers in MongoDB replica set, one is primary and other is secondary. My application runs perfectly on primary server but when run on secondary I get following warning:

INFO: No server chosen by WritableServerSelector from cluster description ClusterDescription{type=REPLICA_SET, connectionMode=SINGLE, serverDescriptions=[ServerDescription{address=localhost:27017, type=REPLICA_SET_SECONDARY, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 2, 11]}, minWireVersion=0, maxWireVersion=4, maxDocumentSize=16777216, roundTripTimeNanos=691940, setName='rs2', canonicalAddress=192.168.71.22:27017, hosts=[192.168.70.197:27017, 192.168.71.22:27017, PC:27017], passives=[], arbiters=[], primary='PC:27017', tagSet=TagSet{[]}, electionId=null, setVersion=3}]}. Waiting for 30000 ms before timing out

Read operations (selection "2" in code) perform correctly after 30 sec timeout. Write operations (selection "1" & "3" in code) trigger this warning to appear again and don't work. What should I change in MongoDB settings or add to code to be able to perform write operations?

Code:

package ru.energodata;

import com.mongodb.*;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;


public class Main {
public static void main(String[] args) {
Scanner scanner;
int selection;
boolean exit = false;
    MongoClient mongoClient = new MongoClient("localhost", 27017);
    DB db = mongoClient.getDB("imagedb");
    GridFS gfsPhoto = new GridFS(db, "photo");

    while (!exit)
    {
        System.out.println("Choose action with the DB");
        System.out.println("1 - add files to DB");
        System.out.println("2 - list files");
        System.out.println("3 - remove files");
        scanner = new Scanner(System.in);
        if(scanner.hasNextInt()) {
            selection = scanner.nextInt();

            if (selection == 1) {
                String path = "C:\\2015";
                String fileName;
                File dir = new File(path);
                File[] imageFile = dir.listFiles();
                try {
                    for (File anImageFile : imageFile) {
                        GridFSInputFile gfsFile = gfsPhoto.createFile(anImageFile);
                        fileName = anImageFile.getName();
                        System.out.println("Current file: " + fileName);
                        // set a new filename for identify purpose
                        gfsFile.setFilename(fileName);
                        // save the image file into mongoDB
                        gfsFile.save();
                    }
                } catch (MongoException | IOException e) {
                    e.printStackTrace();
                }
            }

            if (selection == 2) {
                // print the result
                System.out.println("Database content:");
                DBCursor cursor = gfsPhoto.getFileList();
                if (cursor.hasNext()) {
                    while (cursor.hasNext()) {
                        System.out.println(cursor.next());
                    }
                }

                    else {System.out.println("none.");
                }
            }
            if (selection == 3) {
                // remove the image file from mongoDB
                DBCursor cursor = gfsPhoto.getFileList();
                if (cursor.hasNext()) {
                while (cursor.hasNext()) {
                    gfsPhoto.remove(cursor.next());
                }
                System.out.println("DB content deleted");
                }
                else {System.out.println("DB is empty");
                }
            }
        }
    else {
            System.out.println("Select either 1, 2 or 3");
            scanner = new Scanner(System.in);
        }
    }
}
}
Community
  • 1
  • 1
Paco de la Vega
  • 131
  • 3
  • 15
  • 1
    this should help you.. http://stackoverflow.com/questions/14587398/how-to-prefer-reads-on-secondaries-in-mongodb – user641887 Nov 22 '16 at 18:28

1 Answers1

1

Found out by myself. Changed line:

MongoClient mongoClient = new MongoClient("localhost", 27017);

to

    MongoClientOptions options = MongoClientOptions.builder()
            .readPreference(ReadPreference.nearest())
            .writeConcern(WriteConcern.W2)
            .build();
    MongoClient mongoClient = new MongoClient(Arrays.asList(
            new ServerAddress(serverList[0]),
            new ServerAddress(serverList[1]),
            new ServerAddress(serverList[2])),options);

Where serverList[] string array contains addresses of all servers in replica set. Now application finds primary server and connects to it.

INFO: Discovered replica set primary pc:27017
INFO: Opened connection [connectionId{localValue:5, serverValue:79}] to pc:27017

So write operations become available as you can write only to primary server in set.

Paco de la Vega
  • 131
  • 3
  • 15