Quarkus - Part 1
This post and the code used this book as a refence.
Overview
Quarkus is a runtime environment created by Red Hat in 2019 to fill the gaps regarding cloud environment costs and constraints such as slow startup time, heavy memory consumption and mutable environments.
The Quarkus is a cloud-native framework with built-in Kubernetes integration. The kubernate is the main platform to deploy the enterprise application. Beside the Kubernate, the technologies involved in Quarkus are Java, GraalVM, and Reactive Systems. Also, it supports some Jakarta EE and MicroProfile specifications. It is microservice-oriented.
Benefits:
- Integration with Docker and Kubernate: the application is in a docker container and run on Kubernetes
- Quick startup time: no additional class loading, runtime scanning, or other process done by JVM
- Low resident set size (RSS) memory: small, quick, and productive execution
- Increased developer productivity
- Fast-paced area of microservices and cloud-based applications
- Better scalability of the application
Concepts behind the Quarkus
Reactive: React is the idea to response something when is called.
- Reactive systems: Systems designed to react (e.g to a message, to a request). Principles: responsive, resilient, elastic (application to work with a variable number of instances) and message-driven.
- Reactive streams: Stream processing with non-blocking backpressure (restriction of the number of messages that a subscriber can accept). It is a low-level contract (Publisher, Subscriber, Subscription, Processor).
- Reactive programming: Programming model (based on Reactive streams) on which reactive systems depend on (e.g: validation, marshalling/unmarshallin JSON/XML, Injecting Dependencies, Qualifier, Interceptors).
Microprofile: Quarkus integrate Eclipse MicroProfile through SmallRye where are many microservices design patterns
- CDI (Context and Dependency Injection): it is a MicroProfile specification and makes the components injectable, interceptable and manageable bean. It uses scope and event management. The characteristic of having a low coupled is achived by the interceptors, decorators and events. Quarkus not implement all the CDI specification. CDI is runtime based. Managed Beans are container-managed objects that support resource injection, life cycle management and interception. The Container manage the bean. In Quarkus, is not necessary to use the annotation @Inject when use the constructor to injection. It's possible to use @Qualifier to distinguish between beans to be instanciate. The annotations are: @Inject and @ApplicationScope.
- JAX-RS: it is a specification that provides support for creating REST based web services.
- JSON-B: specification or Jackson project to marshall and unmarshall JSON documents from/to Java objects.
- JAX-B: specification to marshall and unmarshall XML documents from/to Java objects.
- JSON-P: it is a specification to allows JSON processing in Java.
- Fault Tolerance
- Health: provide information about their state to external viewers
- Metrics: export monitoring data to management agents
- OpenAPI: provides a Java API for to expose API documentation.
- REST Client: type safe approach using proxies and annotations for invoking RESTful services over HTTP
- JWT Auth: provides Role-Based Access Control (RBAC) using OpenID Connect (OIDC) and JSON Web Tokens (JWT).
Cloud Native Computing: build and run scalable applications in modern, dynamic environments.
Technologies: containers, microservices, serverless functions, service meshes and immutable infrastructure.
Startup
Scaffold
Quarkus gives a solid foundation to creating a project structure. You can use maven plugin to create a maven or gradle application, create by your IDE, and download from quarkus code page. So, you can create quarkus by command line or maven command.
- Maven
- Gradle
You can list all the extensions and install using this:
Launch dev mode
Quarkus gives the support to review the results after some change in the poject without repackage and redeploy the application (hot deployment). The changes to be detexted are Java files, application configs, and static resources.
Restful Service
The Quarkus give support to create REST API by JAX-RS framework. It uses RESTEasy and Vert.x by default. When the project is created the endpoint 'hello' and the test is given as example.
The project needs 'quarkus-resteasy-jsonb' or 'quarkus-resteasyjackson' extension to has a json response.
CORS
Quarkus also give support to Cross-Origin Resource Sharing (CORS) by use of quarkus.http.cors attribute inside of application.properties.
Route
For endpoints using reactive routes Quarkus uses 'io.vertx.ext.web.Router'. It can be done registering routes in classes or using annotation @Route. For extension is necessary to install it.
Quarkus HTTP is based on a nonblocking and reactive engine where event loop manage each request and handle the logic by worker theread (JAX-RS) I/O thread (reactive route).
The code you can see here.
Also, it's possible intercept request to manipulate the logic. I can be done with Verti.x or JAX-RS. This filter will be applied to JAX-RS resources and reactive routes.
The code you can see here.
Filter
It's possible apply the filter only to JAX-RS using ContainerRequestFilter or ContainerResponseFilter.
The code you can see here.
If necessary, in terms of security, you can use SSL to use certificate:
Event
The Event (javax.enterprise.event.Event) in Quarkus follow the observer pattern. The events in CDI are not treated asynchronously.
There are many ways to intercept the events and apply logic if necessary. One of that is when Quarkus fires CDI events at startup and shutdown of the application.
The code you can see here.
Or after the creation (@PostConstruct) of a component. The logic happens after the constructor is called and after the injections. Or before the destruction (@PreDestroy).
Configuration
The Quarkus can use application.properties/yaml to access the properties for the application. Those properties can be accessed by the class org.eclipse.microprofile.config.inject.ConfigProperty. The properties can be unic or a list.
If no profile is declarad so the property is use as default production mode. If not, Quarkus recognize different profiles for the environment: test, dev, prod (%{profile}.config.key=value.)
The configuration can be done by:
- System properties (-Dgreeting.message=Hello). System properties have more priority than environment variables
- Environment variables (GREETING_MESSAGEE=hello)
- Environment file named .env
- External config directory (config/application.properties)
- Resources src/main/resources/application.properties
PS: Eclipse MicroProfile Configuration has some default converters as boolean and Boolean that can has, e.g, true, 1, YES, Y, and ON to TRUE and FALSE to toher cases.
In the properties file is possible to define the log level as well.
Converter
The converters are very useful the get some data that comes from the endpoint and make it a known object.
The code you can see here.
The converter needs to be registered to be recognized by the application:
- create the file: META-INF/services/org.eclipse.microprofile.config.spi.Converter
- Content: org.acme.quickstart.domain.percentage.PercentageConverter
Validation
Quarkust allows use annotations to validate input and output Values of the REST. That's the bean validation. Also, the validation can be customized or even programmatically
The code you can see here.
Qualifier
The Qualifiers are resources to distinguish a resource. With this Quarkus can decide which object should be injected whitout ambiguite.
So, you there are two classes that implement the same interface Quarkus needs to know which class should be instanciate. CDI define it by the annotation @Retention(RUNTIME) and @javax.inject.Qualifier. Here are some examples how to do it.
The code you can see here.
Creating Interceptors
It is used to implement cross-cutting concerns, or manager data, e.g, to be handle in the same way. It involves an @InterceptorBinding (link the interceptor and the class/method to be intercepted), @AroundInvoke and @Interceptor.
The code you can see here.
Tests
For the tests, there is the annotation @QuarkusTest. This annotation make the use of the quarkus test framework. It use the port 8081, the test profile is activated.
- The Quarkus application is automatically started once and the test execution is started.
- Each test is executed against this running instance.
- The Quarkus application is stopped.