2015-04-18 1 views
3

Недавно я использую новый драйвер async mongodb java. Я пишу некоторые простые коды испытаний, которые являются:MongoDB: Нет сервера, выбранных ReadPreferenceServerSelector

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); 

однако, функция обратного вызова не вызывается, выход консоли:

18 апреля 2015 10:50:27 днем ​​ ком .mongodb.diagnostics.logging.JULLogger сообщение журнала: Кластер создан с настройками {хостами = [LOCALHOST: 27017], режим = SINGLE, requiredClusterType = НЕИЗВЕСТНЫХ, serverSelectionTimeout = '30000', мс maxWaitQueueSize = 500}
базы данных было c onnected! 18 апреля 2015 10:50:28 днем ​​журнал com.mongodb.diagnostics.logging.JULLogger сообщение: Нет сервер выбран ReadPreferenceServerSelector {readPreference = первичный} из кластера описание ClusterDescription {тип = UNKNOWN, connectionMode = SINGLE , all = [ServerDescription {address = localhost: 27017, type = UNKNOWN, state = CONNECTING}]}. Ожидание 30000 мс до выключения времени

Таким образом, вы можете видеть, что функция обратного вызова не называется. Кто-нибудь знает почему?

ответ

6

Короткий ответ - ваш обратный вызов будет называться в конечном итоге.

Для длительного ответа, позволяет работать по коду:

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

MongoClient не блокирует ожидание соединения с MongoDB в фоновом режиме внутренний бассейн подключение пытается подключиться. Из ваших журналов я вижу, что у вас есть значение по умолчанию serverSelectionTimeout из 30000 мс.

Следующий шаг: вы делаете println, который выводит сразу, чтобы «база данных была подключена!». печатается независимо.

Наконец, вы вызываете listDatabaseNames(), но неясно, есть ли кто-либо, ожидающий вызова обратного вызова. Если добавить защелку, то ждать ответа, то вы увидите, что обратного вызова вызывается, например:

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 ======="); 

Теперь с помощью защелки мы await() до обратного вызова не было названо, теперь мы должны увидеть один из двух вещей происходит:

  1. В наличии отсутствует MongoDB. В конечном итоге он вызовет обратный вызов и распечатает сообщение об ошибке. Он будет ждать до serverSelectionTimeout раз.

  2. Доступен MongoDB. В конечном итоге он подключится, для каждой базы данных он применит Block и распечатает имя базы данных, а затем, наконец, он вызовет завершение обратного вызова.

+0

Почему я должен явным образом вызывать ожидание, не должна ли программа ждать завершения всего пользовательского потока? – Sisyphus

2

Я думаю, что вы должны закрыть объект MongoClient каждый раз в предложении finally.Для меня та же проблема возникла, и когда я закрыл соединение в командной строке, я увидел, что было открыто много соединений.

Попробуйте что-то вроде этого (я использую MongoDB 3.0.7 и Монго-Java-драйвер 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) { 
      } 
     } 
    } 

} 

С этим, я мог бы использовать мое подключение без проблем.

 Смежные вопросы

  • Нет связанных вопросов^_^