How do you test listCollections in Mongo - java

I have a spring-boot project, with spring-data-mongo dependency. Everything is working great. I have a service which basically does a listCollections on one of the DB and clears the content of all the collections in that DB.
Code:
public void clearContentsOfAllCollections() {
MongoDatabase db = this.mongoTemplate.getMongoDbFactory().getDb("any-db-name");
LOGGER.info("=================================================================");
LOGGER.info("Clearing collections in DB - {}", db.getName());
MongoIterable<String> collectionNames = db.listCollectionNames();
for (final String collectionName : collectionNames) {
LOGGER.info("Clearing collection - {}", collectionName);
db.getCollection(collectionName).deleteMany(new Document());
}
LOGGER.info("Successfully cleared DB - {}", db.getName());
LOGGER.info("=================================================================");
}
When I try to write unit test, this is what I have
#Test
public void dropDBTest() {
SimpleMongoClientDbFactory simpleMongoClientDbFactory = Mockito.mock(SimpleMongoClientDbFactory.class);
MongoDatabase mongoDatabase = Mockito.mock(MongoDatabase.class);
Mockito.when(mongoTemplate.getMongoDbFactory()).thenReturn(simpleMongoClientDbFactory);
Mockito.when(simpleMongoClientDbFactory.getDb("db-name"))
.thenReturn(mongoDatabase);
// How do I convert this array list into a Mongo iterable
List<String> collectionList = Arrays.asList("collection-1", "collection-2");
}
The problem is - I do not know how I can return the content of collectionList, when I have to mock database.listCollectionNames() (from package com.mongodb.client).
Morever, the iterable.iterator() is of type MongoCursor. How do I test this? Am I missing something?

public class MongoDBTest {
#Test
public void testListCollectionNames() {
// Set up the mock MongoDatabase
MongoDatabase mockDatabase = Mockito.mock(MongoDatabase.class);
// Set up the mock MongoIterable<String>
MongoIterable<String> mockIterable = Mockito.mock(MongoIterable.class);
Mockito.when(mockDatabase.listCollectionNames()).thenReturn(mockIterable);
final var collectionNames = new ArrayList<>();
collectionNames.add("testCollection")
doReturn(collectionNames).when(mockIterable).into(new ArrayList<>());
// Get the list of collection names
List<String> collectionNames = mockDatabase.listCollectionNames().into(new ArrayList<>());
// Assert that the test collection is in the list
assertEquals(true, collectionNames.contains("testCollection"));
}
}

Related

Compile error when using Block<Document> to print collection using Java MongoDB 4.0.4 driver

