gpt4 book ai didi

apache-camel - Camel 消息重新传递未按预期运行

转载 作者:行者123 更新时间:2023-12-04 00:37:48 35 4
gpt4 key购买 nike

我在 Camel 中有一条路线,我想在发生异常时重试,但我想设置一个属性,以便路线第二次可以做一些稍微不同的事情,以尝试阻止错误在重试时再次发生。这是说明我目前正在尝试的想法的路线。

from("direct:onExceptionTest")
.onException(Exception.class)
.maximumRedeliveries(1)
.log("Retrying")
.setProperty("retrying", constant(true))
.end()
.log("Start")
.choice()
.when(property("retrying").isNull())
.log("Throwing")
.throwException(new Exception("Hello world"))
.end()
.end()
.log("Done")

显然这不是真正的路线;整个 choice 主体只是在某些情况下模拟我的组件错误。我期待看到记录以下消息:

Start
Throwing
Retrying
Start
Done

但我实际看到的是:

Start
Throwing
Retrying
Failed delivery for (MessageId: ... on ExchangeId: ...). Exhausted after delivery attempt: 2 caught: java.lang.Exception: Hello world. Processed by failure processor: FatalFallbackErrorHandler[Pipeline[[Channel[Log(onExceptionTest)[Retrying]], Channel[setProperty(retrying, true)]]]]

我已经尝试将 handled(true) 添加到异常处理程序中,但这只是抑制错误消息。我没有看到第二条开始或完成日志消息。

为什么我的路线不像我预期的那样运行,我需要做什么才能让它按照我想要的方式运行?

更新

@ProgrammerDan 指出问题在于重新交付并不是我想要实现的目标,这可以解释为什么我的路线不起作用!所以我需要在我的处理程序中完成工作,但我的路由调用 Web 服务并有一些其他步骤,我不想在处理程序中复制所有这些。我想出了这个,它按预期工作,但它涉及从一开始就再次调用自身的路由。这是一个坏主意吗?我会因为这种方法而陷入困境吗?

from("direct:onExceptionTest")
.onException(Exception.class)
.onWhen(property("retrying").isNull()) // don't retry forever
.log("Retrying")
.setProperty("retrying", constant(true))
.handled(true)
.to("direct:onExceptionTest") // is recursion bad?
.end()
.log("Start")
.choice()
.when(property("retrying").isNull())
.log("Throwing")
.throwException(new Exception("Hello world"))
.end()
.end()
.log("Done")

最佳答案

使用 onRedeliveryProcessor 来设置属性:

String KEY = "retrying";

from("direct:onExceptionTest")
.onException(RuntimeException.class)
.onRedelivery(new Processor() { // Sets a processor that should be processed before a redelivery attempt.
@Override
public void process(final Exchange exchange) throws Exception {
LOG.info("Retrying");
exchange.setProperty(KEY, true);
}
})
.maximumRedeliveries(1)
.handled(true)
.end()
.log("Start")
.process(new Processor() {
@Override
public void process(final Exchange exchange) throws Exception {
LOG.info("No problem");
}
})
.process(new Processor() {
@Override
public void process(final Exchange exchange) throws Exception {
if (exchange.getProperty(KEY) == null) {
LOG.info("Throwing");
throw new RuntimeException("Hello World");
}
else {
LOG.info("No throwing");
}
}
})
.log("Done");

这打印

[                          main] route1                         INFO  Start
[ main] OnExceptionHandler INFO No problem
[ main] OnExceptionHandler INFO Throwing
[ main] OnExceptionHandler INFO Retrying
[ main] OnExceptionHandler INFO No throwing
[ main] route1 INFO Done

正如@ProgrammerDan 指出的那样,只有失败的处理器会重新执行,而不是第一个没有任何问题通过的处理器。

编辑:

如果必须重新完成所有处理,那么您可以使用带有 doTrydoCatch 的子路由,如下所示:

from("direct:onExceptionTest")
.doTry()
.to("direct:subroute")
.doCatch(RuntimeException.class)
.setProperty(KEY, constant(true))
.to("direct:subroute")
.end()
.log("Done");

from("direct:subroute")
.log("Start")
.process(new Processor() {
@Override
public void process(final Exchange exchange) throws Exception {
LOG.info("No problem");
}
})
.process(new Processor() {
@Override
public void process(final Exchange exchange) throws Exception {
if (exchange.getProperty(KEY) == null) {
LOG.info("Throwing");
throw new RuntimeException("Hello World");
}
else {
LOG.info("No throwing");
}
}
});

来自Camel Docs :

When using doTry .. doCatch .. doFinally then the regular Camel Error Handler does not apply. That means any onException or the likes does not trigger. The reason is that doTry .. doCatch .. doFinally is in fact its own error handler and that it aims to mimic and work like how try/catch/finally works in Java.

关于apache-camel - Camel 消息重新传递未按预期运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22719023/

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