Apache Camel 3.7.2升级后聚合操作Exchange.GROUPED_EXCHANGE丢失问题
Apache Camel 3.7.2 升级后聚合属性丢失问题解答
异常原因
- 该问题确实和Camel 3.x的聚合逻辑不兼容变更相关:Camel 3.x为了避免聚合过程中Exchange属性互相污染,调整了
ExchangeHelper.prepareAggregation方法的实现,聚合操作过程中会创建新的Exchange实例,默认不会将旧实例的全部自定义属性拷贝到新实例中。 AbstractListAggregationStrategy是将CamelGroupedExchange属性设置到旧聚合Exchange实例上的,新创建的Exchange实例没有该属性,因此你通过${exchangeProperty}读取时会拿到空值。- Camel 2.x版本中聚合操作全程复用同一个Exchange实例,所以不会出现属性丢失的问题。
修复方案
方案1(推荐):直接使用split组件返回的聚合结果
Camel 3.x的split组件搭配GroupedExchangeAggregationStrategy使用时,split节点执行完成后,默认已经将聚合后的列表结果直接写入当前Exchange的body中,不需要额外读取exchangeProperty,直接删除setBody(groupedExchanges)这行代码即可,修改后的路由代码如下:
@Override public void configure() throws Exception { final SimpleExpression documentAppendix = new SimpleExpression("${body.appendix}"); from("direct://input") .choice() .when(documentAppendix) .split(documentAppendix, new GroupedExchangeAggregationStrategy()) .to("direct://input.splitted") .end() // 直接删除原有的setBody读取属性逻辑 .endChoice() .otherwise() .setBody(constant(Lists.newArrayList())) .end(); // ... 省略其余代码 }
方案2:保留读取exchangeProperty逻辑的适配方案
如果业务逻辑需要保留从exchangeProperty读取的实现,可以自定义聚合策略,将CamelGroupedExchange属性主动同步到新Exchange中,示例代码如下:
public class CustomGroupedAggregationStrategy extends GroupedExchangeAggregationStrategy { @Override public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { Exchange result = super.aggregate(oldExchange, newExchange); // 主动将分组属性设置到新Exchange上 if (newExchange != null) { newExchange.setProperty(Exchange.GROUPED_EXCHANGE, result.getProperty(Exchange.GROUPED_EXCHANGE)); } return result; } }
之后将split节点的聚合策略替换为自定义的实现即可。
方案3:全局开启聚合属性拷贝
如果项目中多处存在类似的依赖聚合属性的逻辑,可以在Camel全局配置中开启聚合属性拷贝开关:camel.aggregate.copy-properties=true,开启后聚合过程中会自动将旧Exchange的全部属性拷贝到新实例中,无需修改业务代码。
内容的提问来源于stack exchange,提问作者Fips
相关产品推荐
相关产品推荐

