添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Recently I am using mongodb java async driver which is newly released. I am writing some simple test codes, which are:

    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:

April 18, 2015 10:50:27 afternoon com.mongodb.diagnostics.logging.JULLogger log message: Cluster created with settings {hosts=[localhost:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
database has been connected! April 18, 2015 10:50:28 afternoon com.mongodb.diagnostics.logging.JULLogger log message: No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, all=[ServerDescription{address=localhost:27017, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out

So you can see there is no callback function called. Anyone knows why?

The short answer is your callback will be called eventually.

For the long answer, lets work through your code:

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

MongoClient doesn't block waiting for a connection to MongoDB in the background the internal connection pool is trying to connect. From your logs I can see you have the default serverSelectionTimeout of 30000ms.

Next step you do a println which output immediately so "database has been connected!" gets printed regardless.

Finally, you call listDatabaseNames() but what's not clear is if any waits for the callback to be called. If you add a latch then await the response then you will see that the callback is called eg:

  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 latch we await() until the callback has been called, now we should see one of two things happen:

  • There is no MongoDB available. It will eventually call the callback and print that there was an error. It will wait until the serverSelectionTimeout times out.

  • There is a MongoDB available. It will eventually connect, for each database it will apply the Block and print out the database name and then finally it will call the callback signalling it has finished.

  • Why should I call wait explicitly, shouldn't the program wait until all user thread finished? – Sisyphus Sep 1, 2015 at 10:56

    I think you should close the MongoClient object every time in a finally clause. For me the same problem occured, and when I closed the connection in the command line I saw that a LOT of connections were open.

    Try something like this (I use 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 this, I could use my connection with no problem.

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.