IOException, исходящий из Spring RestTemplate Не выбирается пользовательским ResponseErrorHandler - PullRequest
0 голосов
/ 13 февраля 2019

Я использую Spring's RestTemplate для выполнения некоторых вызовов API сторонней службы.

Все работает, как и ожидалось, когда ответ возвращается как 200 SUCCESS.

Однако,когда ответом является 400-level error, я получаю IOException из глубины живота кода RestTemplate.

Это расстраивает, потому что я на самом деле написал свою собственную реализацию ResponseErrorHandler, который проверяет определенные ошибки, не относящиеся к 200, и делает что-то по моему выбору (ведение журнала, переформатирование и т. Д.)

На любом другом стороннем API моя реализация ResponseErrorHandler работает, но для этого серверав частности, все ошибки не-200 приводят к этому IOException, и моя пользовательская реализация никогда не достигается.

Примечание: Curl, кажется, обычно возвращает ошибку, когда я пытаюсь достичь этой конечной точки стороннего производителя.

Это ошибка Spring ?Я делаю что-то глупое?Идеи для обхода?

Соответствующий код

Стек Трассировка исключения:

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://third-party.com/api/v2/some-resource": Server returned HTTP response code: 400 for URL: https://third-party.com/api/v2/some-resource; nested exception is java.io.IOException: Server returned HTTP response code: 400 for URL: https://third-party.com/api/v2/some-resource
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:607) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.myowncode.commons.client.RestClient.send(RestClient.java:74) ~[classes/:na]

Использование моего пользовательского ResponseErrorHandler

this.restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setErrorHandler(new LoggingResponseErrorHandler());

Пример моего пользовательского ResponseErrorHandler

(это не имеет значения, поскольку вышеизложенное происходит независимо от того, зарегистрировал я это или нет)

public class LoggingResponseErrorHandler implements ResponseErrorHandler {

    private static final Logger logger = LoggerFactory.getLogger(LoggingResponseErrorHandler.class);

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        // do my own thing
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // do my own thing
    }

}

1 Ответ

0 голосов
/ 18 февраля 2019

Я подозреваю, что это связано с использованием BufferingClientHttpRequestFactory.SimpleBufferingClientHttpRequest, по-видимому, позволяет IOException избегать его метода executeInternal (), тогда как небуферизованная версия SimpleStreamingClientHttpRequest перехватывает и игнорирует его, что, предположительно, позволит вам обработать ответ.

    @Override
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
    try {
        if (this.body != null) {
            this.body.close();
        }
        else {
            SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
            this.connection.connect();
            // Immediately trigger the request in a no-output scenario as well
            this.connection.getResponseCode();
        }
    }
    catch (IOException ex) {
        // ignore
    }
    return new SimpleClientHttpResponse(this.connection);
}

попытайтесь создать свой restTemplate, напримерэто:

this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...