

Invoking REST APIs asynchronously with Quarkus
source link: http://heidloff.net/article/invoking-rest-apis-asynchronously-with-quarkus/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Invoking REST APIs asynchronously with Quarkus
Recently I blogged about how to develop reactive REST APIs with Quarkus. Developing the actual endpoints asynchronously is the first step. To leverage reactive capabilities maximally though, the complete code path should be asynchronous, especially long lasting operations like database accesses and REST API invocations. This article describes two options how to invoke REST APIs asynchronously with Quarkus.
Two Options to invoke REST APIs asynchronously
Here are the two options:
The question is when to use which option. Rather than trying to answer this myself, let me refer to Clement Escoffier, the reactive expert in the Quarkus team. Clement answered this question on StackOverflow:
- The MicroProfile Rest Client is not non-blocking. The Vert.x web client is.
- If the rest of your code uses RX Java, the Vert.x client has a neat RX Java API.
- The MicroProfile Rest Client is using an annotation-driven approach, the Vert.x client is API-driven.
You can use both options in the same application which is what I’ve done in the sample application that is included in the cloud-native-starter project. The sample application uses several microservices. The web-api service invokes the articles service which I’ll describe below.

Eclipse Vert.x Axle Web Client
The Quarkus guide Using Eclipse Vert.x describes how to use the Vert.x client. Let’s take a look at the code to invoke the articles service from the web-api service.
import
io.vertx.axle.core.Vertx;
import
io.vertx.axle.ext.web.client.WebClient;
import
io.vertx.ext.web.client.WebClientOptions;
import
io.vertx.core.json.JsonObject;
import
io.vertx.core.json.JsonArray;
import
javax.annotation.PostConstruct;
import
java.util.concurrent.CompletableFuture;
...
@Inject
Vertx vertx;
private
WebClient client;
@PostConstruct
void
initialize() {
this
.client = WebClient.create(vertx,
new
WebClientOptions().setDefaultHost(ARTICLES_DNS).setDefaultPort(ARTICLES_PORT).setSsl(
false
));
}
public
CompletableFuture<List<CoreArticle>> getArticlesReactiveVertxWebClient(
int
amount) {
CompletableFuture<List<CoreArticle>> future =
new
CompletableFuture<>();
this
.client.get(
"/v2/articles?amount="
+ amount)
.send()
.toCompletableFuture()
.orTimeout(MAXIMAL_DURATION, TimeUnit.MILLISECONDS)
.thenAccept(resp -> {
if
(resp.statusCode() ==
200
) {
List<CoreArticle> articles =
this
.convertJsonToCoreArticleList(resp.bodyAsJsonArray());
future.complete(articles);
}
else
{
future.completeExceptionally(
new
NoConnectivity());
}
})
.exceptionally(throwable -> {
future.completeExceptionally(
new
NoConnectivity());
return
null
;
});
return
future;
}
The methods ‘get’ and ‘send’ invoke the HTTP request. I’ve explained in my previous article why ‘toCompletableFuture’ and ‘orTimeout’ or used.
Once the request has been completed, the HTTP status code has to be checked and converted into a Java exception. If the request has been successful, the response will be a io.vertx.core.json.JsonArray or io.vertx.core.json.JsonObject. These objects need to be converted manually into Java objects, in this example in a list of articles.
Eclipse MicroProfile REST Client
The second option is to use the MicroProfile REST Client. Check out my previous blog Invoking REST APIs from Java Microservices which explains how to invoke REST APIs synchronously.
The MicroProfile REST Client has been extended to also support asynchronous invocations. There is an OpenLiberty guide Consuming RESTful services asynchronously that describes this functionality.
Again, let’s take a look at the code. First you need to define an interface to the service you want to invoke:
import
java.util.concurrent.CompletionStage;
import
org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
...
@RegisterProvider
(ExceptionMapperArticles.
class
)
public
interface
ArticlesServiceReactive {
@GET
@Produces
(MediaType.APPLICATION_JSON)
public
CompletionStage<List<CoreArticle>> getArticlesFromService();
}
In this interface an exception mapper class is defined. This class maps HTTP errors to Java exceptions (see code):
import
org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
...
@Provider
public
class
ExceptionMapperArticles
implements
ResponseExceptionMapper<InvalidArticle> {
@Override
public
boolean
handles(
int
status, MultivaluedMap<String, Object> headers) {
return
status ==
204
;
}
@Override
public
InvalidArticle toThrowable(Response response) {
switch
(response.getStatus()) {
case
204
:
return
new
InvalidArticle();
}
return
null
;
}
}
In order to invoke the REST API, a normal Java method can be called. The implementation of this method handles MicroProfile magically (see code):
public
CompletableFuture<List<CoreArticle>> getArticlesReactive(
int
amount) {
CompletableFuture<List<CoreArticle>> future =
new
CompletableFuture<>();
URL apiUrl;
try
{
ArticlesServiceReactive articlesServiceReative = RestClientBuilder.newBuilder().baseUrl(apiUrl).build(ArticlesServiceReactive.
class
);
articlesServiceReative.getArticlesFromService()
.toCompletableFuture()
.orTimeout(MAXIMAL_DURATION, TimeUnit.MILLISECONDS)
.thenAccept((articles) -> {
future.complete(articles);
})
.exceptionally((throwable) -> {
future.completeExceptionally(
new
NoConnectivity());
return
null
;
});
}
catch
(MalformedURLException e) {
future.completeExceptionally(
new
NoConnectivity());
}
return
future;
}
Note that the deserialization of the JSON response into a list of articles is done automatically.
Closing Thoughts
My two cents: If you are not an experienced Rx Java developer, I’d go with MicroProfile for asynchronous REST invocations. The MicroProfile model is nicely designed, you don’t have to convert objects manually and it’s not blocking.
All samples of this article are included in the open source project cloud-native-starter. Check it out to see the code in action.
This article is part of a series. Read the other articles of this series to learn about reactive programming:
Share this:
Recommend
-
31
Previously I blogged about how to implement and document REST APIs in JavaEE applications with Eclipse Micr...
-
24
Learn more about building a REST API service with Quarkus. Quarkus is designed as a container-first framework optimized for...
-
6
Reactive REST with Quarkus made easy 24 November 2021 by F.Marchioni Quarkus JAX RS implementation has improved a lot since its first r...
-
12
Article Build a REST API from the ground up with Quarkus 2.0
-
4
REST API error modeling with Quarkus 2.0 Skip to main content In the
-
3
Blog Quarkus 2.8.0.Final released - New REST layer by default, GraalVM 22.0 and much more! April 12, 2...
-
10
ReactJS is a popular and widely used Javascript library for building rich user interfaces. this article shows how to consume Rest Services from a Quarkus application in a simple React front-end. Get...
-
5
Quarkus Defends REST APIs against Attack Oct 19, 2022 2 min...
-
7
REST Crud Application using Quarkus and Vue.js 25 January 2023 by F.Marchioni
-
8
Quarkus Reactive REST made easy 25 February 202325 February 2023 by F.Marchioni...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK