I'm using Spring RestTemplate to make RESTful calls. I'm also using a custom ClientHttpRequestInterceptor to log the request and response for debugging purposes.
In order to read the response multiple times (once for the logging, once for processing) I use a BufferingClientHttpRequestFactory. Here's the setup:
ClientHttpRequestInterceptor ri = new LoggingRequestInterceptor();
List<ClientHttpRequestInterceptor> ris = new ArrayList<ClientHttpRequestInterceptor>();
ris.add(ri);
restTemplate.setInterceptors(ris);
restTemplate.setRequestFactory(new InterceptingClientHttpRequestFactory(
new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()) , ris));
I'm testing this system right now against a request that returns a 422 response and am having problems. From within the intercept method of my custom ClientHttpRequestInterceptor:
ClientHttpResponse response = execution.execute(request, body);
if(response.getBody() != null) {
logger.trace(IOUtils.toString(response.getBody(), "UTF-8"));
}
The response.getBody() throws an exception:
org.springframework.web.client.ResourceAccessException: I/O error:
Server returned HTTP response code: 422 for URL:
https://testurl.com/admin/orders/564/fulfill.json;
nested exception is java.io.IOException: Server returned HTTP response
code: 422 for URL:
https://testurl.com/admin/orders/564/fulfill.json
at
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:461)
~[spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE] at
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:409)
~[spring-web-3.1.2.RELEASE.jar:3.1.2.RELEASE]
Not sure why this happens, but I turned on the debugger and I set up a watch expression for request.getBody(). The call to request.getBody() being made in that context before it gets to my actual code fixes the error.
Best Answer
The
IOException
thrown fromsun.net.www.protocol.http.HttpURLConnection
whichRestTemplate
uses by default. Looking the source in grepcode,getInputStream()
throwsIOException
if the HTTP status code is 4xx (for 404 or 410 it throws a more specificFileNotFoundException
)To get around this, you need to supply a different
HttpURLConnection
implementation via theClientHttpRequestFactory
that is used as a constructor parameter toRestTemplate
, or injected into it with therequestFactory
property. For exampleDoing this via Spring injection is an exercise left for the reader :-)