apache-camel - 基于表达式处理的事务性 Camel 路由标记交换不起作用
问题描述
我的骆驼路线以事务方式从/到 JMS 消费和生产。如果多次处理失败,我们的要求是丢弃有害消息。我知道更好的选择是将消息移动到死信队列,但出于本练习的目的,丢弃它只是很好。
下面是模拟问题的路由定义:
package com.my.comp.playground;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Component
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() {
onException(Exception.class)
.process(new Processor() {
private int failureCounter = 0;
@Override
public void process(Exchange exchange) {
exchange.getIn().setHeader("failureCounter", ++failureCounter);
}
})
.log("failureCounter = ${header.failureCounter}")
//.handled(true);
.handled(header("failureCounter").isGreaterThan(3));
from("jms:test.queue")
.routeId("test-route")
.transacted()
.process(exchange -> {
throw new RuntimeException("No good Pal!");
})
.to("mock:discard");
}
}
所以我要做的是保留一个失败的计数器,如果该计数器大于某个数字,则将异常标记为已处理并提交事务。
注意异常处理末尾的两行代码:
//.handled(true);
.handled(header("failureCounter").isGreaterThan(3));
当我使用已header("failureCounter").isGreaterThan(3)
处理的条件运行路由时,消息会一次又一次地回滚,我可以在日志中看到 failureCounter 正确增加:
...
[mer[test.queue]] test-route : failureCounter = 402
[mer[test.queue]] o.a.c.p.e.DefaultErrorHandler : Failed delivery for (MessageId: ...
...
[mer[test.queue]] test-route : failureCounter = 403
...
[mer[test.queue]] test-route : failureCounter = 404
...
但是,当我使用已处理的条件运行路由时,true
事务会在第一次失败后立即提交,如下所示:
[mer[test.queue]] test-route : failureCounter = 1
[mer[test.queue]] o.a.c.s.spi.TransactionErrorHandler : Transaction commit (0x52b2f795) redelivered(true)
所以我的问题是:我做错了什么还是我对如何使用handled
异常的理解不正确?如果是这样,正确的方法是什么?
解决方案
我不知道这是设计使然还是错误。
当我调试您的案例时,我看到谓词 inhandled()
是针对 Camel Exchange 进行评估的。
但是,您的failureCounter
标头不在 Exchange 中。因此,表达式的header("failureCounter")
计算结果为null
并且您的谓词始终为false
。
在一个简短的测试中,我看到存在异常之前设置的标头,但在异常之后设置的标头(即设置在错误处理程序中)在用于评估谓词的 Exchange 上不存在。
推荐阅读
- kotlin - 试图在 gradle kotlindsl 中包含 swagger-codegen
- php - 无法检测到 sql 语法错误
- nativescript - 如何正确切换活动?
- javascript - Angular 上的 Chart.js 与 @types/chart.js
- java - 无法在我的 for-each 循环中将“i+2”写为后置条件 [Java]
- email - OpenProject 电子邮件通知邮件内没有图片
- android - 无法在 Android 中使用我自己的启动器接听 Skype 来电
- google-apps-script - 使用 Google App Script 创建新的幻灯片请求并修改创建的布局
- php - 使用 unserialize() 在控制台请求中反序列化会话数据?
- azure - 如何调试 Azure 应用服务上的启动错误