最近我使用的是新发布的mongodb java异步驱动程序。我正在写一些简单的测试代码,它们是:
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);
但是,未调用回调函数,控制台输出为:
2015年4月18日下午10:50:27 com.mongodb.diagnostics.logging.JULLogger日志消息:已创建集群 设置为{hosts = [localhost:27017],mode = SINGLE, requiredClusterType = UNKNOWN,serverSelectionTimeout =&#39; 30000 ms&#39;, maxWaitQueueSize = 500}
数据库已连接! 2015年4月18日下午10:50:28 com.mongodb.diagnostics.logging.JULLogger日志消息:否 选择的服务器 集群中的ReadPreferenceServerSelector {readPreference = primary} description ClusterDescription {type = UNKNOWN,connectionMode = SINGLE, all = [ServerDescription {address = localhost:27017,type = UNKNOWN, 状态= CONNECTING}]}。在超时之前等待30000毫秒
所以你可以看到没有调用回调函数。谁知道为什么?
答案 0 :(得分:7)
简短的回答是你的回调最终会被调用。
对于长篇答案,让我们完成您的代码:
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 =======");
现在使用latch await()
直到调用回调,现在我们应该看到以下两种情况之一:
没有可用的MongoDB。
它最终将调用回调并打印出错误。它将等到serverSelectionTimeout
次超时。
有一个MongoDB可用。
它最终将连接,对于每个数据库,它将应用Block
并打印出数据库名称,然后最终它将调用已完成的回调信号。
答案 1 :(得分:2)
我认为你应该每次在finally子句中关闭MongoClient对象。对我来说同样的问题发生了,当我在命令行中关闭连接时,我看到很多连接都是打开的。
尝试这样的事情(我使用mongodb 3.0.7和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) {
}
}
}
}
有了这个,我可以毫无问题地使用我的连接。