Quarkus - Part 2
This post and the code used this book as a refence.
The basic concepts you can see in Quarkus - Part 1.
Package | Persistence | FaultTolerance |
Observability | Kubernate | Authentication and Authorization |
Application Secrets Management | Reactive Programming Model | Conclusion |
Package
You can package the application to create, e.g., (1) a CLI application. For that, it's necessary to implements QuarkusApplication and create the main class identified by the annotation @QuarkusMain.
Another porpose is (2) to create an runnable JAR file. For that, it's necessary to use Quarkus Maven plug-in.
To build a container you can use Dockerfile.jvm. This file adds the lib directory and the runnable JAR.
Persistence
The persistence in some database is necesssary add the dependencies in POM file and the database configuration inside the application.properties. Here is an example using h2 database (in-memory). You Can configure more than one database. Fot that, you need to add an optional name to diferenciate the database.
An important feature is to ckeck the database health. You need to add an extension for it. Those extention do the check automatically. But it can be disabled.
Another important point when we talo about persistence is the transaction. Quarkus use the annotation @javax.transaction.Transactional from the extension quarkus-narayana-jta that is added when the persistence extensions are installed. This extensions add the annotation, TransactionManager and UserTransaction classes. The TransactionManager can be used if you need to manually roll back a transaction. The UserTransaction can be used if you need controler over the transaction (Methods: begin(), commit(), rollback(), setRollBackOnly(), getStatus(), setTrasanctio(int)). The transaction's context is propagated throught the calls inside the annotation. In the end, the trasanction do the commit.
The same way, You can use JPA with persistence.xml. The persistence unit has priority over other configurations such as the quarkus.hibernate-orm.* properties. So, you have to choose which one to use. To use entities from different JARs you can use an empty META-INF/beans.xml.
Beside the DAO (using Entity Manager) or repository pattern, a good alternative in quarkus to the persistence is to use Panache, an API build on top of JPA. A complete example you can see here
- Etension: quarkus-hibernate-orm-panache
- Create a class with the annotation @javax.persistence.Entity, and extending from PanacheEntity or PanacheEntityBase.
- Use PanacheEntityBase.findById(Object).
- For reposotory you need implements PanacheRepository (CDI bean)
And giving more support regarding persistence, Quarkus allow the use of the Flyway at start up or programmatically. The Flyway is the alternative to migrate the database schema.
At start-up
- Add the Flyway extension.
- Add the JDBC driver for your database.
- Setup the datasource(s).
- Add migrations to src/main/resources/db/migration.
- Set the quarkus.flyway.migrate-at-start to true.
Programmatically
Fault Tolerance
Quarkus, throught the MicroProfile, give support to retrieve automaticaly any CDI element in order to recover from some failure. The important part of fault-tolerance strategy is a fallback logic if the recovery is not possible.
An important point is that fault tolerance can be anable or disable globally or individually.
To use the MicroProfile Strageies is necessary add extensions and annotate class or method.
If you need to set the timeout to avoid wait for a service you can use the annotation @Timeout(value = 2000).
Also, you can limit the number of request using the Bulkhead Pattern.
This code is here.
Observability
Quarkus gives an API to check the state of service from another machine. For that, it is necessary to install the extension, which makes available two endpoints: Liveness URL and Readiness URL. The first one return 200 (service is UP), 503 (service is DOWN) and 500 (server error). The second one return 200 (service is UP and readu to process the requests), 503 (service unavailabe to receive requests) and 503 (server error).
The health check to database is created automatically when the Quarkus is used to use it. It can be disabled by properties attibutes such as explained in Persistence topic.
Also, it can be customized. You just need to implements the HealthCheck interface and set the class as Livenss or Readiness.
The Observability also allows expose metrics about the services to be used by some tool. It can be customized as well.
Other important feature available is monitoring a distributed application with distributed tracing. It can detect issues between the services. It can be done by extension as "quarkus-smallrye-opentracing or quarkus-tracing; or it can be customized to add some specific information.
Integrating with Kubernate
Kubernates is a plataform to deploy the applications. To deploy the application is necessary a pod.
- Pod: a working unit that represents a group of containers that are running in the same host machine and share resources like IP and ports
- It's necessary to build a container of the servie.
- Quarkus has extensions to Docker (quarkus-container-image-docker), Jib (quarkus-container-image-jib) and S2I (quarkus-container-image-s2i) to build and push the container
In Package you can see an example how to build a container with Docker and bellow how to push.
If you need to create automatically resources to Kubernate or OpenShift you can use the Quarkust extension:
Also, using the Kubernates extension, it is possible to use the ConfigMap to set some configurations read by the application by environment. Using MicroPorfile Config, the properties can be read using the @ConfigProperties annotation.
Authentication and Authorization
Quarkus has resourses to support this feature. One of them is the Authorization with MicroProfile JSON Web Token (JWT). It allows save a security context in REST, for instance. The MicroPrifile consume and validate the token that can transmit user name and the expiration info.
The section of the token are: Header (metadata), Claims (information), Signature. They are encoded to Base64. Here is an simple example shown only the mandatory attributes.
Application Secrets Management
Some data are confidential and need to be store in a secure place like Kubernate. Kubernate has an object called secret for that porpose. The data are encoded to Base64 and you can encrypt them. The Quarkus ggive support to that integration injecting the secret into container. It can be done by environment variable or volume.
Quarkus REST Clients
Now, to access external services the book gives some examples. One of them is using the client or MicroProfile Rest Client.
Also is possible to add attributes to the heater and send to the external service implementing the interface ClientHeadersFactory.
Developing Quarkus Application Using Spring APIs
Quarkus give support to the Spring libraries. You can use, for example, Spring DI and the application will have the same behave. The extenion to use Spring is "spring-di".
The book (Cap. 14) shows the equivalence between some annotations:
Spring | CDI/MicroProfile |
---|---|
@Autowired | @Inject |
@Qualifier | @Named |
@Value | @ConfigProperty |
@Component, @Service, @Repository | @Singleton |
@Configuration | @ApplicationScoped |
@Bean | @Produces |
@RequestMapping | @Path |
@PathVariable | @PathParam |
Reactive Programming Model
The Quarkus support asynchronous Http endpoint that can be done using the extension quarkus-smallrye-reactive-streams-operators to use native Streams or MicroProfile Reactive specification. For SmallRyeMultiny you can use quarkus-resteasy-mutiny.
Conclusion
It is a resource with many options and compatibilities. The decision about which one to use should be made after comparing it with Spring, for example, and seeing the benefits and team experience.
It is a really good book that gives an overview of the Quarkus. The knowledge should be complemented with the Quarkus documentation and experiences in projects.