6. NoSQL persistence on Java services
In this exercise you can validate and practice your knowledge of the following concepts:
- Java microservice implementation with Helidon;
- Dev experience when using NoSQL databases with Java;
- Jakarta NoSQL;
- Implicit and constant usage of CDI;
Getting familiar with the use case and the exercise goals described next is highly recommended, as a detailed step-by-step guide is not provided.
Friendly advice: consider leveraging this opportunity to upskill by making the best use of your knowledge and research skills to code the solution without replicating the provided solution.
6.1 Scenario
Acme Store contacted you to ask for advise about NoSQL databases usage in MicroProfile-based services. They need a solution built on top of the RESTFul service delivered on the previous exercise. If you used the quickstart, by now you should have a microservice that relies on in-memory persistence with MicroStream. We will now add another option of persistence layer to this service, allowing it to persist data on MongoDB.
6.1.1 Goals
About the service:
- You should adapt an existing application, the
acme-store-rest
application. It uses Microprofile 3.3 + Helidon and MicroStream for persistence. - The service handles
Product
, and provides RESTFul operations for it:- List all products: GET "/products/"
- Find a product by ID: GET "/products/{productName}"
- Delete a product: DELETE "/products/{productName}"
- Update a product: PUT "/products/{productName}"
- Insert a product: POST "/products/{productName}"
- The APIs are documented with the Eclipse Microprofile-Open-API;
- It's persistence layer relies on MicroStream for performant in-memory persistence capabilities.
Goals:
- Add the support for persistence with JNoSQL for MongoDB;
- Change as minimum code as possible;
- Test the application;
6.2 How to get started
6.2.1 The database
This exercise requires a MongoDB instance. To facilitate you can use Docker.
If you don't have Docker installer yet, you can get it at: https://www.docker.com/
- Running MongoDB with Docker:
6.2.2 The project
You can use the delivered service you finished on the lab Golden APIs for ACME Store.
If you prefer, you can also start from this quickstart application. It's similar to a resulting application from the previous lab with extra instructions on what the required tasks:
To start the application, you can build, package and run it as usual.
6.3 Implementing the solution
See below a general guidance on how you can add NoSQL persistence to this service:
-
Dependencies: Add the Jakarta NoSQL dependencies to
pom.xml
: -
Database configurations: Add the MongoDB configurations to
microprofile-config.properties
: -
Entity configurations:
- Configure the
Product
as an entity bean: - Add the
@jakarta.nosql.mapping.Entity
declaration; - Add an empty constructor method;
g3. Annotate the attributes with adequate column configurations. Use
@Id
and@Column
. Remember, the attributes can no longer be final.
- Configure the
-
The document manager bean: In the package
org.a4j.product.infra
create a new classDocumentManagerProducer
:package org.a4j.product.infra; //TODO: Set this bean as ApplicationScope class DocumentManagerProducer { //TODO: Use CDI to inject this bean //TODO: Obtain the `document` value configured in microprofile-config.properties. Use @ConfigProperty. private DocumentCollectionManager manager; // TODO: Configure as a producer with @Produces public DocumentCollectionManager getManager() { return manager; } public void destroy(@Disposes DocumentCollectionManager manager) { manager.close(); } }
-
Creating a new repository: Add a new
ProductRepository
interface. It should extend theRepository
interface: -
Adjusting the resource class implementation:
- In the
ProductResource
, let's change the persistence layer. Replace the existing repository based onInventory
with our new oneProductResource
. - the following injection method as we're already injecting in the attribute level:
- In the
-
Adding a new method to the repository:: At this point, you will notice the code doesn't compile since the method
findAll
does not exist in the repository. Currently, (v1.0.0-b4) thejakarta. nosql.mapping.Repository
does not offer afindAll
out-of-the-box. It does offersave
,deleteById
,findById
,existsById
andcount
, therefore, the only method you need to att to theProductRepository
interface to deliver the existing endpoints is thegetAll
method. In theProductRepository
, add the method signature. Example:
6.3.1 Testing the service
- By default it will run on port 8081, as configured in the
microprofile-config.properties
. - Validate your APIs documentation with OpenAPI UI at: http://localhost:8081/openapi-ui/
-
Check the service implementation with the following request examples:
- Insert a new product
- List all products
- Search a product by ID (name)
- Update a product using its ID (name)
- Delete a product by ID (name)
-
If you can successfully execute the above items, it means you acomplished all this challenge goals!
Congratulations!
You've finished your task for Acme Store! You have easily modified an existing project by taking advantadge of a well-defined persistence layer. You have used JNoSQL to allow this service to persist its data using MongoDB. Well done!