If you have been any form of relational database management system for some time now, you have probably come across the name of MongoDB. First introduced in the year 2009, today mongoDb is one of the most popular relational database management systems in the industry. The main reason behind its insane popularity despite the presence of older relational database software managers like MySql present in the market is the wide of numbers and great versatility it brings to the table. The use of MongoDB eliminates many needs, one among them being the need to create a database and defining the data type every time a new project is started. Agenda of the MongoDB client article:
- Prerequisites for MongoDB Client
- Creating the project on Maven
- Adding your very first JSON rest service
- Configuring the MongoDB database
- Running the configured MongoDB database
- Making the front end
- Simplifying the MongoDB client using BSON codec
- Final Code
But to achieve the maximum functionality out of MongoDB, one needs to be familiar with the MongoDB client and in this article, we will discuss just that.
Prerequisites for MongoDB Client
In order for this article fully, you will need to first meet the following prerequisites.
Have an IDE already present in your system.
Java Development Kit or JDK version 1.8 and above installed with JAVA_HOME configured properly.
Docker or MongoDB installed.
Apache Maven version 3.5.3 and above.
The architecture that we have created and used in this guide is one of the simplest. When executed the user can easily add data and elements in a list, after which it will automatically get updated in the database.
Along with this, we have made sure that all the communication between the data and server is in JSON and all the data is stored in MongoDB.
In order to get started with this project, follow the steps outlined below.
Step #1: Creating the project on Maven
The first step is always to create a new project and in order to do this, make use of the following code.
mvn io.quarkus:quarkus-maven-plugin:0.22.0:create -DprojectGroupId=org.acme -DprojectArtifactId=using-mongodb-client -DclassName="org.acme.rest.json.FruitResource" -Dpath="/fruits" -Dextensions="resteasy-jsonb,mongodb-client"
When you run the above command, the IDE will import the JSON-B, MongoDb as well as RESTEasy/JAX-RS clients onto your system.
Moving on with Step 2.
Step #2: Adding your very first JSON rest service
In order to do this, use the code below. package org.acme.rest.json; import java.util.Objects; public class Fruit { private String name; private String description; public Fruit() { } public Fruit(String name, String description) { this.name = name; this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public boolean equals(Object obj) { if (!(obj instanceof Fruit)) { return false; } Fruit other = (Fruit) obj; return Objects.equals(other.name, this.name); } @Override public int hashCode() { return Objects.hash(this.name); } }
With the above example, we have first created the Fruit which will be later used in the program.
Next we need to create the org.acme.rest.json.FruitService file which will be the user layer of our application. In order to do this, use the code below.
package org.acme.rest.json; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import org.bson.Document; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import java.util.ArrayList; import java.util.List; @ApplicationScoped public class FruitService { @Inject MongoClient mongoClient; public List list(){ List list = new ArrayList<>(); MongoCursor cursor = getCollection().find().iterator(); try { while (cursor.hasNext()) { Document document = cursor.next(); Fruit fruit = new Fruit(); fruit.setName(document.getString("name")); fruit.setDescription(document.getString("description")); list.add(fruit); } } finally { cursor.close(); } return list; } public void add(Fruit fruit){ Document document = new Document() .append("name", fruit.getName()) .append("description", fruit.getDescription()); getCollection().insertOne(document); } private MongoCollection getCollection(){ return mongoClient.getDatabase("fruit").getCollection("fruit"); } } Now we need to edit the org.acme.rest.json.FruitResource class to suit our needs. In order to do this, use the code below. @Path("/fruits") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class FruitResource { @Inject FruitService fruitService; @GET public List list() { return fruitService.list(); } @POST public List add(Fruit fruit) { fruitService.add(fruit); return list(); } }
Step #3: Configuring the mongoDb database
The syntax as well as standard code for configuring the mongoDb database is as given below.
# configure the mongoDB client for a replica set of two nodes quarkus.mongodb.connection-string = mongodb://mongo1:27017,mongo2:27017
In our case, we will make use of the following code to configure the database.
# configure the mongoDB client for a replica set of two nodes quarkus.mongodb.connection-string = mongodb://localhost:27017
Step #4: Running the configured MongoDB database
The next step is to run the MongoDB database we just created. In order to do this, make use of the code below.
docker run -ti --rm -p 27017:27017 mongo:4.0
Step #5: Making the front end
Now that all the work at the backend of the application is done, let us take a look at the code used to code the front end of our application.
package org.acme.rest.json; import io.quarkus.mongodb.ReactiveMongoClient; import io.quarkus.mongodb.ReactiveMongoCollection; import org.bson.Document; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import java.util.List; import java.util.concurrent.CompletionStage; @ApplicationScoped public class ReactiveFruitService { @Inject ReactiveMongoClient mongoClient; public CompletionStage<List> list(){ return getCollection().find().map(doc -> { Fruit fruit = new Fruit(); fruit.setName(doc.getString("name")); fruit.setDescription(doc.getString("description")); return fruit; }).toList().run(); } public CompletionStage add(Fruit fruit){ Document document = new Document() .append("name", fruit.getName()) .append("description", fruit.getDescription()); return getCollection().insertOne(document); } private ReactiveMongoCollection getCollection(){ return mongoClient.getDatabase("fruit").getCollection("fruit"); } } package org.acme.rest.json; import javax.inject.Inject; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import java.util.List; import java.util.concurrent.CompletionStage; @Path("/reactive_fruits") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class ReactiveFruitResource { @Inject ReactiveFruitService fruitService; @GET public CompletionStage<List> list() { return fruitService.list(); } @POST public CompletionStage<List> add(Fruit fruit) { fruitService.add(fruit); return list(); } }
In the above example, we are making use of a reactive mongoDb client to facilitate the formation of the front end.
Moving on with Step 6.
Step #6: Simplifying the mongoDb client using BSON codec
In order to do this, make use of the code below.
package org.acme.rest.json.codec; import com.mongodb.MongoClient; import org.acme.rest.json.Fruit; import org.bson.*; import org.bson.codecs.Codec; import org.bson.codecs.CollectibleCodec; import org.bson.codecs.DecoderContext; import org.bson.codecs.EncoderContext; import java.util.UUID; public class FruitCodec implements CollectibleCodec { private final Codec documentCodec; public FruitCodec() { this.documentCodec = MongoClient.getDefaultCodecRegistry().get(Document.class); } @Override public void encode(BsonWriter writer, Fruit fruit, EncoderContext encoderContext) { Document doc = new Document(); doc.put("name", fruit.getName()); doc.put("description", fruit.getDescription()); documentCodec.encode(writer, doc, encoderContext); } @Override public Class getEncoderClass() { return Fruit.class; } @Override public Fruit generateIdIfAbsentFromDocument(Fruit document) { if (!documentHasId(document)) { document.setId(UUID.randomUUID().toString()); } return document; } @Override public boolean documentHasId(Fruit document) { return document.getId() != null; } @Override public BsonValue getDocumentId(Fruit document) { return new BsonString(document.getId()); } @Override public Fruit decode(BsonReader reader, DecoderContext decoderContext) { Document document = documentCodec.decode(reader, decoderContext); Fruit fruit = new Fruit(); if (document.getString("id") != null) { fruit.setId(document.getString("id")); } fruit.setName(document.getString("name")); fruit.setDescription(document.getString("description")); return fruit; } }
Now we will make use of a CodecProvider to link this to the Fruit class already present.
package org.acme.rest.json.codec; import org.acme.rest.json.Fruit; import org.bson.codecs.Codec; import org.bson.codecs.configuration.CodecProvider; import org.bson.codecs.configuration.CodecRegistry; public class FruitCodecProvider implements CodecProvider { @Override public Codec get(Class clazz, CodecRegistry registry) { if (clazz == Fruit.class) { return (Codec) new FruitCodec(); } return null; } }
Step #7: Final Code
The final code for this application, will look something like this.
package org.acme.rest.json; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import java.util.ArrayList; import java.util.List; @ApplicationScoped public class CodecFruitService { @Inject MongoClient mongoClient; public List list(){ List list = new ArrayList<>(); MongoCursor cursor = getCollection().find().iterator(); try { while (cursor.hasNext()) { list.add(cursor.next()); } } finally { cursor.close(); } return list; } public void add(Fruit fruit){ getCollection().insertOne(fruit); } private MongoCollection getCollection(){ return mongoClient.getDatabase("fruit").getCollection("fruit", Fruit.class); } }
Conclusion
Now you know how to configure and use the MongoDB client in your system. Go ahead and try these codes in your system and let us know your experience.
Article Summary
Learn all about the MongoDB client and how you can configure the same in your system for various uses. Read on to know more.
With this, we come to the end of the “MongoDB Client” article. If you want to start a career in the MongoDB field then check out this MongoDB Developer Certification Course
If you wish to learn Microsoft SQL Server and build a career in the relational databases, functions, and queries, variables etc domain, then check out our interactive, live-online Microsoft SQL Certification here, which comes with 24*7 support to guide you throughout your learning period.