This article will teach you how to use MongoDB NoSQL database in the context of an Enterprise application. For the purpose of this example, we will deploy an example application on a Jakarta EE application server.
The most common way to connect to MongoDB from Java Enterprise applications is by means of the MongoDB Java Driver which provides a simple and clean interface to perform CRUD operations and advanced searches on your MongoDB documents.
MongoDB Driver also includes a standalone BSON library that you can use to build high-performance encoders and decoders without requiring the cooperation of a Map instance.
There are two versions of the Driver:
- The MongoDB Java Driver for synchronous Java applications
- The MongoDB Reactive Streams Driver to use the Reactive Streams API for asynchronous stream processing.
In this article, we will be using the MongoDB Java Driver for synchronous Java applications.
Starting Mongo DB
In order to run this tutorial you need MongoDB. Use any of the following options:
- Download and install MongoDB on your Machine from https://www.mongodb.com/try/download/community
- Use a Docker image to start MongoDB
To start MongoDB as Docker image, you can use the following docker-compose.yml file which contains the image reference as well as user/password credentials:
version: '3.1' services: myMongo: image: mongo restart: always environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example mongo-express: image: mongo-express restart: always ports: - 8081:8081 environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: example ME_CONFIG_MONGODB_URL: mongodb://root:example@myMongo:27017/
Start the docker deamon first:
service docker start
Then, launch docker-compose from the same location of your YML file:
docker-compose up
Coding the Enterprise application
Next step is to code our Enterprise application. We will be creating a REST application to access MongoDB Documents, therefore any web application archetype will be good:
mvn archetype:generate -DgroupId=org.acme -DartifactId=mongodb-demo -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
Next, add the dependencies for your application. You will need the Enterprise stack and MongoDB Driver:
<dependencies> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <scope>provided</scope> <version>${jakartaee.version}</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-driver-sync</artifactId> <version>4.7.1</version> </dependency> </dependencies>
Fix the jakartaee.version in a variable. For example:
<jakartaee.version>9.0.0</jakartaee.version>
Finally, if you are going to deploy this example on WildFly, we recommend adding the WildFly Maven plugin:
<plugin> <groupId>org.wildfly.plugins</groupId> <artifactId>wildfly-maven-plugin</artifactId> <version>2.0.0.Final</version> </plugin>
Connecting to MongoDB from Java
Firstly, we will be adding a CDI producer Bean which Produces a com.mongodb.client.MongoClient using the Factory method of the class com.mongodb.client.MongoClients:
@ApplicationScoped public class MongoDBProducer { @Produces public MongoClient createMongo() { return MongoClients.create("mongodb://root:[email protected]:27017/?maxPoolSize=20&w=majority"); } @Produces public MongoDatabase createDB(MongoClient client) { return client.getDatabase("testdb"); } public void close(@Disposes MongoClient toClose) { toClose.close(); } }
Most applications only require a single instance of a MongoClient, even across multiple threads. All resource usage limits, such as max connections, apply to individual MongoClient instances.
To connect to MongoDB, we need to use a connection URI which provides a set of instructions that the driver uses to connect to a MongoDB deployment. For example:
Coding the Model
MongoDB stores data records as BSON documents. In our example, we will be storing a collection of Customer Documents. Our Model will be the following minimal POJO Class:
public class Customer { public Customer() { } public Customer(Long id, String name, String surname) { super(); this.id = id; this.name = name; this.surname = surname; } private Long id; private String name; private String surname; // Getters/Setters omitted }
Coding the Service Class
In order to manage MongoDB Documents, we will need a Service Class that has access to the com.mongodb.client.MongoDatabase. The MongoDatabase is our gateway to the MongoDB Collection “customers“:
@ApplicationScoped public class CustomerService { @Inject MongoDatabase mongoDB; public List<Customer> list(){ List<Customer> list = new ArrayList<>(); try { Bson filter = Filters.empty(); getCollection().find(filter). forEach(doc -> list.add(new Customer(doc.getLong("id"), doc.getString("name"),doc.getString("surname")))); } catch (Exception exc ) { exc.printStackTrace(); } return list; } public void add(Customer customer){ Document document = new Document() .append("name", customer.getName()) .append("surname", customer.getSurname()) .append("id", customer.getId()); InsertOneResult result = getCollection().insertOne(document); System.out.println("Inserted a document with the following id: " + result.getInsertedId().asObjectId().getValue()); } public void update(Customer customer){ // update one document Bson filter = eq("id", customer.getId()); Bson updateOperation = set("name", customer.getName()); getCollection().updateOne(filter, updateOperation); } public void delete(Customer customer){ Bson filter = eq("id", customer.getId()); getCollection().deleteOne(filter); } private MongoCollection<Document> getCollection(){ return mongoDB.getCollection("customers"); } }
Coding the REST Endpoint
Finally, to make our Class accessible to Clients, we will add a REST Service which wraps the CustomerService with HTTP methods:
@Path("/customer") @Produces("application/json") @Consumes("application/json") public class CustomerEndpoint { @Inject CustomerService service; @GET public List<Customer> list() { return service.list(); } @POST public List<Customer> add(Customer customer) { service.add(customer); return list(); } @PUT public List<Customer> put(Customer customer) { service.update(customer); return list(); } @DELETE public List<Customer> delete(Customer customer) { service.delete(customer); return list(); } }
Our REST Service in turn needs a JAX-RS Activator:
@ApplicationPath("/rest") public class JaxRsActivator extends Application { }
Running the example
WildFly users can simply build and deploy the application as follows:
$ mvn install wildfly:deploy
As soon as the application is available, you will see in the server logs that the Connection producer kicked-in:
27017) Opened connection [connectionId{localValue:2, serverValue:2}] to 172.24.0.3:27017 17:07:05,150 INFO [org.mongodb.driver.cluster] (cluster-ClusterId{value='630e2799589b3f0449116034', description='null'}-172.24.0.3:27017) Monitor thread successfully connected to server with description ServerDescription{address=172.24.0.3:27017, type=STANDALONE, state=CONNECTED, ok=true, minWireVersion=0, maxWireVersion=13, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=16070627} 17:07:05,223 INFO [org.mongodb.driver.connection] (default task-1) Opened connection [connectionId{localValue:3, serverValue:4}] to 172.24.0.3:27017
Let’s begin by adding a new Document with an HTTP POST:
curl -X POST http://localhost:8080/mongoclient-wildfly/rest/customer -H 'Content-Type: application/json' -d '{"id":"1","name":"John","surname":"Smith"}'
Then, let’s check the list of Documents for the customers collections:
curl http://localhost:8080/mongoclient-wildfly/rest/customer
Which results in:
[{"id":1,"name":"John","surname":"Smith"}]
Besides, you can also check the available connections in the DB using the mongo client tool:
> show dbs admin 0.000GB config 0.000GB local 0.000GB testdb 0.000GB > use testdb switched to db testdb > db.customers.find() { "_id" : ObjectId("630e34a7095911151a09c344"), "name" : "John", "surname" : "Smith", "id" : NumberLong(1) }
Next, we can try to update the Resource with an HTTP PUT from the Command Line:
curl -X PUT http://localhost:8080/mongoclient-wildfly/rest/customer -H 'Content-Type: application/json' -d '{"id":1,"name":"Frank","surname":"Smith"}'
Finally, you can DELETE the Document as well
curl -X DELETE http://localhost:8080/mongoclient-wildfly/rest/customer -H 'Content-Type: application/json' -d '{"id":1,"name":"Frank","surname":"Smith"}'
Source code
The source code for the full MongoDB example is available here: https://github.com/fmarchioni/mastertheboss/tree/master/nosql/mongodb/mongoclient-wildfly