По моему опыту, стратегия обработки ошибок в различных компонентах 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
, завершите поток;если он возвращает что-то еще, продолжайте.Если пользователь не определяет канал ошибок, отправьте исключение в канал ошибок по умолчанию в рамках.Делайте это независимо от определения потока.