Anuja Barve
Anuja Barve

Reputation: 320

Making Async HTTP Call with Spring WebClient

I have a use case where I need to make HTTP calls from my service.I do not want my threads to blocked waiting for the response to come back . How can I do this in SpringWebClient ? This is how my code looks

public void asyncHttp(HTTPMethod method,
                        String url,
                        String body,
                        Map<String, String> headers){

    WebClient.UriSpec<WebClient.RequestBodySpec> uriSpec = webClient.method(method.getMethod());
    WebClient.RequestBodySpec bodySpec = uriSpec.uri(url);
    WebClient.RequestHeadersSpec<?> headersSpec = bodySpec.bodyValue(body);
    for(Map.Entry<String, String> entry : headers.entrySet()){
       headersSpec.header(entry.getKey(), entry.getValue());
    }
    Mono<JsonObject> responseMono =  headersSpec.retrieve().bodyToMono(JsonObject.class);
  }

I have two questions here

  1. How do I read the response from Mono only after it is completed and parse it. The thread should not wait for the Http Response, once the response is received it should be picked up by a thread.
  2. How do I set request specific timeout in the above code ?

Upvotes: 1

Views: 13089

Answers (1)

isank-a
isank-a

Reputation: 1675

Since your application is not completely reactive and you're using WebClient just to make HTTP calls, you can use Mono#toFuture(), Mono#SubscribeOn(), and Mono#timeout() for your use case

private CompletableFuture<Object> asyncHttpCall(HttpMethod httpMethod, String url, String body, Map<String, String> headers) {

    return WebClient.create(url).method(httpMethod).bodyValue(body).headers(httpHeaders -> headers.forEach(httpHeaders::add))
            .retrieve()
            .bodyToMono(Object.class)
            // specify timeout
            .timeout(Duration.ofSeconds(5L))
            // subscribe on a different thread from the given scheduler to avoid blocking as toFuture is a subscriber
            .subscribeOn(Schedulers.single())
            // subscribes to the mono and converts it to a completable future
            .toFuture();
}

// execute asyncHttpCall 
asyncHttpCall(HttpMethod.POST, "https://httpbin.org/post", "", Collections.emptyMap())
            // consume the response from the CompletableFuture
            .thenAccept(response -> System.out.println("response = " + response));

You can

Upvotes: 3

Related Questions