Testing java mongodb driver source with mongodb running remotly - mongodb

I have made changes to source code, I require to run all testcases to check its effect using command
./gradlew check
I am having the mongodb running in remote machine. Can anyone help me in configuring java mongodb driver with remotely running mongodb.

you need to import the java driver to your project.
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
then you need to connect to the mongoDB on your server, it can be localhost or it can be your server. also you can choose which port to use:
MongoClient mongoClient = new MongoClient("localhost", 27017);
then you can connect to your db:
MongoDatabase db = mongoClient.getDatabase("test");
and to connect to one of your collections, and make actions on it:
db.getCollection("restaurants").insertOne(
new Document("address",
new Document()
.append("street", "2 Avenue")
.append("zipcode", "10075")
.append("building", "1480")
.append("coord", asList(-73.9557413, 40.7720266)))
.append("borough", "Manhattan")
.append("cuisine", "Italian")
.append("grades", asList(
new Document()
.append("grade", "A")
.append("score", 11),
new Document()
.append("grade", "B")
.append("score", 17)))
.append("name", "Vella")
.append("restaurant_id", "41704620"));

One can pass the connection string while starting testcases
./gradlew check -Dorg.mongodb.test.uri=mongodb://example.com:27017/

Related

Combine MongoDb clients: pyMongo and MongoEngine

In my web application, I use Flask as framework and MongoDB as persistent layer. There are multiple libraries to connect to MongoDB. I am currently using the low-level lib pyMongo. However, I would like to combine it with MongoEngine for some models.
The only approach I see is to create an instance of both clients. This looks a big doggy. Is there a simpler way to combine these libraries (pyMongo, MongoEngine) such that they use the same database (with different collections).
Its currently not possible to use an existing Pymongo client to connect MongoEngine but you can do the opposite; if you connect MongoEngine, you can retrieve its underlying pymongo client or database instances.
from mongoengine import connect, get_db, Document, StringField
conn = connect() # connects to the default "test" database on localhost:27017
print(conn) # pymongo.MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True, read_preference=Primary())
db = get_db() # pymongo.Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True, read_preference=Primary()), u'test')
print(db)
class Person(Document):
name = StringField()
coll = Person._get_collection()
print(coll) # pymongo.Collection(Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True, read_preference=Primary()), u'test'), u'person')

MongoDB "no SNI name sent" error from heroku java application

I followed this tutorial to deploy a sample application to Heroku. I just added the below method in MyResource class and returned the result from it instead of "Hello World" from getIt() method. I'm connecting to an atlas free tier cluster:
static String getMessage() {
MongoClient mongoClient = new MongoClient(new MongoClientURI("mongodb://<USER>:<PASSWORD>#cluster0-shard-00-00-2lbue.mongodb.net:27017,cluster0-shard-00-01-2lbue.mongodb.net:27017,cluster0-shard-00-02-2lbue.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin"));
DB database = mongoClient.getDB("mastery");
DBCollection collection = database.getCollection("summary");
DBObject query = new BasicDBObject("_id", new ObjectId("5c563fa2645d6b444c018dcb"));
DBCursor cursor = collection.find(query);
return (String)cursor.one().get("message");
}
This is the driver I'm using:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.9.1</version>
</dependency>
This is my import:
import com.mongodb.*;
The application works fine from my local system. But I face the below error when I deploy the application to Heroku and hit the service:
INFO: Exception in monitor thread while connecting to server cluster0-shard-00-01-2lbue.mongodb.net:27017
com.mongodb.MongoCommandException: Command failed with error 8000 (AtlasError): 'no SNI name sent, make sure using a MongoDB 3.4+ driver/shell.' on server cluster0-shard-00-01-2lbue.mongodb.net:27017. The full response is { "ok" : 0, "errmsg" : "no SNI name sent, make sure using a MongoDB 3.4+ driver/shell.", "code" : 8000, "codeName" : "AtlasError" }
at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:179)
at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:299)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:255)
at com.mongodb.internal.connection.CommandHelper.sendAndReceive(CommandHelper.java:83)
at com.mongodb.internal.connection.CommandHelper.executeCommand(CommandHelper.java:33)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescription(InternalStreamConnectionInitializer.java:106)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:63)
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:127)
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117)
at java.lang.Thread.run(Thread.java:748)
What is this SNI name? I can understand that the drivers are able to pick it from my machine, but not from Heroku machine. But I'm clueless on how to go about solving this! Is there a way to configure Heroku to reveal the SNI name when the driver asks for it? Can we get this value manually from somewhere in Heroku and directly feed it to the MongoDB drivers? Any help is appreciated.
EDIT:
It turned out that the client mentions the SNI name of the server it wishes to connect to as part of TLS security. And there seems to be a way to manually indicate the name in python driver. Is there any way to do this from java? Still puzzled why this is not an issue when running the app locally.
The code I was using to connect to the cluster turned out to be wrong. I followed the directions from the docs and it mentioned this:
To connect to an Atlas M0 (Free Tier) cluster, you must use Java
version 8 or greater and use a Java driver version that supports
MongoDB 3.4.
So I changed the java version to 1.8 in system.properties file:
java.runtime.version=1.8
It was earlier set to 1.7. I was also getting a deprecation warning on one of the methods I had used. So I again followed the docs to use the latest code and it worked like a charm.
The real takeaway here is to refer to the official docs everytime :)

