How to identify response contenttype in Zuul filter? - spring-boot

I have created one filter in zuul service.
I am able to get the response status but I am not able to get the response contenttype.
Code:
public class UserEventFilter extends ZuulFilter {
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HttpServletResponse response = ctx.getResponse();
System.out.println("response status:" + response.getStatus());
System.out.println("response status:" + ctx.getResponseStatusCode());
System.out.println("response content type:" + response.getContentType());
try (final InputStream responseDataStream = ctx.getResponseDataStream()) {
final String responseData = CharStreams
.toString(new InputStreamReader(responseDataStream, Constants.ENCODING_UTF_8));
ctx.setResponseBody(responseData);
System.out.println("responseData:"+responseData);
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
response content type is giving null.
What I want to do is, I have to get the response body for all responses except if it is "application/octet-stream".

Try this:
RequestContext context = RequestContext.getCurrentContext();
List<Pair<String, String>> headers = context.getZuulResponseHeaders();
Than find content type there. You should override filterType method:
#Override
public String filterType() {
return POST_TYPE;
}
that is POST filter, if you want response I guess you are using post filter.

Related

Why do methods on #RestControllerAdvice class return HTML instead of JSON?

I have the following exception handler:
#RestControllerAdvice
#RequiredArgsConstructor
public class ControllerExceptionHandler {
#ExceptionHandler(FeignException.class)
#ResponseBody
public String afterThrowing(FeignException ex, HttpServletResponse response) {
response.setStatus(ex.status());
return ex.contentUTF8();
}
}
I would expect when the FeignException propagates to one of my REST controllers that
The afterThrowing method would be called
The response returned to an HTTP client would be JSON
The method is called but the content type returned to the client is HTML instead of JSON. How can I have JSON returned instead of HTML?
You should wrap your response with something(class or map).
Wrapper class :
public class ApiError {
private HttpStatus status;
private String response;
public ApiError(String response, HttpStatus status) {
this.response = s;
this.status = status;
}
// getter setter
}
And exception handler :
#ExceptionHandler(FeignException.class)
protected ResponseEntity<Object> handleFeignException(FeignException ex) {
ApiError apiError = new ApiError(ex.contentUTF8(), NOT_ACCEPTABLE);
return new ResponseEntity<>(apiError, apiError.getStatus());
}
For further reading you can check this question : How to return simple String as JSON in Rest Controller
Edit:
Since your ex.contentUTF8() call returns valid JSON you don't need to wrap it. Simply return String with ResponseEntity.
#ExceptionHandler(FeignException.class)
protected ResponseEntity<String> handleFeignException(FeignException ex) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<>(ex.contentUTF8(), headers, BAD_REQUEST);
}

Spring RestTemplate, getting junk response when http status code is 404

I am writing a rest proxy (it exposes the API and delegates call to other server) and it works fine for the normal case and also for 500 http status code, we get the response from the rest client.
But when we get 404 status code, the Rest API server returns the message but we get junk values from the RestTemplate. We need to pass the same response to other API user but cannot get the same response.
Message returned from REST API Server:
{
"status_code":"0",
"error":{
"code":"404",
"description":"Source not found"
}
}
Getting the below response by RestTemplate client:
Not able to paste the content, attaching the screen shot of the response.
Please see the code below.
#RequestMapping(value = "/api/**")
public #ResponseBody String apiProxy(#RequestBody String body, HttpMethod method, HttpServletRequest request,
HttpServletResponse response) throws URISyntaxException {
RestTemplate restTemplate = new RestTemplate(
new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setInterceptors(Collections.singletonList(new RestClientLoggingInterceptor()));
restTemplate.setErrorHandler(new CustomResponseErrorHandler());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders httpHeaders = new HttpHeaders();
Enumeration<String> headers = request.getHeaderNames();
String headerName = null;
String headerValue = null;
while (headers.hasMoreElements()) {
headerName = headers.nextElement();
headerValue = request.getHeader(headerName);
httpHeaders.set(headerName, headerValue);
}
HttpEntity<String> httpEntity = new HttpEntity<String>(body, httpHeaders);
URI uri = new URI(ServerProtocol, null, ServerDomain, Integer.valueOf(ServerPort),
request.getRequestURI(), request.getQueryString(), null);
ResponseEntity<String> responseEntity = null;
try {
responseEntity = restTemplate.exchange(uri, method, httpEntity, String.class);
} catch (RestClientResponseException e) {
response.setStatus(e.getRawStatusCode());
return e.getResponseBodyAsString();
}
response.setStatus(responseEntity.getStatusCode().value());
return responseEntity.getBody();
}
ResponseErrorHandler Class
public class CustomResponseErrorHandler extends DefaultResponseErrorHandler {
private static final Logger logger = LogManager.getLogger(CustomResponseErrorHandler.class);
#Override
public void handleError(ClientHttpResponse response) throws IOException {
logger.error("Response error: {} {}", response.getStatusCode(), response.getStatusText());
}
}
RestClientLoggingInterceptor Class
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
ClientHttpResponse response = execution.execute(request, body);
logger.debug("request method:" + request.getMethod());
logger.debug("request URI:" + request.getURI());
logger.debug("request headers:" + request.getHeaders());
logger.debug("request body:" + new String(body, Charset.forName("UTF-8")));
logger.debug("response status code:" + response.getStatusCode());
logger.debug("response headers:" + response.getHeaders());
logger.debug("response body:" + IOUtils.toString(response.getBody(), "UTF-8"));
return response;
}
Thanks
Cannot parse gzip encoded response with RestTemplate from Spring-Web
This was helpful to me for this same issue. You can try this out.

