Apache Camel 运行 onCompletion 的一部分并且不显示堆栈跟踪
Apache Camel runs part of onCompletion and doesn't show stack trace
我正在尝试使用 Camel 一次轮询路由,如果文件存在则使用它,如果不存在则记录错误。
默认情况下,如果文件不存在,路由将不执行任何操作,因此我首先将 consumer.sendEmptyMessageWhenIdle=true
添加到 URI。然后我检查 null body 来决定是记录异常还是继续:
from(theFileUri)
.onCompletion()
.onCompleteOnly()
.log("SUCCESS")
.bean(theOtherAction, "start")
.end()
.onException(Exception.class)
.logStackTrace(true)
.log(ERROR, "Failed to load file")
.handled(true)
.end()
.choice()
.when(body().isNotNull())
.to(NEXT_ROUTE_URI)
.endChoice()
.otherwise()
.throwException(new FileNotFoundException(theFileUri))
.endChoice();
这有两个问题:
- 如果文件丢失,成功日志仍然会出现(但不是 bean!)
- 未打印堆栈跟踪
如果有更好的方法,那么我欢迎提出建议,但我也想知道我在这个方法中做错了什么。
我仍然不完全清楚发生了什么。但是,我认为 onException
调用需要从链中分离出来。在我看来 logStackTrace
仅适用于重新投递尝试。尝试次数默认为 0,这就是我想要的。从 Java DSL 访问异常的唯一方法似乎是自定义 Processor
。 The getException()
method will return null
if you are using handled(true)
so you must use Exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class)
.
我还怀疑来自 onCompletion 的日志消息是由于它 running in parallel 在异常中止之前:
Camel 2.13 or older - On completion runs in separate thread Icon The
onCompletion runs in a separate thread in parallel with the original
route. It is therefore not intended to influence the outcome of the
original route. The idea for on completion is to spin off a new thread
to eg send logs to a central log database, send an email, send alterts
to a monitoring system, store a copy of the result message etc.
Therefore if you want to do some work that influence the original
route, then do not use onCompletion for that. Notice: if you use the
UnitOfWork API as mentioned in the top of this page, then you can
register a Synchronization callback on the Exchange which is executed
in the original route. That way allows you to do some custom code when
the route is completed; this is how custom components can enlist on
completion services which they need, eg the File component does that
for work that moves/deletes the original file etc.
因为我不想运行这个代码异常,我想我可以中止异常的路由。
我目前有这个:
onException(Exception.class)
.handled(true)
.process(new Processor()
{
@Override
public void process(Exchange anExchange) throws Exception
{
Exception myException = anExchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
LOGGER.error("Failed to load", myException);
}
});
from(theFileUri)
.choice()
.when(body().isNotNull())
.to(NEXT_ROUTE_URI)
.log("SUCCESS")
.bean(theOtherAction, "start")
.endChoice()
.otherwise()
.throwException(new FileNotFoundException(theFileUri));
我正在尝试使用 Camel 一次轮询路由,如果文件存在则使用它,如果不存在则记录错误。
默认情况下,如果文件不存在,路由将不执行任何操作,因此我首先将 consumer.sendEmptyMessageWhenIdle=true
添加到 URI。然后我检查 null body 来决定是记录异常还是继续:
from(theFileUri)
.onCompletion()
.onCompleteOnly()
.log("SUCCESS")
.bean(theOtherAction, "start")
.end()
.onException(Exception.class)
.logStackTrace(true)
.log(ERROR, "Failed to load file")
.handled(true)
.end()
.choice()
.when(body().isNotNull())
.to(NEXT_ROUTE_URI)
.endChoice()
.otherwise()
.throwException(new FileNotFoundException(theFileUri))
.endChoice();
这有两个问题:
- 如果文件丢失,成功日志仍然会出现(但不是 bean!)
- 未打印堆栈跟踪
如果有更好的方法,那么我欢迎提出建议,但我也想知道我在这个方法中做错了什么。
我仍然不完全清楚发生了什么。但是,我认为 onException
调用需要从链中分离出来。在我看来 logStackTrace
仅适用于重新投递尝试。尝试次数默认为 0,这就是我想要的。从 Java DSL 访问异常的唯一方法似乎是自定义 Processor
。 The getException()
method will return null
if you are using handled(true)
so you must use Exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class)
.
我还怀疑来自 onCompletion 的日志消息是由于它 running in parallel 在异常中止之前:
Camel 2.13 or older - On completion runs in separate thread Icon The onCompletion runs in a separate thread in parallel with the original route. It is therefore not intended to influence the outcome of the original route. The idea for on completion is to spin off a new thread to eg send logs to a central log database, send an email, send alterts to a monitoring system, store a copy of the result message etc. Therefore if you want to do some work that influence the original route, then do not use onCompletion for that. Notice: if you use the UnitOfWork API as mentioned in the top of this page, then you can register a Synchronization callback on the Exchange which is executed in the original route. That way allows you to do some custom code when the route is completed; this is how custom components can enlist on completion services which they need, eg the File component does that for work that moves/deletes the original file etc.
因为我不想运行这个代码异常,我想我可以中止异常的路由。
我目前有这个:
onException(Exception.class)
.handled(true)
.process(new Processor()
{
@Override
public void process(Exchange anExchange) throws Exception
{
Exception myException = anExchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
LOGGER.error("Failed to load", myException);
}
});
from(theFileUri)
.choice()
.when(body().isNotNull())
.to(NEXT_ROUTE_URI)
.log("SUCCESS")
.bean(theOtherAction, "start")
.endChoice()
.otherwise()
.throwException(new FileNotFoundException(theFileUri));