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.
Default Error Handling By default, the RestTemplate will throw one of these exceptions in the case of an HTTP error: HttpClientErrorException – in the case of HTTP status 4xx. HttpServerErrorException – in the case of HTTP status 5xx. UnknownHttpStatusCodeException – in the case of an unknown HTTP status.
RestTemplate will still be used. But in some cases, the non-blocking approach uses much fewer system resources compared to the blocking one.
4.1. RestTemplate's postForObject method creates a new resource by posting an object to the given URI template. It returns the result as automatically converted to the type specified in the responseType parameter.
Using postForEntity()Find the postForEntity method declaration from Spring doc. url: The URL to post the request. request: The object to be posted. responseType: The type of response body.
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 :-)
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