MongoConnectionTimeOut is not working using the MongoClientURI

I am trying to connect MongoDB using MongoClientURI(URL) my URL is mongodb://userName:Password#host:PortNumber/DBName?connectTimeoutMS=10000
when my MongoDB is Down i try to Post Request but it take default time 30 sec.
Can any one help me solve the problem
Thanks in Advance.
You can set timeouts by using the Mongo Java client's MongoClientOptions. For example:
MongoClientOptions clientOptions = MongoClientOptions.builder()
.connectTimeout(...)
.socketTimeout(...)
.serverSelectionTimeout(...)
.build();
MongoClient mongoClient = new MongoClient(new ServerAddress(host, port), clientOptions);
Examining mongoClient.getMongoClientOptions() after the above line of code clearly shows that the created client is faithful to the supplied config values. By contrast, if you do not set these values via MongoClientOptions then mongoClient.getMongoClientOptions() shows that the default values have been chosen.
Based on your updated comments I think the situation you are trying to cater for is this:
Creating a connection against a server instance which does not exists / is unavailable should fail sooner that the default of 30s.
If so then the configuration parameter you want to use is serverSelectionTimeout. The following invocation ...
MongoClientOptions clientOptions = MongoClientOptions.builder()
.serverSelectionTimeout(2000)
.build();
MongoClient mongoClient = new MongoClient(new ServerAddress(host, port), clientOptions);
... will cause this exception to be thrown:
com.mongodb.MongoTimeoutException: Timed out after 2000 ms while waiting to connect.
Note: serverSelectionTimeout is available in the version of the MongoDB Java driver which you are using (3.2.2 according to the comment you posted on your question).

Jongo connect to remote MongoDB server

Is it possible to connect to a remote MongoDB when using Jongo (jongo.org)?
I saw a piece of code where MongoClientURI was used like this:
MongoClientURI uri = new MongoClientURI("mongodb://IP_ADDRESS:27017/DB_NAME");
I have the following code:
if(client != null) {
db = client.getDatabase("StockApp");
database = client.getDB("StockApp");
jongo = new Jongo(database);
}
In this example, StockApp is the name of my database. It will connect to my local database (127.0.0.1:27017/StockApp). When I try to change StockApp to uri.getDatabase() in both lines, I get the following exception:
com.mongodb.MongoSocketOpenException: Exception opening socket
I can also see that it tries to connect to localhost (127.0.0.1).
When I change the uri to new MongoClientURI("IP_ADDRESS") or new MongoClientURI("IP_ADDRESS:27017) I get the error that the uri should start with mongodb://
Does anyone know if it is possible to connect to a remote MongoDB server using Jongo?
You can initialize Jongo from a MongoClient like this:
MongoClient mongoClient = new MongoClient("host", 27017);
DB db = mongoClient.getDB("theDB");
Jongo jongo = new Jongo(db);
You can check the MongoClient constructor detail here

Connect to MongoDb using X509 certificate

I am trying to connect to MongoDB using mongoX509. I am using mongo java driver 3.3.0 jar. In api reference I can see MongoCredential to pass subject name and authenticate but i am not able to import this in my code. When I decompile the jar I am not able to see MongoCredential as well.
Am I missing any dependencies. Is there any easy way to connect to Mongodb without using MongoCredential? The details i have is server, port and certificate subject name?
I can post the code I am trying if anyone wants to take a look at it as well
Thanks in Advance
Code - I am using SoapUI to run this code
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCredential;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
try{
def subjectName="CN=xx,OU=xx,O=xx,C=US,ST=CA,L=xx"
MongoCredential credential = MongoCredential.createMongoX509Credential(subjectName);
def URI = "mongodb://server1:27017,server2:27017,server3:27017/<<database>>?replicaSet=<<XYZ>>&authMechanism=MONGODB-X509&ssl=true"
MongoClientURI uri = new MongoClientURI(URI)
MongoClient client = new MongoClient(uri, Arrays.asList(credential));
DB database = client.getDB(<<database>>);
collection = database.isAuthenticated();
log.info collection
}
catch (Exception e){
log.info e
}
The issue was because of incorrect jar that I was using. I got the correct version and it worked.