2015-05-20 1 views
4

Я использую Spring RestTemplate для вызова RESTful. Я также использую пользовательский ClientHttpRequestInterceptor для регистрации запроса и ответа для целей отладки.RestTemplate ClientHttpResponse.getBody() выбрасывает ошибку ввода-вывода

Чтобы прочитать ответ несколько раз (один раз для ведения журнала, один раз для обработки), я использую BufferingClientHttpRequestFactory. Вот установка:

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)); 

Я тестирую эту систему прямо сейчас против запроса, который возвращает 422 ответа и у меня возникают проблемы. Изнутри метода перехвата моего пользовательского ClientHttpRequestInterceptor:

ClientHttpResponse response = execution.execute(request, body); 
if(response.getBody() != null) { 
    logger.trace(IOUtils.toString(response.getBody(), "UTF-8")); 
} 

response.getBody() бросает исключение:

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]

Не знаю, почему это происходит, но я включил отладчик и настроить выражение watch для request.getBody(). Вызов request.getBody() выполняется в этом контексте до того, как он дойдет до моего фактического кода исправляет ошибку.

+0

где находятся ваши XML-конфигурации для resttemplate –

+2

же здесь. Еще одно интересное поведение: вызов 'response.getStatusCode()' до 'response.getBody()' также «исправляет» проблему. – istibekesi

+0

https://stackoverflow.com/questions/47429978/resttemplate-response-getbody-throws-exception-on-4-and-5-errors-for-put-and –

ответ

2

IOException выброшено из sun.net.www.protocol.http.HttpURLConnection, которое RestTemplate использует по умолчанию. Глядя на источник в grepcode, getInputStream() бросает IOException если код состояния HTTP является 4xx (на 404 или 410 он выдает более конкретную FileNotFoundException)

Чтобы обойти эту проблему, необходимо поставить другую HttpURLConnection реализацию через ClientHttpRequestFactory, который используется в качестве параметра конструктора для RestTemplate или вводится в него свойством requestFactory. Например

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 
RestTemplate restTemplate = new RestTemplate(factory); 

Doing это с помощью инъекций Spring это упражнение оставил для читателя :-)