springrestresttemplatespring-restxml-binding

Unmarshalling response depending on HTTP code during Spring Rest Service call


Calling a Rest Webservice using the Spring Rest Template as follows-

ResponseEntity<String> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, entity, String.class); 

and get the output in String format as

<Info xmlns="http://schemas.test.org/2009/09/Tests.new" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<FirstName>FirstName</FirstName>
<LastName>LastName</LastName>
<TestGuid>Guid</TestGuid>
<TestUID>1</TestUID>
<Token>token</Token>
<TestUserID>14</TestUserID>
</Info>

When trying to unmarshal it to java class as follows

ResponseEntity<Info> response = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, entity, Info.class)

The Info class is defined as

@XmlRootElement(name = "Info", namespace = "http://schemas.test.org/2009/09/Tests.new")
public class Info implements Serializable{

    private String FirstName;
    private String LastName;
    private String TestGuid;
    private String TestUID;
    private String Token;
    private String TestUserID;

    //getters and setter

}   

If the Response http code is 500 then the response is not of type info but of other type infoException.

Can we specify to the resttemplate to unmarshal the output depending on the Http response code?


Solution

  • The rest template checks response for error before extracting the data. So one way would be to create Rest Template with the implementation of ResponseErrorHandler and override the handleError method to extract the error response to your object using converters and then wrap this error object into exception. Something like this.

        class ErrorObjectResponseHandler implements ResponseErrorHandler {
    
          private List<HttpMessageConverter<?>> messageConverters;
    
          @Override
          public boolean hasError(ClientHttpResponse response) throws IOException {
            return hasError(response.getStatusCode());
          }
    
          protected boolean hasError(HttpStatus statusCode) {
            return (statusCode.is4xxClientError() || statusCode.is5xxServerError());
          }
    
          @Override
          public void handleError(ClientHttpResponse response) throws IOException {
            HttpMessageConverterExtractor<Error> errorMessageExtractor =
              new HttpMessageConverterExtractor(Error.class, messageConverters);
            Error errorObject = errorMessageExtractor.extractData(response);
            throw new SomeException(errorObject);
          }
    
          public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
            this.messageConverters = messageConverters;
          }