DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • GraphQL vs REST API: Which Is Better for Your Project in 2025?
  • Build a REST API With Just 2 Classes in Java and Quarkus
  • Efficient Data Management With Offset and Cursor-Based Pagination in Modern Applications
  • Building a MongoDB-Powered RESTful Application With Quarkus and Eclipse JNoSQL

Trending

  • PWA on iOS, Part 1: PWAs on the iPhone Are Older Than They Look
  • Article Moderation: Your Questions, Answered
  • How to Build Your Own AI SRE From Scratch
  • Frame Buffer Hashing for Visual Regression on Embedded Devices

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Invoking REST APIs Asynchronously With Quarkus

Invoking REST APIs Asynchronously With Quarkus

By 
Niklas Heidloff
·
Apr. 27, 20 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
17.7K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

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:

  • Eclipse MicroProfile REST Client
  • Eclipse Vert.x Axle Web Client

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 codeto invoke the articles service from the web-api service.

Java
 




x
37


 
1
import io.vertx.axle.core.Vertx;
2
import io.vertx.axle.ext.web.client.WebClient;
3
import io.vertx.ext.web.client.WebClientOptions;
4
import io.vertx.core.json.JsonObject;
5
import io.vertx.core.json.JsonArray;
6
import javax.annotation.PostConstruct;
7
import java.util.concurrent.CompletableFuture;
8
...
9
@Inject
10
Vertx vertx;
11
private WebClient client;
12
 
13
@PostConstruct
14
void initialize() {             
15
  this.client = WebClient.create(vertx, new WebClientOptions().setDefaultHost(ARTICLES_DNS).setDefaultPort(ARTICLES_PORT).setSsl(false));
16
}
17
 
18
public CompletableFuture<List<CoreArticle>> getArticlesReactiveVertxWebClient(int amount) {     
19
  CompletableFuture<List<CoreArticle>> future = new CompletableFuture<>();
20
  this.client.get("/v2/articles?amount=" + amount)
21
    .send()
22
    .toCompletableFuture() 
23
    .orTimeout(MAXIMAL_DURATION, TimeUnit.MILLISECONDS)
24
    .thenAccept(resp -> {
25
      if (resp.statusCode() == 200) {
26
        List<CoreArticle> articles = this.convertJsonToCoreArticleList(resp.bodyAsJsonArray());
27
        future.complete(articles);
28
      } else {
29
        future.completeExceptionally(new NoConnectivity());
30
      }
31
    })
32
    .exceptionally(throwable -> {
33
      future.completeExceptionally(new NoConnectivity());
34
      return null;
35
    });
36
    return future;
37
}



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:

Java
 




xxxxxxxxxx
1


 
1
import java.util.concurrent.CompletionStage;
2
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
3
...
4
@RegisterProvider(ExceptionMapperArticles.class)
5
public interface ArticlesServiceReactive {
6
  @GET
7
  @Produces(MediaType.APPLICATION_JSON)
8
  public CompletionStage<List<CoreArticle>> getArticlesFromService();
9
}



In this interface an exception mapper class is defined. This class maps HTTP errors to Java exceptions (see code):

Java
 




xxxxxxxxxx
1
17


 
1
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
2
...
3
@Provider
4
public class ExceptionMapperArticles implements ResponseExceptionMapper<InvalidArticle> {
5
  @Override
6
  public boolean handles(int status, MultivaluedMap<String, Object> headers) {
7
    return status == 204;
8
  }
9
  @Override
10
  public InvalidArticle toThrowable(Response response) {
11
    switch (response.getStatus()) {
12
      case 204:
13
        return new InvalidArticle();
14
      }
15
      return null;
16
    }
17
}



In order to invoke the REST API, a normal Java method can be called. The implementation of this method handles MicroProfile magically (see code):

Java
 




xxxxxxxxxx
1
21


 
1
public CompletableFuture<List<CoreArticle>> getArticlesReactive(int amount) {       
2
  CompletableFuture<List<CoreArticle>> future = new CompletableFuture<>();
3
  URL apiUrl;
4
  try {
5
    apiUrl = new URL("http://" + ARTICLES_DNS + ":" + ARTICLES_PORT + "/v2/articles?amount=" + amount);
6
    ArticlesServiceReactive articlesServiceReative = RestClientBuilder.newBuilder().baseUrl(apiUrl).build(ArticlesServiceReactive.class);
7
    articlesServiceReative.getArticlesFromService()
8
      .toCompletableFuture()
9
      .orTimeout(MAXIMAL_DURATION, TimeUnit.MILLISECONDS)   
10
      .thenAccept((articles) -> {
11
        future.complete(articles);
12
      })
13
      .exceptionally((throwable) -> {
14
        future.completeExceptionally(new NoConnectivity());
15
        return null;
16
      });
17
    } catch (MalformedURLException e) {
18
      future.completeExceptionally(new NoConnectivity());
19
    }
20
  return future;
21
}



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:

  • Development of Reactive Applications with Quarkus
  • Accessing Apache Kafka from Quarkus
  • Accessing PostgreSQL in Kubernetes from Quarkus
  • Reactive Messaging Examples for Quarkus
  • Developing reactive REST APIs with Quarkus
  • Comparing synchronous and asynchronous Access to Postgres
REST Web Protocols Quarkus

Published at DZone with permission of Niklas Heidloff. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • GraphQL vs REST API: Which Is Better for Your Project in 2025?
  • Build a REST API With Just 2 Classes in Java and Quarkus
  • Efficient Data Management With Offset and Cursor-Based Pagination in Modern Applications
  • Building a MongoDB-Powered RESTful Application With Quarkus and Eclipse JNoSQL

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook