Quarkus & Microprofile: How to make a Microservice with persistence
Today we are going to see a new way to make a microservice. This time using Quarkus and Microprofile. We will also add a small persistence layer.
We have already seen Quarkus integrated with Apache Camel, here, but today we will see it individually. Quarkus is a Java framework but Kubernetes-native, that is, optimized for use in Graalvm and its deployment through containers. And as this is the first time we do Quarkus on its own, we will start by showing how we can create a project, for this we will use the command:
mvn com.redhat.quarkus.platform:quarkus-maven-plugin:2.13.5.Final-redhat-00002:create \
-DprojectGroupId=com.home.example -DprojectArtifactId=ms-with-panache
And the main libraries to be used will be:
- REST: quarkus-resteasy-reactive
- Hibernate & Panache: quarkus-hibernate-orm-panache
- JSON: quarkus-resteasy-reactive-jackson
Microprofile use RestEasy, so if you have any experience the microservice generation part will be easy. But we will still give a small explanation of how to generate any method:
- @Path(“/book”): It allows us to indicate which is the root of the microservice, in which context it attends to calls. It is also used in each of the resources, if it has a different subsequent context.
- @GET, @DELETE…. : Indicates the HTTP verb with which we will make the invocation.
- @QueryParam : Allows us to indicate parameters that travel in the URL.
- @PathParam : Allows us to indicate parameters that are part of the context. They must be indicated in the @Path annotation.
- @Produces and @Consumes: Allows us to indicate the format of the output and the expected input.
If you still need it, here we made another post about RESTEasy.
For the persistence part we will use Panache, which will provide us with two different patterns to carry it out. On the one hand we will have the Repository pattern, where we will create an intermediate class that will be in charge of performing the operations against the database similar to Spring Data.
@ApplicationScoped
@Transactional
public class BookRepository implements PanacheRepository<Book>{ }
On the other hand, we will have the Active Record pattern, where the entity itself will provide the programmer with the different persistence methods.
@Entity
@Table(name = "BOARDGAME")
public class BoardGame extends PanacheEntity {
//warning with PanacheEntity we dont need getter/setter or Id
public String designer;
public String name;
}
Below is an example of everything together. In the Git repository you can see all the code.
@Path("/boardgame")
public class BoardGameResource {
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public BoardGame getBoardGameById(@PathParam("id") final Long id) {
return BoardGame.findById(id);
}
//warning: if we don put @Transactional generates an error
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
public BoardGame persist(final BoardGame newBoardGame) {
BoardGame.persist(newBoardGame);
return newBoardGame;
}
}
To be able to configure the different characteristics, we will be able to do it through the application.properties file. Here we indicate some of them:
- quarkus.http.port: We can indicate in which port the calls are allowed.
- quarkus.datasource.username/password/jdbc.url: We can indicate the connection to the DB.
- quarkus.hibernate-orm: It has multiple options to indicate if we want or not to generate the DB schema when starting the application and the files for it.
Once we have developed and configured the project, we will proceed to start it. As we are in development, we will use the command:
mvn quarkus:dev
Another point in favor of using Quarkus, is that we can easily reload the application and check the changes, simply by pressing the ‘s’ key in the console where we have it running.
I hope it has been useful, as always. And if you want to see all the code, it is here.