Spring Resttemplate exception handling

Below is the code snippet; basically, I am trying to propagate the exception when the error code is anything other than 200.
ResponseEntity<Object> response = restTemplate.exchange(url.toString().replace("{version}", version),
HttpMethod.POST, entity, Object.class);
if(response.getStatusCode().value()!= 200){
logger.debug("Encountered Error while Calling API");
throw new ApplicationException();
}
However in the case of a 500 response from the server I am getting the exception
org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
Do I really need to wrap the rest template exchange method in try? What would then be the purpose of codes?
You want to create a class that implements ResponseErrorHandler and then use an instance of it to set the error handling of your rest template:
public class MyErrorHandler implements ResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
// your error handling here
}
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
...
}
}
[...]
public static void main(String args[]) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyErrorHandler());
}
Also, Spring has the class DefaultResponseErrorHandler, which you can extend instead of implementing the interface, in case you only want to override the handleError method.
public class MyErrorHandler extends DefaultResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
// your error handling here
}
}
Take a look at its source code to have an idea of how Spring handles HTTP errors.
Spring cleverly treats http error codes as exceptions, and assumes that your exception handling code has the context to handle the error. To get exchange to function as you would expect it, do this:
try {
return restTemplate.exchange(url, httpMethod, httpEntity, String.class);
} catch(HttpStatusCodeException e) {
return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders())
.body(e.getResponseBodyAsString());
}
This will return all the expected results from the response.
You should catch a HttpStatusCodeException exception:
try {
restTemplate.exchange(...);
} catch (HttpStatusCodeException exception) {
int statusCode = exception.getStatusCode().value();
...
}
Another solution is the one described here at the end of this post by "enlian":
http://springinpractice.com/2013/10/07/handling-json-error-object-responses-with-springs-resttemplate
try{
restTemplate.exchange(...)
} catch(HttpStatusCodeException e){
String errorpayload = e.getResponseBodyAsString();
//do whatever you want
} catch(RestClientException e){
//no response payload, tell the user sth else
}
Spring abstracts you from the very very very large list of http status code. That is the idea of the exceptions. Take a look into org.springframework.web.client.RestClientException hierarchy:
You have a bunch of classes to map the most common situations when dealing with http responses. The http codes list is really large, you won't want write code to handle each situation. But for example, take a look into the HttpClientErrorException sub-hierarchy. You have a single exception to map any 4xx kind of error. If you need to go deep, then you can. But with just catching HttpClientErrorException, you can handle any situation where bad data was provided to the service.
The DefaultResponseErrorHandler is really simple and solid. If the response status code is not from the family of 2xx, it just returns true for the hasError method.
I have handled this as below:
try {
response = restTemplate.postForEntity(requestUrl, new HttpEntity<>(requestBody, headers), String.class);
} catch (HttpStatusCodeException ex) {
response = new ResponseEntity<String>(ex.getResponseBodyAsString(), ex.getResponseHeaders(), ex.getStatusCode());
}
A very simple solution can be:
try {
requestEntity = RequestEntity
.get(new URI("user String"));
return restTemplate.exchange(requestEntity, String.class);
} catch (RestClientResponseException e) {
return ResponseEntity.status(e.getRawStatusCode()).body(e.getResponseBodyAsString());
}
If you use pooling (http client factory) or load balancing (eureka) mechanism with your RestTemplate, you will not have the luxury of creating a new RestTemplate per class. If you are calling more than one service you cannot use setErrorHandler because if would be globally used for all your requests.
In this case, catching the HttpStatusCodeException seems to be the better option.
The only other option you have is to define multiple RestTemplate instances using the #Qualifier annotation.
Also - but this is my own taste - I like my error handling snuggled tightly to my calls.
The code of exchange is below:
public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException
Exception RestClientException has HttpClientErrorException and HttpStatusCodeException exception.
So in RestTemplete there may occure HttpClientErrorException and HttpStatusCodeException exception.
In exception object you can get exact error message using this way: exception.getResponseBodyAsString()
Here is the example code:
public Object callToRestService(HttpMethod httpMethod, String url, Object requestObject, Class<?> responseObject) {
printLog( "Url : " + url);
printLog( "callToRestService Request : " + new GsonBuilder().setPrettyPrinting().create().toJson(requestObject));
try {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> entity = new HttpEntity<>(requestObject, requestHeaders);
long start = System.currentTimeMillis();
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
printLog( "callToRestService Status : " + responseEntity.getStatusCodeValue());
printLog( "callToRestService Body : " + new GsonBuilder().setPrettyPrinting().create().toJson(responseEntity.getBody()));
long elapsedTime = System.currentTimeMillis() - start;
printLog( "callToRestService Execution time: " + elapsedTime + " Milliseconds)");
if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) {
return responseEntity.getBody();
}
} catch (HttpClientErrorException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}catch (HttpStatusCodeException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}
return null;
}
Here is the code description:
In this method you have to pass request and response class. This method will automatically parse response as requested object.
First of All you have to add message converter.
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
Then you have to add requestHeader.
Here is the code:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> entity = new HttpEntity<>(requestObject, requestHeaders);
Finally, you have to call exchange method:
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
For prety printing i used Gson library.
here is the gradle : compile 'com.google.code.gson:gson:2.4'
You can just call the bellow code to get response:
ResponseObject response=new RestExample().callToRestService(HttpMethod.POST,"URL_HERE",new RequestObject(),ResponseObject.class);
Here is the full working code:
import com.google.gson.GsonBuilder;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
public class RestExample {
public RestExample() {
}
public Object callToRestService(HttpMethod httpMethod, String url, Object requestObject, Class<?> responseObject) {
printLog( "Url : " + url);
printLog( "callToRestService Request : " + new GsonBuilder().setPrettyPrinting().create().toJson(requestObject));
try {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> entity = new HttpEntity<>(requestObject, requestHeaders);
long start = System.currentTimeMillis();
ResponseEntity<?> responseEntity = restTemplate.exchange(url, httpMethod, entity, responseObject);
printLog( "callToRestService Status : " + responseEntity.getStatusCodeValue());
printLog( "callToRestService Body : " + new GsonBuilder().setPrettyPrinting().create().toJson(responseEntity.getBody()));
long elapsedTime = System.currentTimeMillis() - start;
printLog( "callToRestService Execution time: " + elapsedTime + " Milliseconds)");
if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) {
return responseEntity.getBody();
}
} catch (HttpClientErrorException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}catch (HttpStatusCodeException exception) {
printLog( "callToRestService Error :" + exception.getResponseBodyAsString());
//Handle exception here
}
return null;
}
private void printLog(String message){
System.out.println(message);
}
}
Thanks :)
To extedend #carcaret answer a bit....
Consider your response errors are returned by json message. For example the API may return 204 as status code error and a json message as error list. In this case you need to define which messages should spring consider as error and how to consume them.
As a sample your API may return some thing like this, if error happens:
{ "errorCode":"TSC100" , "errorMessage":"The foo bar error happend" , "requestTime" : "202112827733" .... }
To consume above json and throw a custom exception, you can do as below:
First define a class for mapping error ro object
//just to map the json to object
public class ServiceErrorResponse implements Serializable {
//setter and getters
private Object errorMessage;
private String errorCode;
private String requestTime;
}
Now define the error handler:
public class ServiceResponseErrorHandler implements ResponseErrorHandler {
private List<HttpMessageConverter<?>> messageConverters;
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return (response.getStatusCode().is4xxClientError() ||
response.getStatusCode().is5xxServerError());
}
#Override
public void handleError(ClientHttpResponse response) throws IOException {
#SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<ServiceErrorResponse> errorMessageExtractor =
new HttpMessageConverterExtractor(ServiceErrorResponse.class, messageConverters);
ServiceErrorResponse errorObject = errorMessageExtractor.extractData(response);
throw new ResponseEntityErrorException(
ResponseEntity.status(response.getRawStatusCode())
.headers(response.getHeaders())
.body(errorObject)
);
}
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
}
The custom Exception will be:
public class ResponseEntityErrorException extends RuntimeException {
private ResponseEntity<ServiceErrorResponse> serviceErrorResponseResponse;
public ResponseEntityErrorException(ResponseEntity<ServiceErrorResponse> serviceErrorResponseResponse) {
this.serviceErrorResponseResponse = serviceErrorResponseResponse;
}
public ResponseEntity<ServiceErrorResponse> getServiceErrorResponseResponse() {
return serviceErrorResponseResponse;
}
}
To use it:
RestTemplateResponseErrorHandler errorHandler = new
RestTemplateResponseErrorHandler();
//pass the messageConverters to errror handler and let it convert json to object
errorHandler.setMessageConverters(restTemplate.getMessageConverters());
restTemplate.setErrorHandler(errorHandler);
This is how to handle exceptions in Rest Template
try {
return restTemplate.exchange("URL", HttpMethod.POST, entity, String.class);
}
catch (HttpStatusCodeException e)
{
return ResponseEntity.status(e.getRawStatusCode()).headers(e.getResponseHeaders())
.body(e.getResponseBodyAsString());
}
Here is my POST method with HTTPS which returns a response body for any type of bad responses.
public String postHTTPSRequest(String url,String requestJson)
{
//SSL Context
CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
//Initiate REST Template
RestTemplate restTemplate = new RestTemplate(requestFactory);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//Send the Request and get the response.
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
ResponseEntity<String> response;
String stringResponse = "";
try {
response = restTemplate.postForEntity(url, entity, String.class);
stringResponse = response.getBody();
}
catch (HttpClientErrorException e)
{
stringResponse = e.getResponseBodyAsString();
}
return stringResponse;
}
I fixed it by overriding the hasError method from DefaultResponseErrorHandler class:
public class BadRequestSafeRestTemplateErrorHandler extends DefaultResponseErrorHandler
{
#Override
protected boolean hasError(HttpStatus statusCode)
{
if(statusCode == HttpStatus.BAD_REQUEST)
{
return false;
}
return statusCode.isError();
}
}
And you need to set this handler for restemplate bean:
#Bean
protected RestTemplate restTemplate(RestTemplateBuilder builder)
{
return builder.errorHandler(new BadRequestSafeRestTemplateErrorHandler()).build();
}
Read about global exception handling in global exception handler add the below method. this will work.
#ExceptionHandler( {HttpClientErrorException.class, HttpStatusCodeException.class, HttpServerErrorException.class})
#ResponseBody
public ResponseEntity<Object> httpClientErrorException(HttpStatusCodeException e) throws IOException {
BodyBuilder bodyBuilder = ResponseEntity.status(e.getRawStatusCode()).header("X-Backend-Status", String.valueOf(e.getRawStatusCode()));
if (e.getResponseHeaders().getContentType() != null) {
bodyBuilder.contentType(e.getResponseHeaders().getContentType());
}
return bodyBuilder.body(e.getResponseBodyAsString());
}
There is also an option to use TestRestTemplate. It is very useful for integration and E2E tests, when you need to validate all status codes manually (for example in negative test-cases).
TestRestTemplate is fault-tolerant. This means that 4xx and 5xx do not result in an exception being thrown and can instead be detected via the response entity and its status code.
Try using #ControllerAdvice. This allows you to handle the exception only once and have all 'custom' handled exceptions in one place.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html
example
#ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler{
#ExceptionHandler(MyException.class)
protected ResponseEntity<Object> handleMyException(){
MyException exception,
WebRequest webRequest) {
return handleExceptionInternal(
exception,
exception.getMessage(),
exception.getResponseHeaders(),
exception.getStatusCode(),
webRequest);
}

