How to implement a REST call which can sometimes return no body?
My SpringBoot application calls an external service over REST HTTP and its implemented via the org.springframework.web.client Client and method public <T> ResponseEntity<T> exchange.
The client received till now always a String body -> ResponseEntity<String>. Some time ago the service we are calling returns us HTTP 202 without body, so the following exception is thrown:
java.lang.IllegalArgumentException: argument "content" is null.
How can I tell Spring to ignore the body for a 202 status code?
You can use Void as the generic type parameter for ResponseEntity if the service does not return a response body:
ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Void.class)
If the service returns a response sometimes, you could handle the response as a String. For empty responses, you would receive an empty string. For non-empty responses, you would need to deserialize the returned payload yourself.
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class)
if (Strings.isEmpty(res.getBody())) {
// handle empty response
} else {
// handle non-empty response
}
Related
From my spring boot app I am making multiple calls to an API search service using the Spring Web Client. This is required due to pagination and multiple search params that cannot be used together.
When making calls with certain params I am getting HTTP 204 No Content, which is completely normal and expected. However this is causing an issue with decoding the body to my Response object
I am attempting to handle the 204 status in a filter but what I am doing seems a bit wonky and wondering how this should be handled. I am new to the reactive style but want to avoid using the deprecated RestTemplate style.
.builder()
.filter(WebClientFilter.handleError())
.filter(responseFilter)
.clientConnector(new ReactorClientHttpConnector(HttpClient.create().followRedirect(true)))
... default header stuff ommitted ...
.build().post().uri(searchServiceUrl)
.body(BodyInserters.fromValue(createsearchRequest()))
.retrieve()
.bodyToMono(SearchResponse.class)
.block();
Here is where I am filtering for the 204 and returning a newly constructed Response with my empty Dto. This just seems wrong that I am replacing the response from the server with my own, but if I do not do this the WebClient returns null causing other issues.
private static Mono<ClientResponse> exchangeFilterResponseProcessor(ClientResponse response) {
HttpStatus status = response.statusCode();
if (HttpStatus.NO_CONTENT.equals(status)) {
return response.bodyToMono(String.class).flatMap(body -> {
log.info("Body is {}" , body);
ClientResponse emptyResponse = ClientResponse.create(HttpStatus.OK)
.header(CONTENT_TYPE, "application/json")
.body(new SearchResponse().toString())
.build();
return Mono.just(emptyResponse);
});
}
return Mono.just(response);
}
Should I refactor the code to just allow the null response and deal with it that way vs trying to do it in the code above?
I am currently sending a resource to a client, I am using code that has been done already and I am modifying it, there is a line shown below in this code that I don't understand. Well I understand that I am sending or posting a resource, I understand this method takes the url of the client, that it takes the type of HTTP request for example in this case POST, but I dont understant why this method takes nService.getStringHttpEntityWithPayload(payLoad) and Resource.class? Also the response entity it is returning will it be a class only or a class with a status and a headers?
ResponseEntity<Resource> responseEntity = restTemplate.exchange(
eURL,
HttpMethod.POST,
nService.getStringHttpEntityWithPayload(payLoad),
Resource.class);
why this method takes nService.getStringHttpEntityWithPayload(payLoad) and Resource.class?
The method getStringHttpEntityWithPayload is returning a HttpEntity which is composed of a body and header data to be sent to a URL. The method is creating the request message by adding the content type header, letting the receiving service know that the body contains JSON data.
The parameter Resource.class is used to determine what class to deserialize the response body from the service into. It defines the generic type of the return value: ResponseEntity<Resource>.
Also the response entity it is returning will it be a class only or a class with a status and a headers?
I'm not sure what you mean by "class only". The ResponseEntity is similar to HttpEntity (in fact class ResponseEntity<T> extends HttpEntity<T>). The ResponseEntity class contains the response body and headers, as well as the HTTP Status code of the response.
I have a jersey client which calls an api whose return type is javax.ws.rs.core.Response as defined in the interface being used.
public Response getResponse(String id)
The response for a call has status as 'Server Error' but the client does not throw InternalServerException rather returns InboundJaxrsResponse.
On checking Jersey code I see that the JerseyInvocation class being used has the logic to check if response type is of javax.ws.rs.core.Response then to return an InboundJaxrsResponse object.
How can I get an appropriate exception as per the response status here?
PS: RestEasy client also has a similar logic.
With presume that you use <T> T get(Class<T> responseType) to get integer from an HTTP response body, exception that can be thrown if response status is not 2xx is WebApplicationException.
In your case, the second requirement of API contract is not fulfilled
WebApplicationException - in case the response status code of the
response returned by the server is not successful
and the specified response type is not Response.
I'm making a rest call to an endpoint that returns a multipart/mixed payload.
Here's the call using Spring's RestTemplate:
ResponseEntity<String> res = template.exchange(queryStr, HttpMethod.GET, entity, String.class);
I know I can get the entire body from the ResponseEntity as a String, but I don't want to have to manually parse it. Isn't there a more elegant way to handle the parsing of multipart/mixed. I've tried things like:
ResponseEntity<MultipartFile> res = template.exchange(queryStr, HttpMethod.GET, entity, MultipartFile.class);
but I get this exception:
org.springframework.web.client.RestClientException Could not extract response: no suitable HttpMessageConverter found for response type [interface org.springframework.web.multipart.MultipartFile] and content type [multipart/mixed;boundary=ML_BOUNDARY_10842596526049964806]
Thoughts?
I'm not familiar with Spring RestTemplate.
But for this project I have to use Spring RestTemplate to send a POST call to consume a rest api.
I'm using this code:
String restCall = restTemplate.postForObject(url+restParm, null, String.class);
This is working fine.
I would like to retriveve the HTTP status code (E.g: 200 OK.). How could I do that ?
Thanks.
You use the postForEntity method as follows...
ResponseEntity<String> response = restTemplate.postForEntity(url+restParm, null, String.class);
HttpStatus status = response.getStatusCode();
String restCall = response.getBody();
It will be pretty weird if RestTemplate couldn't get the response,as others have suggested. It is simply not true.
You just use the postForEntity method which returns a
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/http/ResponseEntity.html
And as the documentation suggests, the response entity has the status.