When using Java MongoDB Driver 4.0.4, OpenJDK 11 and following the example on MongoDB docs, seeing a compile error when using findIterable.forEach(printBlock);
Also looks like com.mongodb.Block http://mongodb.github.io/mongo-java-driver/4.0/driver/tutorials/aggregation/ is not deprecated.
public String testLocal() {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("cord");
MongoCollection<Document> collection1 = database.getCollection("papers");
FindIterable<Document> findIterable = collection1.find(new Document());
findIterable.forEach(printBlock);
}
public Block<Document> printBlock = new Block<Document>() {
#Override
public void apply(final Document document) {
System.out.println(document.toJson());
}
};
Error:
[ERROR] /Projects/cord/src/main/java/com/engg/java/cord/services/PrimaryService_Local.java:
[24,30] incompatible types: com.mongodb.Block<org.bson.Document> cannot be converted
to java.util.function.Consumer<? super org.bson.Document>
The documentation obviously is outdated. If you look at the javadocs for FindIterable
(http://mongodb.github.io/mongo-java-driver/4.0/apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html) you'll see that forEach is inherited from java.lang.Iterable which takes a Consumer as a parameter, not a Block.
Thus, replace your printBlock declaration with:
public Consumer<Document> printBlock = document -> System.out.println(document.toJson());
... and all shall be fine.
With help from mtj and Mongodb support, adding working code blocks..
public String testLocal() {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("cord");
MongoCollection<Document> collection1 = database.getCollection("papers");
FindIterable<Document> findIterable = collection1.find(new Document());
findIterable.forEach((Consumer<Document>) d -> System.out.println( d.toJson()));
}
or
public Consumer<Document> printBlock = document -> System.out.println(document.toJson());
public String testLocal() {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("cord");
MongoCollection<Document> collection1 = database.getCollection("papers");
FindIterable<Document> findIterable = collection1.find(new Document());
findIterable.forEach(printBlock);
}
or with reference to https://jira.mongodb.org/browse/DOCS-13638
public String testLocal() {
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("cord");
MongoCollection<Document> collection1 = database.getCollection("papers");
FindIterable<Document> findIterable = collection1.find(new Document());
findIterable.forEach(printBlock);
}
Consumer<Document> printBlock = new Consumer<Document>() {
public void accept(final Document doc) {
System.out.println(doc.toJson());
};
};

How to create a method for a mongoDB connection, and write query in different method in Java?

I have created a method for MongoDB connection and I am able to print all document from the collection.
public static void connectMongowithURI_1() {
String db_name = "YYYY", db_col_name = "XXXX";
String client_url = "mongodb:localhost XXXXX";
MongoClientURI uri = new MongoClientURI(client_url);
// Connecting to the mongodb server using the given client uri.
MongoClient mongo_client = new MongoClient(uri);
// Fetching the database from the mongodb.
MongoDatabase db = mongo_client.getDatabase(db_name);
// Fetching the collection from the mongodb.
MongoCollection<Document> coll = db.getCollection(db_col_name);
//log.info("Fetching all documents from the collection");
System.out.println("Fetching all documents from the collection");
BasicDBObject whereQuery = new BasicDBObject();
whereQuery.put("SyncAccount.DataArea.GeneralInfo.AccountBusinessKey",101871);
//FindIterable<Document> cursor = coll.find(whereQuery);
// Performing a read operation on the collection.
FindIterable<Document> fi = coll.find(whereQuery);
MongoCursor<Document> cursor = fi.iterator();
try {
while(cursor.hasNext()) {
//log.info(cursor.next().toJson());
System.out.println(cursor.next().toJson());
}
} finally {
cursor.close();
}
}
But when I created two separated methods, one for to make a connection and another for to write query.
This method is for making connection to MongoDB.
public static MongoClient connectMongowithURI() {
String mongoURI = "mongodb: XXXYYY";
MongoClientURI uri = new MongoClientURI(mongoURI);
MongoClient mongoClient = new MongoClient(uri);
System.out.println("MongoDB is Connected");
return mongoClient;
}
This method is for the Write query. But This is not working. Can Anyone please help me to solve this problem.
public static void findAllDocument(String dataBaseName, String collectionName) {
MongoDatabase db = connectMongowithURI().getDatabase(dataBaseName);
System.out.println("Connected_1");
MongoCollection<Document> collection = db.getCollection(collectionName);
System.out.println("Connected_2");
BasicDBObject whereQuery = new BasicDBObject();
whereQuery.put("SyncAccount.DataArea.GeneralInfo.AccountBusinessKey",101871);
System.out.println("Connected_3");
//FindIterable<Document> cursor = coll.find(whereQuery);
// Performing a read operation on the collection.
FindIterable<Document> fi = collection.find(whereQuery);
System.out.println("Connected_5");
fi.noCursorTimeout(true); // ERROR MESSAGE GENERATE AFTER THIS LINE.
MongoCursor<Document> cursor = fi.iterator();
System.out.println("Connected_6");
try {
while(cursor.hasNext()) {
//log.info(cursor.next().toJson());
System.out.println(cursor.next().toJson());
}`enter code here`
} finally {
cursor.close();
}
}
Here is Exception: (Console report)
Exception in thread "main" com.mongodb.MongoQueryException: Query failed with error code 13 and error message 'not authorize. at com.mongodb.operation.FindOperation$1.call(FindOperation.java:735)
at com.mongodb.operation.FindOperation$1.call(FindOperation.java:725)
at com.mongodb.operation.OperationHelper.withReadConnectionSource(OperationHelper.java:463)
at com.mongodb.operation.FindOperation.execute(FindOperation.java:725)
at com.mongodb.operation.FindOperation.execute(FindOperation.java:89)
at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:189)
at com.mongodb.client.internal.MongoIterableImpl.execute(MongoIterableImpl.java:143)
at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:92)
at dB.connection.ConnectToMongoDB.findAllDocument(ConnectToMongoDB.java:80)
at dB.connection.ConnectToMongoDB.main(ConnectToMongoDB.java:21)

