【问题标题】:How to catch exception when creating MongoClient instance创建 MongoClient 实例时如何捕获异常
【发布时间】:2016-11-25 22:41:49
【问题描述】:

我正在使用 Mongo DB java 驱动程序连接到 mongo 实例。下面是我用来创建 MongoClient 实例的代码。

try {
            new MongoClient("localhost", 1111);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

如果主机名或端口号不正确,我会得到以下异常。我徘徊如何捕捉异常。 MongoDB 连接发生在客户端代码无法捕获的内部线程中。我想知道 MongoClient 是否连接正确。我怎样才能获得这些信息?

INFO: Exception in monitor thread while connecting to server localhost:0
com.mongodb.MongoSocketOpenException: Exception opening socket
    at com.mongodb.connection.SocketStream.open(SocketStream.java:63)
    at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115)
    at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:116)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.ConnectException: Can't assign requested address (connect failed)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:50)
    at com.mongodb.connection.SocketStream.open(SocketStream.java:58)
    ... 3 more

EDIT1

上面显示的异常没有被我的代码捕获。它可能会被 Mongo 代码捕获。所以不知道实例是否创建正确。

【问题讨论】:

    标签: mongodb mongodb-java


    【解决方案1】:

    服务器连接是在守护线程上创建的。长话短说,您将无法在创建 Mongo 客户端时检查与连接相关的错误。

    当您创建第一个涉及读取或写入的真实数据库时,您将不得不延迟连接检查。

    仅用于演示目的,让您了解一下。

    MongoClient mongoClient = new MongoClient("127.0.34.1", 89);
    DB db = mongoClient.getDB("test");
    try {
       db.addUser("user", new char[] {'p', 'a', 's', 's'});
    } catch(Exception e) { MongoTimeoutException exception}
    

    来自 Deamon 线程的 MongoSocketOpenException

    INFO: Exception in monitor thread while connecting to server 127.0.34.1:89
    com.mongodb.MongoSocketOpenException: Exception opening socket
    at com.mongodb.connection.SocketStream.open(SocketStream.java:63)
    at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115)
    at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:116)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.net.ConnectException: Connection refused: connect
    

    来自主线程的 MongoTimeoutException

    Exception in thread "main" com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=127.0.34.1:89, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, 
    caused by {java.net.ConnectException: Connection refused: connect}}]
    at com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:375)
    

    因此,使用MongoTimeoutException 将代码包装在try catch 块中,它可以正常检查与连接相关的错误。

    【讨论】:

      【解决方案2】:

      它非常简单优雅:

      1. System.err 重定向到一个文件:

        ByteArrayOutputStream file=new ByteArrayOutputStream();
        System.setErr(new PrintStream(file));
        
      2. 使用您的MongoClient 和您的MongoCredentials 连接到服务器:

        MongoCredential credenciales=MongoCredential.createCredential("root", "admin", "root".toCharArray());
        MongoClient client = new MongoClient(new ServerAddress("localhost"), Arrays.asList(credenciales));
        
      3. 读取错误输出,在ByteArrayOutputStream对象中:

        String texto=new String(file.toByteArray());
        
      4. 检查Autentication failed字符串是否存在:

        if (texto.contains("'Authentication failed.'"))
           // do something;
        else
          ...
        

      【讨论】:

        【解决方案3】:

        对于现在偶然发现这一点的任何人。我遇到了同样的问题并尝试使用 Macario 的答案,但运气不佳。然后意识到监视连接的线程不是将其发送到 System.err,而是将其发送到 System.out,所以不要使用 System.err,而是像这样使用 System.out:

        PrintStream out = System.out;  // Save the original out stream to reset later
        
        // Set out to a buffer
        ByteArrayOutputStream file=new ByteArrayOutputStream();
        System.setOut(new PrintStream(file));
        
        mongoClient = new MongoClient(new MongoClientURI("<connection_string>")));
        
        // Found this to be important as we need to wait for the thread to dump to out
        // 1000 millis was too fast for me but 2000 did the trick
        Thread.sleep(2000);
        
        // Convert buffer to a string
        String texto=new String(file.toByteArray());
        
        System.setOut(out); // Reset out
        
        // Check if saved out contins the error (I was looking for MongoSocketException)
        if(texto.contains("MongoSocketException")){
            // Do Stuff
        }
        

        【讨论】:

          【解决方案4】:
            new MongoClient("localhost", 1111);
          
                  } catch (MongoSocketOpenException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
          

          您只需在 catch 块中命名适当的异​​常。这适用于任何例外。您可以为每个唯一异常添加尽可能多的 catch 块

          【讨论】:

          • 我试过了,但还是没有发现异常。如果您查看我在帖子中打印的异常堆栈,您可以看到“at java.lang.Thread.run(Thread.java:745)”这一行,这表明异常发生在线程上。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-10
          • 2012-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-12
          相关资源
          最近更新 更多