Throw exception from spring controller which producces xml MediaType

I have the the following controller with one RequestMapping which produces an xml MediaType.
#RestController
#RequestMapping("/api")
public class ArticleResource {
#RequestMapping(value = "/xml/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<byte[]> getXml(#PathVariable(value = "id") String id,
final HttpServletRequest request,
final HttpServletResponse response) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(path + id + ".xml");
} catch (FileNotFoundException e) {
throw new BadRequestException("No such xml exists");
}
try {
return new ResponseEntity<byte[]>(IOUtils.toByteArray(inputStream), HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
}
return new ResponseEntity<byte[]>(HttpStatus.NOT_FOUND);
}
}
The BadRequestException implementation is the following:
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}
}
It works fine when the xml exists, but when the xml cannot be found I have a 406 error code. I suppose the problem occurs because it expects a xml media type and instead a RuntimeException is returned. How can I tackle with this issue?
Do you have an Accept: header in your HTTP request? Your error handler will just return an HTTP error code (response status) so it causes a 406 Not Acceptable on the client side if the client expects XML.
If this is the case you can return an XML response entity from the error handler and update your signature to reflect that it produces XML. Or you can try removing the Accepts from your request.
I solved my issue by returning the following:
String returnString = "XML file don't exists";
return new ResponseEntity<byte[]>(IOUtils.toByteArray(
new ByteArrayInputStream(returnString.getBytes())), HttpStatus.NOT_FOUND);

