techrhl
techrhl

Reputation: 454

Not able to connect to Microsoft Azure Cosmos Emulator through MongoClient

I am trying to push some data to Azure Cosmos DB. As a shortcut, read about Microsoft Azure Cosmos Emulator and installed it in my local machine, and able to see the main page (Dashboard) through https://localhost:8081/_explorer/index.html

enter image description here

Here is the code I am trying

    MongoClientURI uri = new MongoClientURI("mongodb://localhost:C2y6yDjf5%2FR%2Bob0N8A7Cgv30VRDJIWEHLM%2B4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw%2FJw%3D%3D@localhost:10255/admin?ssl=true");
    MongoClient mongoClient = null;
    try {
        mongoClient = new MongoClient(uri);
        MongoDatabase database = mongoClient.getDatabase("DEMO_ACTUALS");
        MongoCollection<Document> collection = database.getCollection("Item");
        collection.insertOne(generatePurchaseOrder(new OrderDetail("Laptop", "Sekhar", 1000)));
        collection.insertOne(generatePurchaseOrder(new OrderDetail("Desktop", "Nilanjan", 2000)));
        Document queryResult = collection.find().first();
        System.out.println(queryResult.toJson());
    } finally {
        if (mongoClient != null) {
            mongoClient.close();
        }
    }

I am getting the following error. Tried adding the certificate also to JVM.

    > Aug 11, 2021 5:58:56 PM com.mongodb.diagnostics.logging.JULLogger log
    INFO: Cluster created with settings {hosts=[localhost:10255], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
    Aug 11, 2021 5:58:56 PM com.mongodb.diagnostics.logging.JULLogger log
    INFO: No server chosen by WritableServerSelector from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, serverDescriptions=[ServerDescription{address=localhost:10255, type=UNKNOWN, state=CONNECTING}]}. Waiting for 30000 ms before timing out
    Aug 11, 2021 5:58:56 PM com.mongodb.diagnostics.logging.JULLogger log
    INFO: Exception in monitor thread while connecting to server localhost:10255
    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:113)
        at java.base/java.lang.Thread.run(Thread.java:831)
    Caused by: java.net.ConnectException: Connection refused: no further information
        at java.base/sun.nio.ch.Net.pollConnect(Native Method)
        at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:669)
        at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542)
        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:333)
        at java.base/java.net.Socket.connect(Socket.java:645)
        at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:290)
        at com.mongodb.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:57)
        at com.mongodb.connection.SocketStream.open(SocketStream.java:58)
        ... 3 more
    > 
    > 
    > Exception in thread "main" com.mongodb.MongoTimeoutException: Timed out after 30000 ms 
while waiting for a server that matches WritableServerSelector. Client view of cluster state 
is {type=UNKNOWN, servers=[{address=localhost:10255, type=UNKNOWN, state=CONNECTING, 
exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by 
 {java.net.ConnectException: Connection refused: no further information}}]
        at com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:377)

Upvotes: 0

Views: 1939

Answers (1)

Vlad Rez
Vlad Rez

Reputation: 21

I had faced similar problems before and was able to reproduce the issue with the provided code snippet.

For this specific exception:

java.security.cert.CertPathValidatorException: signature check failed

Good chance it's how the SSL certificate is set up in your JVM.

Try this:

  1. Run the emulator at the 3.6 API level using a terminal with elevated permissions (sudo or PowerShell with Run as Administrator).

.\CosmosDB.Emulator /EnableMongoDBEndpoint=3.6

  1. When the emulator starts, use the explorer web page to create your database and collection as needed.

  2. Note which JDK you are using to run your app with java -version or if you're using an IDE like IntelliJ File > Project Structure > Project Settings > Project SDK.

In this example, I'm using Oracle JDK v1.8 on Windows.

  1. Add the emulator's certificate to JVM:

If you have *nix system, WSL, or Git Bash installed on Windows, use OpenSSL to get the server certificate.

openssl s_client -connect localhost:8081

From the response, copy the Server Certificate section into a file and call it something like cosmos_emulator.cert.

File content should be something like this:

-----BEGIN CERTIFICATE-----
3IIDJjCCAg6gAaIBAgIQYxVF123456789qwYfvqr6TANBgkqhkiG9aHBAQUFADAU
...
...
...
vGvh3/t88agaKl3iZL3hQYfDQ12456789zxc+kHNr2xygbaQaDAFHL9IS
-----END CERTIFICATE-----

Alternatively, if on Windows, you can export this file via Control Panel -> Manage Computer Certificates as described in Azure Docs: Export the Azure Cosmos DB Emulator certificates.

We want to add this saved *.cert/*.cer file to the JVM keystore file cacerts located in:

'C:\Program Files\Java\jdk1.8.0_202\jre\lib\security\'

To do this, navigate to the keytool app located in:

'C:\Program Files\Java\jdk1.8.0_202\jre\bin\'

and run

.\keytool.exe -importcert -alias cosmos_emulator -file .\path\to\certfile\cosmos_emulator.cert -keystore .\..\lib\security\cacerts

A prompt will appear to Trust this certificate?, type yes. Next, it will ask for the Keystore password; the default is changeit.

This needs to be done on a terminal with elevated privileges. Otherwise, it will throw an exception.

  1. From here, you should be able to access the emulator through your app.

Note: You will have to do this every time your system restarts, so before installing a new certificate, delete the old one with the keytool command:

.\keytool.exe -delete -noprompt -alias cosmos_emulator -file .\path\to\certfile\cosmos_emulator.cert -keystore .\..\lib\security\cacerts

Enter the default password changeit when prompted to delete.

Upvotes: 1

Related Questions