Given a REST service call
http://acme.com/app/widget/123
returns:
<widget>
<id>123</id>
<name>Foo</name>
<manufacturer>Acme</manufacturer>
</widget>
This client code works:
RestTemplate restTemplate = new RestTemplate();
XStreamMarshaller xStreamMarshaller = new XStreamMarshaller();
xStreamMarshaller.getXStream().processAnnotations(
new Class[] {
Widget.class,
ErrorMessage.class
});
HttpMessageConverter<?> marshallingConverter = new MarshallingHttpMessageConverter(
xStreamMarshaller, xStreamMarshaller);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(marshallingConverter);
restTemplate.setMessageConverters(converters);
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 123L);
However, calling http://acme.com/app/widget/456 returns:
<error>
<message>Widget 456 does not exist</message>
<timestamp>Wed, 12 Mar 2014 10:34:37 GMT</timestamp>
</error>
but this client code throws an Exception:
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
org.springframework.web.client.HttpClientErrorException: 404 Not Found
I tried:
try {
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
}
catch (HttpClientErrorException e) {
ErrorMessage errorMessage = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", ErrorMessage.class, 456L);
// etc...
}
The second invocation just threw another HttpClientErrorException, plus it does not feel right calling the service twice.
Is there a way to call the service once and parse the response into a Widget on success and an ErrorMessage when not found?
You can also create an object from Error response body if you like:
ObjectMapper om = new ObjectMapper();
String errorResponse = ex.getResponseBodyAsString();
MyClass obj = om.readValue(errorResponse, MyClass.class);
Following from my comment, I checked the HttpClientErrorException
JavaDoc and it does support both setting/getting the statusText
as well as the responseBody
. However they are optional and RestTemplate may not populate them - you'll need to try something like:
try {
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
}
catch (HttpClientErrorException e) {
String responseBody = e.getResponseBodyAsString();
String statusText = e.getStatusText();
// log or process either of these...
// you'll probably have to unmarshall the XML manually (only 2 fields so easy)
}
If they are both empty/null then you may have to extend the RestTemplate class involved and populate those fields yourself and/or raise a Jira issue on the Spring site.
As you already catch the HttpClientErrorException object, it should allows you to easily extract useful information about the error and pass that to the caller.
For example:
try{
<call to rest endpoint using RestTemplate>
} catch(HttpClientErrorException e){
HttpStatus statusCode = e.getStatusCode();
String body = e.getResponseBodyAsString();
}
IMO if one needs to further de-serialize the error message body
into some relevant object, that can be handled somewhere outside of the catch statement scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With