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.
 

Create a new file at 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));
    }
}
A few notes on this code:
  • 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 of RoutingContext which provides a variety of useful methods. Using this object, you can retrieve the HTTP request (using request()) and write the response using response().end().
More details about using the 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
You should see a random report of the samples from earlier, but done so with a 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.

Daniel Oh
Daniel Oh
Senior Principal Developer Advocate
Daniel Oh is a Senior Principal Developer Advocate at Red Hat. He works to evangelize building cloud-native microservices and serverless functions with cloud-native runtimes to developers. He also continues to contribute to various open-source cloud projects and ecosystems as a Cloud Native Computing Foundation (CNCF) ambassador for accelerating DevOps adoption in enterprises. Daniel also speaks at technical seminars, workshops, and meetups to elaborate on new emerging technologies for enterprise developers, SREs, platform engineers, and DevOps teams.