Передача сообщений об ошибках из приложения Spring Boot из SSE (Webflux) в интерфейс Angular 7 - PullRequest
7 голосов
/ 19 марта 2019

Мое приложение представляет собой приложение Spring Boot с несколькими конечными точками.Мы пытаемся добавить конечную точку с поддержкой SSE, используя Webflux.

Вариант использования:

Шаг 1. Внешний интерфейс отправляет запрос конечной точке POST и получает уникальный идентификатор.

Шаг 2: Внешний интерфейс извлекает обработанный результат, используяGET конечная точка (SSE включен - Flux)

Angular использует объект EventSource для использования конечной точки SSE.Требуется конечная точка для создания текста / потока событий.Это работает очень хорошо для положительных тестовых случаев.Но когда из службы вызываются исключения во время выполнения, внешний интерфейс Angular не может получить коды состояния HTTP и сведения об исключениях.Это просто ошибки без данных.

Исключения:

@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class RequestNotFoundException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public RequestNotFoundException(String message) {
        super(message);
    }
}

Как уже упоминалось в this , возвращая Flux<ServerSentEvent> и завершая поток с пользовательским событием:

Javaконечная точка

 @GetMapping(path= "{id}/async", produces=MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<Optional<ProcessedResult>>> getProcessedResultStream(
        @PathVariable("id") @ApiParam(value = "The unique identifier of the request", required = true) String id)
        throws InterruptedException {
    // Combining data and adding a disconnect event to handle at the frontend.
    return Flux.concat(
            Flux.just(ServerSentEvent.<Optional<ProcessedResult>>builder(service.getProcessedResult(id))
                    .build()),
            Flux.just(ServerSentEvent.<Optional<ProcessedResult>>builder().event("disconnect").build()));
}

Это помогает закрыть соединение на стороне пользовательского интерфейса, отключив его.Но моя главная проблема остается открытой.Как я должен идти о распространении сообщений об ошибках обратно на веб-интерфейс?Все другие (обычные) конечные точки генерируют пользовательские исключения времени выполнения с правильными HTTP-кодами, как указано выше.

Должен ли я изменить свой класс ProcessedResult, чтобы он также принимал сведения об исключениях?

1 Ответ

4 голосов
/ 23 марта 2019

События на стороне сервера используют открытое соединение HTTP для потоковой передачи содержимого с сервера. В соответствии со спецификацией W3C Eventsource HTTP 200 OK ответы с правильным заголовком Content-Type требуются для установления соединения, HTTP 500, 502, 503, 504 или любые другие сетевые ошибки приведут к тому, что браузер восстановит соединение. Если ни один из вышеперечисленных случаев не удовлетворен, событие ошибки запускается с readyState = 'CLOSED'. Короче говоря, обратный вызов onError предназначен только для обработки таймаутов сети или проблем контроля доступа.

Невозможно отправить другой код состояния HTTP, основанный на исключении времени выполнения, поскольку вы уже отправили 200 Ok при установлении соединения. Единственный способ обработки ошибки времени выполнения - перехватить исключение и отправить пользовательское именованное событие с сервера и close EvetSource на его основе.

...