2. Delivering ultra-fast persistence with well-designed Java microservices
2.1 Introduction
2.1.1 What you will learn
Here are the key learnings you will get with this hands-on exercise:
-
Learn how Microprofile empowers Java developers to quickly build and deliver microservices.
Info
The exercises are built on Helidon as the runtime, although other MicroProfile runtimes can be used to implement the same examples. E.g. WildFly, Open Liberty, Payara.
-
Explore the basic project structure of a MicroProfile-based Java microservice;
- Understand how architectural best practices allows the implementation decoupled code - domain logic and technical details are not tightened together;
- Learn how to add in-memory Java-native persistence;
- Know the capabilities that results from usage of specifications such as MicroProfile Config, CDI, JAX-RS and more;
- Experience the benefits of using a Java native persistence solution, such as easy data model mapping and manipulation;
2.2 Pre requisites
To be able to go through this guided exercise, you will need to have the following components in your dev environment:
- Have finished the steps described in Preparing your environment, especially the section Prepare-your-working-directory.
2.3 Hands-on practice
2.3.1 Getting started with MicroProfile
2.3.1.1 Explore the project
The projects have the following characteristics:
| Info | Details |
|---|---|
| MicroProfile Version | 3.3 |
| Build Tool | Maven |
| MicroProfile Runtime | Helidon |
The project's structures are similar to:
.
├── pom.xml
├── readme.md
└── src
└── main
├── java
│ └── org
│ └── a4j
│ └── ...(packages and classes)
│ └── resources
│ └── META-INF
│ ├── beans.xml
│ └── microprofile-config.properties
└── pom.xml
2.3.1.2 Package and run
-
Open the terminal and access the project's folder:
devoxx-be-2022/workshop-foundation/microprofile/ -
Run the following maven command. Maven will download the dependencies described in the project's
pom.xmlfile. It will also create an executable jar we can use to access our application:team.jar. -
Now, let's start the microservice. In the terminal, run the following command:
-
If everything goes well, you should see an output similar to:
bash 2022.10.11 02:34:00 INFO io.helidon.microprofile.server.ServerCdiExtension !thread!: Server started on http://localhost:8080 (and all other host addresses) in 2277 milliseconds (since JVM startup). 2022.10.11 02:34:00 INFO io.helidon.common.HelidonFeatures !thread!: Helidon MP 2.5.4 features:[CDI, Config, Fault Tolerance, Health, JAX-RS, Metrics, Open API, REST Client, Security, Server, Tracing] -
In your browser, access the page http://localhost:8080/data/hello
What are the classes that are responding to this request?
-
Now change the message that is displayed in this page to "Hello Devoxx Belgium!!!" .
Tip
In the class
org.a4j.workshop.HelloController, you'll find a GET endpoint that prints the message you saw in your browser. If you update it, package and run the application you should see the changes reflected on the page.When using helidon CLI and the Dev Loop, you should be able to visualize the change without the extra effort of manually re-packaging and running the service.
-
Package your application, start it again, and check the changes on the page.
Congratulations
You've successfully created, packaged, changed and accessed an application based on the MicroProfile specification and that runs with the Helidon runtime!
2.3.1.3 Going further
There are several cool capabilities - such as native compilation and the Helidon dev loop - that you can further explore. To know more about these topics, refer to the Learn More page.
2.3.2 MicroStream: using ultra-fast persistence
The project contains a data model and the respective classes required to manipulate these data:
* Data model: composed of the Player, Position and Team classes.
* Service classes: the layer that holds business rules. The TeamService is part of it.
* Endpoints: the REST API is exposed through the resource class, in this case, TeamResource.
Feel free to explore these classes before moving forward.
2.3.2.1 Add MicroStream to the project
-
To add MicroStream as the persistence solution of this microservice, we must add it as a maven dependency, so it gets included as a library when this project is build. Open the
pom.xmland add the following dependency: -
Next, we'll add Microstream's configuration. It relies on MicroProfile Config and has a very flexible and easy setup. Open
src/main/resources/META-INF/microprofile-config.properties:Tip
The property
one.microstream.storage.directoryindicates the folder where any data will be persisted. Filesystem is the default persistent storage target, although, it is not recommended for production. To learn about other storage targets check out the MicroStream documentation
2.3.2.2 Data mapping and storage configuration
-
Entity configurations:
Open the
Playerclass. In the JPA world, this would be considered an entity bean and would be mapped with @Entity`. With MicroStream, there is no need to annotate classes and map them to an existing database.If we were using JPA, we would also have to set the
@Idand@Columnin the attributes of the class.Good news: nothing needs to be changed on the data model!
-
Root and Storage: manipulating data gets very straightforward with MicroStream. The objects are serialized and saved in a graph structure, which means you don't have to worry with all the complex relations between classes. The key is to understand what is going to be your
rootnode.In our scenario, we have a team of players. In this case, we do not want to allow the user to manipulate players as an independent model, instead, every player is part of a team - in other words, it belongs to an object graph in which the
rootis the team.Once you identify what is going to be the
rootclass in your scenario, you then know which class you should configure with the@Storageannotation. Once you add the root node as a@Storage, CDI will take care of a lot of work under the covers. You won't have to deal with transaction managers, persistence context and so on. As of now, let's configure theTeamclass as ourroot:4.1. Open the
org.a4j.workshop.Teamclass, and annotate it with@Storage:
Next, you'll work on the methods that manipulates the data inside our service in-memory persistence storage.
2.3.2.3 Data manipulation
---- wip refer to the comments in the code
2.3.2.4 Methods that changes persisted data
--- wip: @store in class teamservice
2.3.3 Testing the service
- By default it will run on port 8081, as configured in the
microprofile-config.properties. -
Check the service implementation with the following request examples: ----- wip: atualizar os requests
- 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 this section's goals!
Congratulations!
You've finished your task! You have easily modified an existing project by taking advantadge of a well-defined persistence layer. You have used MicroStream to allow this service to persist its data using an ultra-fast in-memory solution. Well done!