Как сделать исключительную обработку для WebFlux, используя Springboot? - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть 3 приложения микро-службы.Я пытаюсь сделать 2 получить асинхронный вызов с использованием веб-клиента из реактивного пакета, а затем объединить их всякий раз, когда я получаю ответ.

Пример кода для этого: (по ссылке - https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/web-reactive.html#webflux-client-synchronous)

Mono<Person> personMono = client.get().uri("/person/{id}", personId)
        .retrieve().bodyToMono(Person.class);

Mono<List<Hobby>> hobbiesMono = client.get().uri("/person/{id}/hobbies", personId)
        .retrieve().bodyToFlux(Hobby.class).collectList();

Map<String, Object> data = Mono.zip(personMono, hobbiesMono, (person, hobbies) -> {
            Map<String, String> map = new LinkedHashMap<>();
            map.put("person", personName);
            map.put("hobbies", hobbies);
            return map;
        })
        .block();

Мой вопрос: как я могу добавить обработку исключений к полученным вызовам?

Как проверить, получил ли я 404 или 204 или что-то еще?

Я пытался:

  1. Добавление .onStatus () к вызовам GET
    .onStatus(HttpStatus::is4xxClientError, clientResponse ->
             Mono.error(new Data4xxException(String.format(
                "Could not GET data with id: %s from another app, due to error: 
                 %s", key, clientResponse))))
    .onStatus(HttpStatus::is5xxServerError, clientResponse ->
          Mono.error(new Data5xxException(
              String.format("For Data %s, Error Occurred: %s", key, clientResponse))))
Добавление обработчиков исключений - но у меня точно нет контроллера, так что, похоже, он не работает.
@ExceptionHandler(WebClientException.class)
    public Exception handlerWebClientException(WebClientException webClientException) {
        return new Data4xxException("Testing", webClientException);
    }
Добавлен класс с ControllerAdvice и ExceptionHandler внутри него
@ControllerAdvice
public class WebFluxExceptionHandler {

    @ExceptionHandler(WebClientException.class)
    public Exception handlerWebClientException(WebClientException webClientException) {
        return new Data4xxException("Testing", webClientException);
    }
}

Но я не вижу их напечатанными в журналах весенней загрузки.

The Mono.zip.Метод block () просто возвращает ноль и на самом деле не генерирует никаких исключений.

Как мне получить, чтобы метод zip генерировал исключение и не возвращал ноль?

Ответы [ 2 ]

2 голосов
/ 20 сентября 2019

Вам не очень ясно, когда вы спрашиваете

"Как я могу получить метод zip для исключения и не возвращает ноль?"

В webfluxВы обычно не генерируете исключения, вы распространяете исключения и затем обрабатываете их.Почему?поскольку мы имеем дело с потоками данных, если вы генерируете исключение, поток заканчивается, клиент отключается и цепочка событий останавливается.

Мы по-прежнему хотим поддерживать поток данных и обрабатывать неверные данные, когда они проходят через.

Вы можете обрабатывать ошибки, используя метод doOnError.

.onStatus(HttpStatus::is4xxClientError, clientResponse ->
         Mono.error(new Data4xxException(String.format(
            "Could not GET data with id: %s from another app, due to error: 
             %s", key, clientResponse))))

Mono.zip( .. ).doOnError( //Handle your error, log or whatever )

Если вы хотите сделать что-то более конкретное, вам придется обновить свой вопрос так, как вы хотите, чтобы ваши ошибки исправлялись.быть обработанным.

0 голосов
/ 23 сентября 2019

Способ сделать это - использовать onErrorMap следующим образом:

Mono<Person> personMono = client.get()
.uri("/person/{id}", personId)
.retrieve()
.bodyToMono(Person.class)
.onErrorMap((Throwable error) -> error);

onErrorMap заставит Mono фактически выдавать ошибку, когда Zip блокирует, завершая zip и позволяя spring или любому другому классу, который выхочу обработать исключение.

...