gpt4 book ai didi

apache-camel - 如果处理了内部路由中的异常,则不会执行具有聚合策略的 Splitter 之后的代码(Apache Camel)

转载 作者:行者123 更新时间:2023-12-04 08:51:32 27 4
gpt4 key购买 nike

我遇到了我无法理解的行为。执行 Split with AggregationStrategy 时会发生此问题,并且在其中一次迭代期间发生异常。在另一条路由(每次迭代调用的直接端点)中的 Splitter 内部发生异常。似乎路由执行在 Splitter 之后停止。
这是示例代码。
这是一种为每个客户端构建一个报告并收集文件名称以进行内部统计的路由。


@Component
@RequiredArgsConstructor
@FieldDefaults(level = PRIVATE, makeFinal = true)
public class ReportRouteBuilder extends RouteBuilder {

ClientRepository clientRepository;

@Override
public void configure() throws Exception {
errorHandler(deadLetterChannel("direct:handleError")); //handles an error, adds error message to internal error collector for statistic and writes log

from("direct:generateReports")

.setProperty("reportTask", body()) //at this point there is in the body an object of type ReportTask, containig all data required for building report

.bean(clientRepository, "getAllClients") // Body is a List<Client>

.split(body())
.aggregationStrategy(new FileNamesListAggregationStrategy())
.to("direct:generateReportForClient") // creates report which is saved in the file system. uses the same error handler
.end()

//when an exception occurs during split then code after splitter is not executed

.log("Finished generating reports. Files created ${body}"); // Body has to be List<String> with file names.
}
}

AggregationStrategy 非常简单——它只是提取文件的名称。如果标题不存在,则返回 NULL。

public class FileNamesListAggregationStrategy extends AbstractListAggregationStrategy<String> {

@Override
public String getValue(Exchange exchange) {
Message inMessage = exchange.getIn();
return inMessage.getHeader(Exchange.FILE_NAME, String.class);
}
}

当拆分后一切顺利时,正文列表中将包含所有文件名。但是当在路由“direct:generateReportForClient”中发生一些异常时(我为一个客户端添加了错误模拟),而不是聚合体只包含一个少的文件名 - 没关系(一切都被正确聚合)。
但是,在路由执行停止后的拆分之后,此时主体中的结果(带有文件名的列表)将返回给客户端(FluentProducer),客户端(FluentProducer)期望 ReportTask 作为响应主体。
并尝试将值 - 列表(聚合结果)转换为 ReportTask 并导致 org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type为什么拆分后路由会中断?所有错误都被处理并且聚合正确完成。
PS我已经阅读了关于Splitter的Camel In Action书和文档,但我还没有找到答案。
PPS 项目在 Spring Boot 2.3.1 和 Camel 3.3.0 上运行
更新
此路由由 FluentProducerTemplate 启动
    ReportTask processedReportTask = producer.to("direct:generateReports")
.withBody(reportTask)
.request(ReportTask.class);

最佳答案

问题在于拆分中的错误处理程序 + 自定义聚合策略。
来自《 Camel 行动》一书(5.3.5):

WARNING When using a custom AggregationStrategy with the Splitter,it’s important to know that you’re responsible for handlingexceptions. If you don’t propagate the exception back, the Splitterwill assume you’ve handled the exception and will ignore it.


在您的代码中,您使用从 AbstractListAggregationStrategy 扩展而来的聚合策略。 .让我们看看 aggregate AbstractListAggregationStrategy 中的方法:
@Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
List<V> list;

if (oldExchange == null) {
list = getList(newExchange);
} else {
list = getList(oldExchange);
}

if (newExchange != null) {
V value = getValue(newExchange);
if (value != null) {
list.add(value);
}
}

return oldExchange != null ? oldExchange : newExchange;
}

如果第一次交换由错误处理程序处理,我们将在结果交换( newExchange )中拥有由错误处理程序( Exchange.EXCEPTION_CAUGHT, Exchange.FAILURE_ENDPOINT, Exchange.ERRORHANDLER_HANDLED and Exchange.FAILURE_HANDLED )和 exchange.errorHandlerHandled=true 设置的属性数量.方法 getErrorHandlerHandled()/setErrorHandlerHandled(Boolean errorHandlerHandled)可在 ExtendedExchange 购买界面。
在这种情况下,您的拆分以与 errorHandlerHandled=true 的交换结束。它打破了路线。
原因在 camel exception clause manual中描述

If handled is true, then the thrown exception will be handled andCamel will not continue routing in the original route, but break out.


为了防止这种行为,您可以将您的交易所投给 ExtendedExchange并设置 errorHandlerHandled=false在聚合策略中 aggregate方法。你的路线不会被打破,而是会继续。
  @Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
Exchange aggregatedExchange = super.aggregate(oldExchange, newExchange);
((ExtendedExchange) aggregatedExchange).setErrorHandlerHandled(false);
return aggregatedExchange;
}
棘手的情况是,如果您已将错误处理程序处理为 不是第一个 在您的聚合策略中,您不会遇到任何问题。因为camel会使用 第一 交换(没有 errorHandlerHandled=true )作为聚合的基础。

关于apache-camel - 如果处理了内部路由中的异常,则不会执行具有聚合策略的 Splitter 之后的代码(Apache Camel),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64078024/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com