How to parse the response body in Java, when the HTTP request has return status 401
Try the following approach without needing a custom handler. The idea is to get the response as a string from the HttpStatusCodeException, and then you can convert it to your object. For the conversion I used the Jackson's ObjectMapper:
try {
restTemplate.postForObject(url, pojoInstance, responseClass);
} catch (HttpStatusCodeException e) {
if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
String responseString = e.getResponseBodyAsString();
ObjectMapper mapper = new ObjectMapper();
CustomError result = mapper.readValue(responseString,
CustomError.class);
}
}
Update: Usage of a different factory may also help since there is a bug in the default one related to your issue (see comment below):
RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
I did it like that:
@Component
public class RestTemplateFactory {
public enum Type {
JSON, XML
}
public RestTemplate create(Type type) {
RestTemplate restTemplate = new RestTemplate();
if (type == Type.XML) {
Jaxb2RootElementHttpMessageConverter jaxbMessageConverter = new Jaxb2RootElementHttpMessageConverter();
jaxbMessageConverter.setSupportedMediaTypes(Lists.newArrayList(MediaType.TEXT_HTML, MediaType.APPLICATION_XML));
restTemplate.setMessageConverters(Lists.newArrayList(jaxbMessageConverter));
}
restTemplate.setErrorHandler(new BpmRestErrorHandler(restTemplate.getMessageConverters()));
return restTemplate;
}
public HttpHeaders contentHeaders(Type type) {
HttpHeaders headers = new HttpHeaders();
if (type == Type.XML) {
headers.setContentType(MediaType.APPLICATION_XML);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
} else {
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
}
return HttpHeaders.readOnlyHttpHeaders(headers);
}
}
And handler:
public class BpmRestErrorHandler extends DefaultResponseErrorHandler {
private final List<HttpMessageConverter<?>> messageConverters;
public BpmRestErrorHandler(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
for (HttpMessageConverter messageConverter : messageConverters) {
if (messageConverter.canRead(RestRuntimeException.class, response.getHeaders().getContentType())) {
RestRuntimeExceptionData exceptionData =
(RestRuntimeExceptionData)messageConverter.read(RestRuntimeException.class, response);
throw new BpmRestException(exceptionData);
}
}
super.handleError(response);
}
}
Where RestRuntimeExceptionData
is my custom WebFault object.
It re-uses RestTemplate's HttpConverters.