Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get response json from Spring WebClient

I've been trying to follow the simplest tutorials out there for how to use WebClient, which I understand to be the next greatest thing compared to RestTemplate.

For example, https://www.baeldung.com/spring-5-webclient#4-getting-a-response

enter image description here

So when I try to do the same thing with https://petstore.swagger.io/v2/pet/findByStatus?status=available which is supposed to return some json,

WebClient webClient = WebClient.create();
webClient.get().uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available").exchange().block();

enter image description here

I have absolutely no idea how to proceed from the resultant DefaultClientResponse object. It shouldn't be this convoluted to arrive at the physical response body, but I digress.

How do I get the response body with the code I provided?

like image 641
notacorn Avatar asked Jul 09 '20 20:07

notacorn


People also ask

How do I get JSON response from WebClient?

You would just use bodyToMono which would return a Mono object. WebClient webClient = WebClient. create(); String responseJson = webClient. get() .

What is the difference between retrieve and exchange in WebClient?

The retrieve() method decodes the ClientResponse object and hands you the ready-made object for your use. It doesn't have a very nice api for handling exceptions. However on the other hand the exchange() method hands you the ClientResponse object itself along with the response status and headers.

Is WebClient better than RestTemplate?

Compared to RestTemplate , WebClient has a more functional feel and is fully reactive. Since Spring 5.0, RestTemplate is deprecated. It will probably stay for some more time but will not have major new features added going forward in future releases. So it's not advised to use RestTemplate in new code.


2 Answers

In the form you currently have it, and explaining the behaviour..

WebClient webClient = WebClient.create();
webClient.get()
         .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
         .exchange()
         .block();

the block() starts the request by internally synchronously subscribing to the Mono, and returns the resulting ClientResponse. You could also handle this asynchronously by calling subscribe() on the Mono returned by the exchange() method, instead of block().

In this current form, after the block() you now have all the metadata (ie. from the response header) about the response in a ClientResponse object, including the success status. This does not mean that the response body has finished coming through. If you don't care about the response payload, you could confirm the success and leave it at that.

If you further want to look at the response body, you need to convert the response body stream into some class. A this point you can decide whether you want to read everything into a single Mono with bodyToMono or into a stream of objects (Flux) with bodyToFlux, such as in the case where the response is a JSON array that can be parsed into individual separate Java objects.

However, in your case, you just want to see the JSON as-is. So converting to a String is sufficient. You would just use bodyToMono which would return a Mono object.

WebClient webClient = WebClient.create();
String responseJson = webClient.get()
                               .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
                               .exchange()
                               .block()
                               .bodyToMono(String.class)
                               .block();

Here you use block() to wait for the response payload to arrive and be parsed into a String, but you could also subscribe to the Mono to receive it reactively when it is complete.

One thing to note is that retrieve() can be used instead of exchange() to shortcut the ClientResponse. In this case you let default behavior handle error responses. Using exchange() puts all the responsibility on the application for responding to error responses on the ClientResponse. Read more in the Javadoc. The retrieve() version would look as follows. No need to block() as you only care about the response data.

WebClient webClient = WebClient.create();
String responseJson = webClient.get()
                               .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
                               .retrieve()
                               .bodyToMono(String.class)
                               .block();
like image 83
rewolf Avatar answered Oct 13 '22 01:10

rewolf


Here is how you make a request with RestTemplate

String json = new RestTemplate()
    .getForEntity("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
    .getBody();

Here is how you make a request with requests

import requests

json = requests.get("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
    .content

Here is how you make a request with WebClient

String json = WebClient.create()
    .get()
    .uri("https://petstore.swagger.io/v2/pet/findByStatus?status=available")
    .exchange()
    .block()
    .bodyToMono(String.class)
    .block();
like image 30
notacorn Avatar answered Oct 12 '22 23:10

notacorn