Spring Integration: Обработка ошибок в среде несовместима - PullRequest
0 голосов
/ 27 мая 2018

По моему опыту, стратегия обработки ошибок в различных компонентах EIP имеет небольшую согласованность или не соответствует ей.

Случай 1: handle :

return IntegrationFlows.from(inputChannel)
    .enrichHeaders(spec -> spec.header(ERROR_CHANNEL, ARTIFACTORY_ERROR_CHANNEL, true))
    .handle(WebFlux.outboundGateway(uri, webClient)
            .expectedResponseType(ArtifactSearchResponse.class)
            .httpMethod(GET)
            .mappedRequestHeaders(ACCEPT))
    .log(LoggingHandler.Level.INFO, CLASS_NAME, Message::getPayload)
    .handle(transformer)
    .channel(outputChannel)
    .get();

В этом случаеЕсли handle(transformer) выдает исключение, сообщение отправляется на ARTIFACTORY_ERROR_CHANNEL, как и ожидалось, но исключение возвращается вызывающей стороне.Таким образом, тест должен использовать try-catch, чтобы не потерпеть неудачу.

try {
    inputChannel.send(new GenericMessage<>("start"));
} catch (Exception e) {
    // nop-op
}
verify(mockMessageHandler, timeout.times(1)).handleMessage(any(ErrorMessage.class));

Случай 2: преобразование : изменить handle(transformer) на transform(transformer), и исключение никогда не отправляетсяARTIFACTORY_ERROR_CHANNEL канал.

Случай 3: шлюз :

public IntegrationFlow fileStreamingFlow() {
  return IntegrationFlows.from(inputChannel)
      .gateway(f -> f.handle(String.class, (fileName, headers) -> {
          throw new RuntimeException();
      }), spec -> spec.requiresReply(false).errorChannel(S3_ERROR_CHANNEL))
      .channel(outputChannel)
      .get();
  }
}

В этом случае вызовы блокируются навсегда.См. # 2451 .

Случай 4: дескриптор с routeByException :

return IntegrationFlows.from(s3Properties.getFileStreamingInputChannel())
    .enrichHeaders(spec -> spec.header(ERROR_CHANNEL, S3_ERROR_CHANNEL, true))
    .handle(String.class, (fileName, h) -> {
        return new ErrorMessage(new RuntimeException(), h);
    }, spec -> spec.requiresReply(false))
    .channel(outputChannel)
    .routeByException(r -> r.channelMapping(Exception.class, S3_ERROR_CHANNEL))
    .get();
}

Чтобы исключение было отправлено на S3_ERROR_CHANNELМне нужно преобразовать исключение в ErrorMessage, а также применить routeByException, хотя ранее уже было настроено ERROR_CHANNEL.

Что я ожидаю : если пользователь определяетканал ошибки, отправьте туда все исключения.Если обработчик ошибок, связанный с этим каналом, возвращает null, завершите поток;если он возвращает что-то еще, продолжайте.Если пользователь не определяет канал ошибок, отправьте исключение в канал ошибок по умолчанию в рамках.Делайте это независимо от определения потока.

1 Ответ

0 голосов
/ 27 мая 2018

трансформатор - если ваш трансформатор возвращает Message<?>;он отвечает за распространение заголовка errorChannel.

При использовании шлюза канал ошибки должен быть объявлен на нем, а не добавляться позже.

Я не понимаю, что вы пытаетесь делать там.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...