MongoDB: server not selected using ReadPreferenceServerSelector

I am recently using the async java mongodb driver which was recently released. I am writing some simple test codes that:

    MongoClient mongoClient = MongoClients.create();
    System.out.println("database has been connected!");

    SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Void>() {
        @Override
        public void onResult(final Void result, final Throwable t) {
            System.out.println("Operation Finished!");
        }
    };

    mongoClient.listDatabaseNames().forEach(new Block<String>() {
        @Override
        public void apply(final String s) {
            System.out.println(s);
        }
    }, callbackWhenFinished);

      

however the callback function is not called, the console output is:

Apr 18, 2015 10:50:27 AM com.mongb.diagnostics.logging.JULLogger log message: Cluster created with settings {hosts = [localhost: 27017], mode = SINGLE, requiredClusterType = UNKNOWN, serverSelectionTimeout = '30000 ms', maxWaitQueueSize = 500}
the database has been connected! April 18, 2015 10:50:28 AM com.mongb.diagnostics.logging.JULLogger log message: No server selected by ReadPreferenceServerSelector {readPreference = primary} from cluster description ClusterDescription {type = UNKNOWN, connectionMode = SINGLE, all = [ServerDescription {address = localhost: 27017, type = UNKNOWN, state = CONNECTING}]}. Wait 30,000ms before shutdown time

So you can see that the callback function is not called. Does anyone know why?

+3


source to share


2 answers


The short answer is your answer will be called eventually.

For a long answer, let's work through your code:

    MongoClient mongoClient = MongoClients.create();
    System.out.println("database has been connected!");

      

MongoClient

does not block waiting for a connection to MongoDB in the background that tries to connect the internal connection pool. From your logs, I can see that you have a default of serverSelectionTimeout

30000ms.

In the next step you do println

, which is immediately outputted so that "the database is connected!". printed independently.



Finally, you call listDatabaseNames()

, but it's not clear if there is anyone waiting for the callback to be called. If you add a latch, then wait for a response, then you will see that the callback is called, for example:

  System.out.println("======= Start =======");

  MongoClient mongoClient = MongoClients.create();

  final CountDownLatch latch = new CountDownLatch(1);

  SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Void>() {
      @Override
      public void onResult(final Void result, final Throwable t) {
          System.out.println("Operation Finished!");
          if (t != null) {
              System.out.println("listDatabaseNames() errored: " + t.getMessage());
          }
          latch.countDown();
      }
  };

  mongoClient.listDatabaseNames().forEach(new Block<String>() {
      @Override
      public void apply(final String s) {
          System.out.println(s);
      }
  }, callbackWhenFinished);

  latch.await();

  // close resources
  mongoClient.close();
  System.out.println("======= Finish =======");

      

Now, using the we latch await()

until the callback is called, we should now see one of two things:

  • No MongoDB available. Eventually it will call the callback and print out the error message. He will wait for the time to run out serverSelectionTimeout

    .

  • MongoDB available. It will eventually connect, for each database, it will apply Block

    and print the name of the database, and then finally call the callback to complete.

+6


source


I think you should close the MongoClient object every time in the finally clause. The same problem came up for me, and when I closed the connection on the command line, I saw that many connections were open.

Try something like this (I'm using mongodb 3.0.7 and mongo-java-driver 3.1.0):



package com.mkyong.core;

import org.bson.Document;
import org.junit.Test;

import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoDatabase;

/**
 * Unit test for simple App.
 */
public class AppTest {

    @Test
    public void firstTest() throws Exception {
        MongoClient mongoClient = null;
        try {
            mongoClient = new MongoClient("127.0.0.1", 27017);
            MongoDatabase db = mongoClient.getDatabase("census");
            FindIterable<Document> iterable = db.getCollection("states").find();
            iterable.forEach(new Block<Document>() {
                @Override
                public void apply(final Document document) {
                    System.out.println(document);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                mongoClient.close();
            } catch (Exception e2) {
            }
        }
    }

}

      

With that, I could use my connection without any problem.

+2


source







All Articles