JerseyClient not throwing exception for 4xx and 5xx response - java

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.

Related

Receive Spring ResponseEntity with and without body

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
}

What is the purpose of the exchange method in the RestTemplate?

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.

Spring RestTemplate: How to reach state to check #is4xxClientError, instead of RestClientException 1st?

In my experience, after calling Spring's RestTemplate#exchange that subsequently receives '404 - Not Found' response, a RestClientException is thrown instead of returning a ResponseEntity that can have its status checked (i.e: with ResponseEntity#getStatusCode#is4xxClientError).
I don't understand why HttpStatus#is4xxClientError even exists if instead an Exception is thrown that prevents returning a ResponseEntity with HttpStatus to call #is4xxClientError on...
I'm reasonably convinced what I just described is the actual situation, because I can find other accounts on the internet that confirm that (i.e: Spring MVC - RestTemplate launch exception when http 404 happens).
How can I get to a state in Java code using RestTemplate where I can indeed check ResponseEntity#getStatusCode#is4xxClientError when RestTemplate#exchange receives 404, rather than being prevented by the RestClientException? Is it something to do with RestTemplate configuration?
Or am I correct that is not actually possible, and maybe the existence of ResponseEntity#getStatusCode#is4xxClientError is actually a 'bug'?
RestTemplate has a method
public void setErrorHandler(ResponseErrorHandler errorHandler);
And ResponseErrorHandler interface look like this.
public interface ResponseErrorHandler {
boolean hasError(ClientHttpResponse response) throws IOException;
void handleError(ClientHttpResponse response) throws IOException;
}
Whenever RestTemplate processes a response, it first call ResponseErrorHandler#hasError(), if it returns true, ResponseErrorHandler#handleError() is called which may throw exception.
If you don't set ResponseErrorHandler#setErrorHandler(), it defaults to DefaultResponseErrorHandler.java.
Default implementation treats 4xx / 5xx series status code as error and throws RestClientException (not this exception but subclasses of this exception).
You can always write your own ResponseErrorHandler and override the default behavior. So this way you can get a ResponseEntity object even in case of 4xx / 5xx (by writing your own implementation of ResponseErrorHandler and returning always false from the method hasError()).
Once you have ResponseEntity object, you can use ResponseEntity#getStatusCode()#is4xxClientError() method for the same purpose.

When HttpStatusCodeException exception raised?

when i use below code , what is the case to get HttpStatusCodeException exception .
ResponseEntity<Object> response =
restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, entity, Object.class);
Please can anyone help out ????????
According to documentation there are two types of HttpStatusCodeException HttpClientErrorException and HttpServerErrorException.
The former is thrown when an HTTP 4xx is received.
The latter is thrown when an HTTP 5xx is received.
so you can just use ResponseEntity.BodyBuilder.status(505) for example to raise an HttpServerErrorException in your
exhange(...) method of org.springframework.web.client.RestTemplate class was added in 3.1.0.RELEASE of spring-web library.
This method throws RestClientException which covers client (4_xx) and server (5_xx) side http code errors. But RestClientException doesn't offer getStatusCode(), getResponseAsString(), etc... methods.
HttpsStatusCodeException is the child of RestClientException which is doing same thing but with additional methods like getStatusCode(), getResponseAsString(), etc.
HttpClientErrorException child of HttpsStatusCodeException and only entertain client error (4_xx) not the server error.
HttpServerErrorException child of HttpsStatusCodeException and only entertain server error (5_xx) not the client error.
HTTP Status Codes are responses from the server, therefore if you have control of the server then you could make it return whichever errors you want. If you don't have control of the server then you could try sending bad/invalid requests so that the server will complain.
Something like this on your server side:
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity getAnError() {
// complain!
return ResponseEntity.status(HttpStatus.FORBIDDEN);
}

how can i return response status 405 with empty entity?

How can i return response status 405 with empty entity in java REST?
#POST
#Path("/path")
public Response createNullEntity() {
return Response.created(null).status(405).entity(null).build();
}
It returns status code 405, but the entity is not null, it is the http page for the error 405.
When you return an error status, Jersey delegates the response to your container's error processing via sendError. When sendError is called, the container will serve up an error page. This process is outlined in the Java Servlet Specification ยง10.9 Error Handling.
I suspect what you are seeing is your container's default error page for a 405 response. You could probably resolve your issue by specifying a custom error page (which could be empty). Alternatively, Jersey won't use sendError if you provide an entity in your response. You could give it an empty string like this:
#POST
#Path("/path")
public Response createNullEntity() {
return Response.status(405).entity("").build();
}
The above results in Content-Length of 0

Categories

Resources