How to save an Object containing List of Objects in MongoDB collection

I have a Java Class named Status and it consists of 3 fields namely : String Email, String Status, ArrayList(Comment) commentList. Comment is another Java class consisting of 2 String field. I have worked with MySQL and i know how i could save this Status object in database table. Now i am learning MongoDB and i need this Status object to store in my db collection. How do i do it? As of now i have tried the following and failed to store the Status object. Can anyone please help me with it?
I have tried the following :
public static MongoClient getMongoConnection() {
MongoClient mongo = null;
try {
mongo = new MongoClient("localhost", 27017);
} catch (Exception e) {
e.printStackTrace();
}
return mongo;
}
public static void main(String[] args) {
MongoClient mongo = getMongoConnection();
DB db = mongo.getDB("myTestdatabase");
DBCollection myReviews = db.getCollection("myStatus");
BasicDBObject obj = new BasicDBObject();
List<Object> commentList = new BasicDBList();
commentList.add(new Comment("Looks like a nice status", "email#gmail.com"));
commentList.add(new Comment("This is a nice status", "email#gmail.com"));
Status status = new Status();
status.setStatus("This is my new Status");
status.setEmail("email#gmail.com");
obj.put("status", status.getStatus());
obj.put("email", status.getEmail());
obj.put("comments", commentList);
myReviews.insert(obj);
}
I get this error.
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.Comment.
mongo.getDB is depreciated. Use the below to create your DB. Make sure you import bson as well.
MongoClient mongo = new MongoClient("localhost", 27017);
MongoDatabase db = mongo.getDatabase("myDB");
MongoCollection items = db.getCollection("myCollection");
Document document = new Document(); // Create the document to be inserted to the DB
document.put("First Name", "John");
document.put("Last Name", "Smith");
items.insertOne(document); // Insert document to DB

Java: Mongo fails to assert the right number of documents inserted

I have a following test
#Test
public void testPutDocuments() throws Exception {
final DBObject document01 = new DBObject();
document01.put("uniqueId", "001");
document01.put("rv", "values");
document01.put("pv", "values");
final DBObject document02 = new DBObject();
document02.put("uniqueId", "002");
document02.put("rv", "values");
document02.put("pv", "values");
final DBObject document03 = new DBObject();
document03.put("uniqueId", "003");
document03.put("rv", "values");
document03.put("pv", "values");
final List<DBObject> documents = new ArrayList<DBObject>();
documents.add(document01);
documents.add(document02);
documents.add(document03);
mongoRule.getMongoService().putDocuments(documents);
assertEquals(3, mongoRule.getDatabase().getCollection("test").getCount());
}
Where mongoRule is a rule which connects to database, provides MongoService(a wrapper written to mongo client)
MongoService related methods
public void putDocument(#Nonnull final DBObject document) {
LOGGER.info("inserting document - " + document.get("uniqueId"));
mongo.getDB(database).getCollectionFromFull(getCollectionName(document)).insert(document);
}
public void putDocuments(#Nonnull final List<DBObject> documents) {
for (final DBObject document : documents) {
putDocument(document);
}
}
When I run this, I get
java.lang.AssertionError:
Expected :3
Actual :1
Now, if I do this
mongoRule.getMongoService().putDocuments(documents);
Thread.sleep(1000);
assertEquals(3, mongoRule.getDatabase().getCollection("contract").getCount());
I see no error.
Question:
a.) Why sleeping a thread for a second helped in getting a right number. isn't it a concurrency related issue? What if two threads are trying to put same documents where as document has to be unique.
b.) How can I fix this?
Thank you
answered here - https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/jyvMkDFVous

Convert DBObject to a POJO using MongoDB Java Driver