Spring RestTemplate - Overriding ResponseErrorHandler

I am calling a ReST service through RestTemplate and trying to override ResponseErrorHandler in Spring 3.2 to handle custom error codes.
CustomResponseErrroHandler
public class MyResponseErrorHandler implements ResponseErrorHandler {
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
boolean hasError = false;
int rawStatusCode = response.getRawStatusCode();
if (rawStatusCode != 200){
hasError = true;
}
return hasError;
}
#Override
public void handleError(ClientHttpResponse response) throws IOException {
//String body = IOUtils.toString(response.getBody());
throw new CustomServiceException(response.getRawStatusCode() , "custom Error");
}
}
Spring framework invokes hasError method but not handleError, so I couldn't throw my custom exception. After delving into Spring RestTemplate source code, I realized that the code in handleResponseError method is causing the issue - It is looking for response.getStatusCode or response.getStatusText and throwing exception (as statusCode/statusText is null when Rest service throws exception) and it never calls either custom implemented or default handleError method in the next line.
Spring RestTemplate source code for handleResponse method:
private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException {
if (logger.isWarnEnabled()) {
try {
logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
response.getStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
}
catch (IOException e) {
// ignore
}
}
getErrorHandler().handleError(response);
}
FYI, while service throws exception, I can read rawstatuscode but not statuscode from response
How to bypass this framework code and make call my custom handler?
Thanks for your help in advance.
Following link has useful information about Exception Flow for Spring ResponseErrorHandler .
Adding code here, just in-case the blog is down:
Code for ErrorHandler:
public class MyResponseErrorHandler implements ResponseErrorHandler {
private static final Log logger = LogFactory.getLog(MyResponseErrorHandler.class);
#Override
public void handleError(ClientHttpResponse clienthttpresponse) throws IOException {
if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
logger.debug(HttpStatus.FORBIDDEN + " response. Throwing authentication exception");
throw new AuthenticationException();
}
}
#Override
public boolean hasError(ClientHttpResponse clienthttpresponse) throws IOException {
if (clienthttpresponse.getStatusCode() != HttpStatus.OK) {
logger.debug("Status code: " + clienthttpresponse.getStatusCode());
logger.debug("Response" + clienthttpresponse.getStatusText());
logger.debug(clienthttpresponse.getBody());
if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
logger.debug("Call returned a error 403 forbidden resposne ");
return true;
}
}
return false;
}
}
Code for using it in RestTemplate:
RestTemplate restclient = new RestTemplate();
restclient.setErrorHandler(new MyResponseErrorHandler());
ResponseEntity<String> responseEntity = clientRestTemplate.exchange(
URI,
HttpMethod.GET,
requestEntity,
String.class);
response = responseEntity.getBody();
I don't see your RestTemplate code, but I assume you to set your ResponseErrorHandler for RestTemplate to use like:
RestTemplate restClient = new RestTemplate();
restClient.setErrorHandler(new MyResponseErrorHandler());
The exception is indeed thrown in handleError method. You can find how to throw CustomException using CustomResponseHandler from one of my previous answers.

Resources