[
https://issues.apache.org/jira/browse/CAMEL-26741?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Work on CAMEL-26741 started by shashank.
----------------------------------------
> camel-core - an Error thrown by a plain Processor escapes after the callback:
> the route continues as if it succeeded and the exchange stays inflight
> ----------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-26741
> URL: https://issues.apache.org/jira/browse/CAMEL-26741
> Project: Camel
> Issue Type: Bug
> Components: camel-core
> Reporter: shashank
> Assignee: shashank
> Priority: Major
>
> A plain {{Processor}} is called as an {{AsyncProcessor}} through an adapter:
> {{DelegateSyncProcessor}} for {{process(...)}}, the bridge of
> {{AsyncProcessorConverterHelper}} (for example a producer that is not an
> {{AsyncProcessor}}), and the Processor adapter of the bean component
> ({{AbstractBeanProcessor.useCustomAdapter}}, for a bean that is a
> {{Processor}}). Each calls the callback in {{finally}}, but catches only
> exceptions ({{DelegateSyncProcessor}} also {{LinkageError}}, the bean adapter
> also {{AssertionError}}). Any other {{Error}}, such as an {{AssertionError}}
> in a test processor or a custom {{Error}}, is thrown on after the callback
> was called:
> * the exchange has no exception, so the callback continues it and the next
> steps run as if the processor had succeeded;
> * the error handler, {{onException}} and {{doCatch}} never see the {{Error}};
> * the {{Error}} leaves the reactive executor's loop, so work already queued
> there is left behind: the exchange stays inflight, the context stop waits its
> whole shutdown timeout, and the queued work may run later on another
> exchange's send.
> {code:java}
> from("direct:start")
> .onException(Error.class).handled(true).to("mock:handled").end()
> .process(e -> { throw new Error("boom"); })
> .to("mock:result");
> {code}
> On main, without the {{onException}}, {{template.send("direct:start", ...)}}
> throws the {{Error}} to the caller and the exchange stays inflight; with it,
> {{mock:handled}} receives nothing and {{mock:result}} receives the message.
> Stopping the context with a 5 second shutdown timeout then took 5 s.
> Camel already treats an {{Error}} of a step as a failure elsewhere: the error
> handlers and {{CamelInternalProcessor}} catch {{Throwable}} when a processor
> throws before calling its callback (CAMEL-26464),
> {{DefaultErrorHandlerCatchThrowableTest}} expects a {{NoSuchMethodError}} of
> a processor to fail the exchange, CAMEL-16821 made the bean adapter fail the
> exchange on an {{AssertionError}}, and CAMEL-19497 moved its callback into
> {{finally}} so that "unhandled exceptions" do not block. CAMEL-19748 narrowed
> these catches from {{Throwable}}, as catching JVM errors can be dangerous;
> here the {{Error}} is not passed on cleanly either, as the callback was
> already called.
> Seen while building the exchange sanitizer (CAMEL-26714): an {{Error}} of a
> plain {{Processor}} breaks the rule "call the callback exactly once, and do
> not throw from process" in Camel's adapter, not in the processor.
> Suggested fix: the three adapters catch {{Throwable}} and set it on the
> exchange (an {{Error}} is wrapped in a {{CamelExecutionException}} by
> {{setException}}), so the exchange fails and error handling applies, as for
> an exception. This changes behaviour for an {{Error}}, so it needs an upgrade
> guide note.
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)