Reactive and Asynchronous APIs
Quarkus is reactive. If you look under the hood, you will find a reactive engine powering your Quarkus application. This engine is Eclipse Vert.x. Every IO interaction passes through the non-blocking and reactive Vert.x engine. All of the HTTP requests your application receives are handled by event loops (IO Thread) and then are routed towards the code that manages the request. Depending on the destination, it can invoke the code managing the request on a worker thread (Servlet, Jax-RS) or use the IO Thread (reactive route). Mutiny is a reactive programming library allowing to express and compose asynchronous actions.
Qute Templates can be asynchronously rendered as a CompletionStage
(completed with the rendered output asynchronously) or as Publisher
containing the rendered chunks.
If these are returned in an REST endpoint, the endpoint will be processed asynchronously, saving compute resources by not creating many threads to handle requests. Let's compare both types by creating a traditional (blocking) endpoint, and an async endpoint.
Quarkus Reactive routes propose an alternative approach to implement HTTP endpoints where you declare and chain routes. This approach became very popular in the JavaScript world, with frameworks like Express.Js or Hapi. Quarkus also offers the possibility to use reactive routes. You can implement REST API with routes only or combine them with JAX-RS resources and servlets.
Creating a Reactive Report Generator
During the project creation, you already added the quarkus-vertx-web
extension which provides the ability to declare Reactive Routes.
src/main/java/org/acme/ReactiveResource.java
with the following body:
package org.acme;
import io.quarkus.qute.Template;
import io.quarkus.qute.api.ResourcePath;
import io.quarkus.vertx.web.Route;
import io.quarkus.vertx.web.RoutingExchange;
import io.vertx.core.http.HttpMethod;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.core.MediaType;
@ApplicationScoped
public class ReactiveResource {
@Inject
SampleService service;
@ResourcePath("reports/v1/report_01.json.template")
Template report;
@Route(path = "/reactive", methods = HttpMethod.GET, produces = MediaType.APPLICATION_JSON)
void reactive(RoutingExchange ex) throws Exception {
report
.data("samples",service.get())
.data("now", java.time.LocalDateTime.now())
.renderAsync()
.thenAccept((val) -> ex.ok(val));
}
}
- The
@Route
annotation indicates that the method is a reactive route. Again, by default, the code contained in the method must not block. - Note the use of the Qute
renderAsync()
method. This method will be completed with the rendered template asynchronously. - The method gets a
RoutingExchange
object as a parameter.RoutingExchange
is a convenient wrapper ofRoutingContext
which provides a variety of useful methods. Using this object, you can retrieve the HTTP request (usingrequest()
) and write the response usingresponse().end()
.
RoutingContext
is available in the Vert.x Web documentation.Testing the Endpoint
The following command will access the endpoint and generate a report:
curl http://localhost:8080/reactive
ReactiveRoute
.Wrapping Up
Congratulations! Qute provides a powerful, flexible, type-safe and reactive way to render templates using ideas and mechanisms familiar to Java developers. To learn more about Qute, please refer to the Qute reference guide.