Reputation: 6802
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.
Upvotes: 8
Views: 9739
Reputation: 5008
The IOException
thrown from sun.net.www.protocol.http.HttpURLConnection
which RestTemplate
uses by default. Looking the source in grepcode, getInputStream()
throws IOException
if the HTTP status code is 4xx (for 404 or 410 it throws a more specific FileNotFoundException
)
To get around this, you need to supply a different HttpURLConnection
implementation via the ClientHttpRequestFactory
that is used as a constructor parameter to RestTemplate
, or injected into it with the requestFactory
property. For example
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
RestTemplate restTemplate = new RestTemplate(factory);
Doing this via Spring injection is an exercise left for the reader :-)
Upvotes: 7