MongoDB seems to return BSON/JSON objects.
I thought that surely you'd be able to retrieve values as Strings, ints etc. which can then be saved as POJO.
I have a DBObject (instantiated as a BasicDBObject) as a result of iterating over a list ... (cur.next()).
Is the only way (other than using some sort of persistence framework) to get the data into a POJO to use a JSON serlialiser/deserialiser?
My method looks like this:
public List<User> findByEmail(String email){
DBCollection userColl;
try {
userColl = Dao.getDB().getCollection("users"); } catch (UnknownHostException e) { e.printStackTrace(); } catch (MongoException e) { e.printStackTrace();}
DBCursor cur = userColl.find();
List<User> usersWithMatchEmail = new ArrayList<User>();
while(cur.hasNext()) {
// this is where I want to convert cur.next() into a <User> POJO
usersWithMatchEmail.add(cur.next());
}
return null;
}
EDIT: It's pretty obvious, just do something like this.
Let Spring do the heavy lifting with the stuff it already has built for this...
The real trick is: mongoTemplate.getConverter().read(Foo.class, obj);
For example, when using a DBCursor -
while (cursor.hasNext()) {
DBObject obj = cursor.next();
Foo foo = mongoTemplate.getConverter().read(Foo.class, obj);
returnList.add(foo);
}
http://revelfire.com/spring-data-mongodb-convert-from-raw-query-dbobject/
There is a few java libs that can help you with it:
Morhpia - http://code.google.com/p/morphia/
Spring Data for MongoDB - http://www.springsource.org/spring-data/mongodb
Though a late answer , someone might find this useful.
I use GSON to convert from BasicDBObject to my own POJO which is TinyBlogDBObject
TinyBlogDBObject obj = convertJSONToPojo(cursor.next().toString());
private static TinyBlogDBObject convertJSONToPojo(String json){
Type type = new TypeToken< TinyBlogDBObject >(){}.getType();
return new Gson().fromJson(json, type);
}
1. Provide MongoDatabase bean with proper CodecRegistry
#Bean
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString("mongodb://username:password#127.0.0.1:27017/dbname");
ConnectionPoolSettings connectionPoolSettings = ConnectionPoolSettings.builder()
.minSize(2)
.maxSize(20)
.maxWaitQueueSize(100)
.maxConnectionIdleTime(60, TimeUnit.SECONDS)
.maxConnectionLifeTime(300, TimeUnit.SECONDS)
.build();
SocketSettings socketSettings = SocketSettings.builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.applyToConnectionPoolSettings(builder -> builder.applySettings(connectionPoolSettings))
.applyToSocketSettings(builder -> builder.applySettings(socketSettings))
.build();
return MongoClients.create(clientSettings);
}
#Bean
public MongoDatabase mongoDatabase(MongoClient mongoClient) {
CodecRegistry defaultCodecRegistry = MongoClientSettings.getDefaultCodecRegistry();
CodecRegistry fromProvider = CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build());
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(defaultCodecRegistry, fromProvider);
return mongoClient.getDatabase("dbname").withCodecRegistry(pojoCodecRegistry);
}
2. Annotate POJOS
public class ProductEntity {
#BsonProperty("name") public final String name;
#BsonProperty("description") public final String description;
#BsonProperty("thumb") public final ThumbEntity thumbEntity;
#BsonCreator
public ProductEntity(
#BsonProperty("name") String name,
#BsonProperty("description") String description,
#BsonProperty("thumb") ThumbEntity thumbEntity) {
this.name = name;
this.description = description;
this.thumbEntity = thumbEntity;
}
}
public class ThumbEntity {
#BsonProperty("width") public final Integer width;
#BsonProperty("height") public final Integer height;
#BsonProperty("url") public final String url;
#BsonCreator
public ThumbEntity(
#BsonProperty("width") Integer width,
#BsonProperty("height") Integer height,
#BsonProperty("url") String url) {
this.width = width;
this.height = height;
this.url = url;
}
}
3. Query mongoDB and obtain POJOS
MongoCollection<Document> collection = mongoDatabase.getCollection("product");
Document query = new Document();
List<ProductEntity> products = collection.find(query, ProductEntity.class).into(new ArrayList<>());
Please check my answer in other post
POJO to org.bson.Document and Vice Versa
You can use GSON library provided by Google. Here is the example of it. There are many other api that you can use to convert json into pojo like jettision api,etc.

Categories