{
"_id": {
"$oid": "5dee6b079503234323db2ebc"
},
"Name": "Member1",
"Rank": "Captain",
"CrewID": "000001"
}
Contents
- What you’ll learn
- Additional prerequisites
- Getting started
- Providing a MongoDatabase
- Implementing the Create, Retrieve, Update, and Delete operations
- Configuring the MongoDB driver and the Liberty
- Running the application
- Testing the application
- Tearing down the environment
- Great work! You’re done!
- Related Links
- Guide Attribution
Tags
Persisting data with MongoDB
Prerequisites:
Learn how to persist data in your microservices to MongoDB, a document-oriented NoSQL database.
What you’ll learn
You will learn how to use MongoDB to build and test a simple microservice that manages the members of a crew. The microservice will respond to POST
, GET
, PUT
, and DELETE
requests that manipulate the database.
The crew members will be stored in MongoDB as documents in the following JSON format:
This microservice connects to MongoDB by using Transport Layer Security (TLS) and injects a MongoDatabase
instance into the service with a Contexts and Dependency Injection (CDI) producer. Additionally, MicroProfile Config is used to easily configure the MongoDB driver.
For more information about CDI and MicroProfile Config, see the guides on Injecting dependencies into microservices and Separating configuration from code in microservices.
Additional prerequisites
You will use Docker to run an instance of MongoDB for a fast installation and setup. Install Docker by following the instructions in the official Docker documentation, and start your Docker environment.
Getting started
The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:
git clone https://github.com/openliberty/guide-mongodb-intro.git
cd guide-mongodb-intro
The start
directory contains the starting project that you will build upon.
The finish
directory contains the finished project that you will build.
Before you begin, make sure you have all the necessary prerequisites.
Setting up MongoDB
This guide uses Docker to run an instance of MongoDB. A multi-stage Dockerfile is provided for you. This Dockerfile uses the mongo
image as the base image of the final stage and gathers the required configuration files. The resulting mongo
image runs in a Docker container, and you must set up a new database for the microservice. Lastly, the truststore that’s generated in the Docker image is copied from the container and placed into the Open Liberty configuration.
You can find more details and configuration options on the MongoDB website. For more information about the mongo
image, see mongo in Docker Hub.
Running MongoDB in a Docker container
Run the following commands to use the Dockerfile to build the image, run the image in a Docker container, and map port 27017
from the container to your host machine:
docker build -t mongo-sample -f assets/Dockerfile .
docker run --name mongo-guide -p 27017:27017 -d mongo-sample
Adding the truststore to the Open Liberty configuration
The truststore that’s created in the container needs to be added to the Open Liberty configuration so that the Liberty can trust the certificate that MongoDB presents when they connect. Run the following command to copy the truststore.p12
file from the container to the start
and finish
directories:
WINDOWS
MAC
LINUX
docker cp ^
mongo-guide:/home/mongodb/certs/truststore.p12 ^
start/src/main/liberty/config/resources/security
docker cp ^
mongo-guide:/home/mongodb/certs/truststore.p12 ^
finish/src/main/liberty/config/resources/security
docker cp \
mongo-guide:/home/mongodb/certs/truststore.p12 \
start/src/main/liberty/config/resources/security
docker cp \
mongo-guide:/home/mongodb/certs/truststore.p12 \
finish/src/main/liberty/config/resources/security
docker cp \
mongo-guide:/home/mongodb/certs/truststore.p12 \
start/src/main/liberty/config/resources/security
docker cp \
mongo-guide:/home/mongodb/certs/truststore.p12 \
finish/src/main/liberty/config/resources/security
Try what you’ll build
The finish
directory in the root of this guide contains the finished application. Give it a try before you proceed.
To try out the application, first go to the finish
directory and run the following Maven goal to build the application and deploy it to Open Liberty:
cd finish
mvn liberty:run
After you see the following message, your Liberty instance is ready:
The defaultServer server is ready to run a smarter planet.
You can now check out the service by going to the http://localhost:9080/mongo/ URL.
After you are finished checking out the application, stop the Liberty instance by pressing CTRL+C
in the command-line session where you ran Liberty. Alternatively, you can run the liberty:stop
goal from the finish
directory in another shell session:
mvn liberty:stop
Providing a MongoDatabase
Navigate to the start
directory to begin.
When you run Open Liberty in dev mode, dev mode listens for file changes and automatically recompiles and deploys your updates whenever you save a new change. Run the following goal to start Open Liberty in dev mode:
mvn liberty:dev
After you see the following message, your Liberty instance is ready in dev mode:
************************************************************** * Liberty is running in dev mode.
Dev mode holds your command-line session to listen for file changes. Open another command-line session to continue, or open the project in your editor.
With a CDI producer, you can easily provide a MongoDatabase
to your microservice.
Create theMongoProducer
class.src/main/java/io/openliberty/guides/mongo/MongoProducer.java
MongoProducer.java
microprofile-config.properties
pom.xml
server.xml
The values from the microprofile-config.properties
file are injected into the MongoProducer
class. The MongoProducer
class requires the following methods for the MongoClient
:
-
The
createMongo()
producer method returns an instance ofMongoClient
. In this method, the username, database name, and decoded password are passed into theMongoCredential.createCredential()
method to get an instance ofMongoCredential
. TheJSSEHelper
gets theSSLContext
from theoutboundSSLContext
in theserver.xml
configuration file. Then, aMongoClient
instance is created. -
The
createDB()
producer method returns an instance ofMongoDatabase
that depends on theMongoClient
. This method injects theMongoClient
in its parameters and passes the database name into theMongoClient.getDatabase()
method to get aMongoDatabase
instance. -
The
close()
method is a clean-up function for theMongoClient
that closes the connection to theMongoDatabase
instance.
Implementing the Create, Retrieve, Update, and Delete operations
You are going to implement the basic create, retrieve, update, and delete (CRUD) operations in the CrewService
class. The com.mongodb.client
and com.mongodb.client.result
packages are used to help implement these operations for the microservice. For more information about these packages, see the com.mongodb.client and com.mongodb.client.result Javadoc. For more information about creating a RESTful service with JAX-RS, JSON-B, and Open Liberty, see the guide on Creating a RESTful web serivce.
Create theCrewService
class.src/main/java/io/openliberty/guides/application/CrewService.java
CrewService.java
CrewMember.java
In this class, a Validator
is used to validate a CrewMember
before the database is updated. The CDI producer is used to inject a MongoDatabase
into the CrewService class.
Implementing the Create operation
The add()
method handles the implementation of the create operation. An instance of MongoCollection
is retrieved with the MongoDatabase.getCollection()
method. The Document
type parameter specifies that the Document
type is used to store data in the MongoCollection
. Each crew member is converted into a Document
, and the MongoCollection.insertOne()
method inserts a new crew member document.
Implementing the Retrieve operation
The retrieve()
method handles the implementation of the retrieve operation. The Crew
collection is retrieved with the MongoDatabase.getCollection()
method. Then, the MongoCollection.find()
method retrieves a FindIterable
object. This object is iterable for all the crew members documents in the collection, so each crew member document is concatenated into a String array and returned.
Implementing the Update operation
The update()
method handles the implementation of the update operation. After the Crew
collection is retrieved, a document is created with the specified object id
and is used to query the collection. Next, a new crew member Document
is created with the updated configuration. The MongoCollection.replaceOne()
method is called with the query and new crew member document. This method updates all of the matching queries with the new document. Because the object id
is unique in the Crew
collection, only one document is updated. The MongoCollection.replaceOne()
method also returns an UpdateResult
instance, which determines how many documents matched the query. If there are zero matches, then the object id
doesn’t exist.
Implementing the Delete operation
The remove()
method handles the implementation of the delete operation. After the Crew
collection is retrieved, a Document
is created with the specified object id
and is used to query the collection. Because the object id
is unique in the Crew
collection, only one document is deleted. After the document is deleted, the MongoCollection.deleteOne()
method returns a DeleteResult
instance, which determines how many documents were deleted. If zero documents were deleted, then the object id
doesn’t exist.
Configuring the MongoDB driver and the Liberty
MicroProfile Config makes configuring the MongoDB driver simple because all of the configuration can be set in one place and injected into the CDI producer.
Create the configuration file.
src/main/resources/META-INF/microprofile-config.properties
microprofile-config.properties
Values such as the hostname, port, and database name for the running MongoDB instance are set in this file. The user’s username and password are also set here. For added security, the password was encoded by using the securityUtility encode command.
To create a CDI producer for MongoDB and connect over TLS, the Open Liberty needs to be correctly configured.
Replace the Libertyserver.xml
configuration file.src/main/liberty/config/server.xml
server.xml
The features that are required to create the CDI producer for MongoDB are Contexts and Dependency Injection (cdi-4.0
), Secure Socket Layer (ssl-1.0
), MicroProfile Config (mpConfig-3.1
), and Password Utilities (passwordUtilities-1.1
). These features are specified in the featureManager
element. The Secure Socket Layer (SSL) context is configured in the server.xml
configuration file so that the application can connect to MongoDB with TLS. The keyStore
element points to the truststore.p12
keystore file that was created in one of the previous sections. The ssl
element specifies the defaultKeyStore
as the keystore and outboundTrustStore
as the truststore.
After you replace the server.xml
file, the Open Liberty configuration is automatically reloaded.
Running the application
You started the Open Liberty in dev mode at the beginning of the guide, so all the changes were automatically picked up.
Go to the http://localhost:9080/openapi/ui/ URL to see the OpenAPI user interface (UI) that provides API documentation and a client to test the API endpoints that you create after you see a message similar to the following example:
CWWKZ0001I: Application guide-mongodb-intro started in 5.715 seconds.
Try the Create operation
From the OpenAPI UI, test the create operation at the POST /api/crew
endpoint by using the following code as the request body:
{
"name": "Member1",
"rank": "Officer",
"crewID": "000001"
}
This request creates a new document in the Crew
collection with a name of Member1
, rank of Officer
, and crew ID of 000001
.
You’ll receive a response that contains the JSON object of the new crew member, as shown in the following example:
{
"Name": "Member1",
"Rank": "Officer",
"CrewID": "000001",
"_id": {
"$oid": "<<ID>>"
}
}
The <<ID>>
that you receive is a unique identifier in the collection. Save this value for future commands.
Try the Retrieve operation
From the OpenAPI UI, test the read operation at the GET /api/crew
endpoint. This request gets all crew member documents from the collection.
You’ll receive a response that contains an array of all the members in your crew. The response might include crew members that were created in the Try what you’ll build section of this guide:
[
{
"_id": {
"$oid": "<<ID>>"
},
"Name": "Member1",
"Rank": "Officer",
"CrewID": "000001"
}
]
Try the Update operation
From the OpenAPI UI, test the update operation at the PUT /api/crew/{id}
endpoint, where the {id}
parameter is the <<ID>>
that you saved from the create operation. Use the following code as the request body:
{
"name": "Member1",
"rank": "Captain",
"crewID": "000001"
}
This request updates the rank of the crew member that you created from Officer
to Captain
.
You’ll receive a response that contains the JSON object of the updated crew member, as shown in the following example:
{
"Name": "Member1",
"Rank": "Captain",
"CrewID": "000001",
"_id": {
"$oid": "<<ID>>"
}
}
Try the Delete operation
From the OpenAPI UI, test the delete operation at the DELETE/api/crew/{id}
endpoint, where the {id}
parameter is the <<ID>>
that you saved from the create operation. This request removes the document that contains the specified crew member object id
from the collection.
You’ll receive a response that contains the object id
of the deleted crew member, as shown in the following example:
{
"_id": {
"$oid": "<<ID>>"
}
}
Now, you can check out the microservice that you created by going to the http://localhost:9080/mongo/ URL.
Testing the application
Next, you’ll create integration tests to ensure that the basic operations you implemented function correctly.
Create theCrewServiceIT
class.src/test/java/it/io/openliberty/guides/application/CrewServiceIT.java
CrewServiceIT.java
The test methods are annotated with the @Test
annotation.
The following test cases are included in this class:
-
testAddCrewMember()
verifies that new members are correctly added to the database. -
testUpdateCrewMember()
verifies that a crew member’s information is correctly updated. -
testGetCrewMembers()
verifies that a list of crew members is returned by the microservice API. -
testDeleteCrewMember()
verifies that the crew members are correctly removed from the database.
Running the tests
Because you started Open Liberty in dev mode, you can run the tests by pressing the enter/return
key from the command-line session where you started dev mode.
You’ll see the following output:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.application.CrewServiceIT
=== Adding 2 crew members to the database. ===
=== Done. ===
=== Updating crew member with id 5df8e0a004ccc019976c7d0a. ===
=== Done. ===
=== Listing crew members from the database. ===
=== Done. There are 2 crew members. ===
=== Removing 2 crew members from the database. ===
=== Done. ===
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.411 s - in it.io.openliberty.guides.application.CrewServiceIT
Results:
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
Tearing down the environment
When you are done checking out the service, exit dev mode by pressing CTRL+C
in the command-line session where you ran Liberty.
Then, run the following commands to stop and remove the mongo-guide
container and to remove the mongo-sample
and mongo
images.
docker stop mongo-guide
docker rm mongo-guide
docker rmi mongo-sample
Great work! You’re done!
You’ve successfully accessed and persisted data to a MongoDB database from a Java microservice using Contexts and Dependency Injection (CDI) and MicroProfile Config with Open Liberty.
Related Links
Guide Attribution
Persisting data with MongoDB by Open Liberty is licensed under CC BY-ND 4.0
Prerequisites:
Nice work! Where to next?
What did you think of this guide?
Thank you for your feedback!
What could make this guide better?
Raise an issue to share feedback
Create a pull request to contribute to this guide
Need help?
Ask a question on Stack Overflow