Spring boot Webclient's retrieve vs exchange - spring-boot

I have started using WebClient in my Spring boot project recently.
Can somebody throw some light on the differences/usages between exchange and retrieve method in WebClient.
I undertand that exchange returns Mono<ClientResponse> and retrieve returns ResponseSpec, I just want to know when/why I should use each one of them.
Much Thanks.

Adding to #JArgente's answer.
According to the official documentation of the retrieve() method:
Perform the HTTP request and retrieve the response body.
...
This method is a shortcut to using exchange() and decoding the response body through
ClientResponse.
and the exchange() method
Perform the HTTP request and return a ClientResponse with the response status and headers. You can then use methods of the response to consume the body:
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. With exchange method you get fine grained control over your response objects and a better way to handle the response object and the exceptions.
If you just want to consume some api go with retrieve().
If you want a better control over your response objects, headers and exceptions, go with exchange().
Update 1
Starting from Spring 5.3, the exchange() method is deprecated due to possible memory/connection leaks. exchangeToMono() or exchangeToFlux() can be used instead.
Thanks #rhubarb for the update.

According to spring Webclient api documentation the difference between the two is that exchange retrieve in addition to the body other http response information like headers and status, while retrieve only returns body information.
So If you only need the body information you should use retrieve, because it is a shortcut for exchange and then get the body, but if you need other information like http status you must use exchange.

Related

Spring RestTemplate Response string is shorter than expected

I am trying to get an access token via RestTemplate.postForEntity().
myRestTemplate.postForEntity(authBaseUrl, request, Object.class);
I have a specific class for it, but let's use now a simple Object as type. It contains an access_token field.
It works, because I can get response, but the length if the access tokens (which is a string)
is 1196 character long. And I can get the same length in Postman too.
But if I use the intelliJ built-in REST client, the length is 1199.
Only the token from the intelliJ rest client works (So the longer).
Because I always get a new access token, it is impossible to get the same token twice.
How can I debug it?
What could be the problem?
Is the code that generates the response available to you? if so in your response add a header content-length so you can see what the server sent and what you received. Also, debug the server side and see what is being generated. In addition take another 3d party Http client and test it with this client see if you see a difference. The Http clients that you can try are Apache Http client, OK Http client, or my favorite - a very simplistic client written by me as part of my own Open Source MgntUtils library. Here is the Javadoc for my http client Here is a link to a similar question where you can get the references for any of above mentioned Http clients: How to check the status of POST endpoint/url in java

Why Rest End point is not showing any json data while using POST method in POSTMAN application?

I am trying to implement sample spring boot project and to ensure my endpoints are working properly, i'm using POSTMAN. When using POSTMAN , I am not able to see the response(i.e in Pretty) for a POST request. But the Status is 200 OK and I am able to see the result using GET request.
No Pretty response for POST request
GET Response ensuring that the previous POST request works fine
And my controller code is the following
#PostMapping("/message")
public Message createMessage(#RequestBody Message message)
{
return service.createMessage(message);
}
Can anyone help me to find out why I am not able to see the result while using POST method please?
Like Rafael says it is good to return a Response with the object entity. I haven't been working with Spring myself but with JavaEE and in JavaEE it is perfectly possible to return the object directly without using a Response. I use Responses anyways though, because it is much nicer to work with, and you can create your own custom responses and status codes.
Maybe check if your createUser service actually returns a message.
I don't know much about Spring, but usually what works for me is using a ResponseEntity as the object returned by the function. Also, maybe you should use #RestController as the annotation to your class controller
#PostMapping("/message")
public ResponseEntity<Message> createMessage(#RequestBody Message message)
{
Message msg = service.createMessage(message);
return ResponseEntity.ok(msg);
}

Spring PostMapping return 401 without body

I want to make a Post to write some data into the database, but all needed information is stored on the server, so my Post service requires no body:
#PostMapping("foo")
public #ResponseBody
RestResponse writeFoo() {
// WRITE AND RETURN
}
If I try to make a post request to this service I receive 401 even if I pass a valid token. If I change my exposed service to a GetMapping all works as expected. It seems that I can't manage a Post request with an empty body.
I've tried adding some fake parameters as
RestResponse writeFoo(#RequestBody(required = false) String fake)
but without success.
Any idea?
The issue you explain is most commonly the cause of bad (or missing?) configuration.
Pay attention that i.e. GET method is allowed by default by your REST API, while you need to specify other method types (i.e. PUT and POST), otherwise it won't work out of the box due to CORS.
The part where GET method works while POST method doesn't is a strong hint towards missing/incorrect CORS configuration. You can fix it quickly by adding some CORS filter and setup your response headers.
The official documentation should give you a good start, if you don't know where to look for: Spring docs - enabling CORS
UPDATE:
The issue is successfully resolved, check comments section for more info.
Short story - back-end configuration for CORS/CSRF token was set up correctly in this particular case, the issue occurred due to missing header (CSRF token) on the angular/front-end part of the webapp.

Spring MVC REST API: Invoke controller method programmatically given URL and JSON request body

I have a general REST API (developed using Spring MVC) that takes a list of API requests as its request body.
Each API request in the list has its own URL and request body.
In the implementation of this general REST API, I need to call the corresponding Spring controller method (in the same app) for each of these individual API requests (with their appropriate URL and request body).
(I will then merge all those individual API responses and return it in one big response from the general REST API).
I've been searching around, but I'm unclear how to programmatically call Spring to execute each individual API request. I would ideally like to get back the ResponseEntity from each call instead of the actual JSON response.
(More information:
On the same app server as the general API, I need to translate the URL and JSON request body for each individual API into the arguments to the controller method. I also need to take the URL and have Spring determine which controller method to invoke itself.)
Any help would be greatly appreciated.
Thanks,
Matt
Answer depend on whether the individual URLs that you are planning to invoke is with in the same server (Accessible without using network call) or not
If it is with in the same app server, spawn multiple threads and invoke the individual methods and join the response together and send it back
If it is not within the same app server, there are many Async Restclients are there besides spring's own webclient/restTemplate etc

Override response of POST in Django Rest Framework

I'm using Django Rest Framework's Generics (generics.ListCreateAPIView), when I make a POST request I get a response of Http code (200/400/..etc.) and a JSON showing the posted data, I need to know how can I override the response to get a custom response.
Note that I use
def perform_create(self,serializer):
return Response(<my response>)
to override the POST request handling but I still get the same response
The response from perform_create is ignored.
You'll likely want to override the create method using the mixins as example

Resources