Claus Ibsen created CAMEL-25115:
-----------------------------------
Summary: camel-core - Error handler failure paths: fix bugs found
in a deep review
Key: CAMEL-25115
URL: https://issues.apache.org/jira/browse/CAMEL-25115
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: Claus Ibsen
A deep look at the failure paths of the error handler (RedeliveryErrorHandler,
FatalFallbackErrorHandler, DefaultExceptionPolicyStrategy,
OnCompletionProcessor and DefaultErrorRegistry) found the following bugs:
# An onException *onWhen* predicate that throws an exception escaped from the
error handler. It is now logged at WARN and regarded as not matching, so
another onException (or the error handler) handles the exchange.
# A *handled*, *continued* or *retryWhile* predicate that throws an exception
replaced the original exception, and the onException outputs / dead letter
channel were skipped. It is now logged at WARN and regarded as false; the
original exception is kept (the predicate exception is attached as suppressed),
and the exchange is still delivered to the failure processor / dead letter
channel.
# FatalFallbackErrorHandler kept its "running under" route ids in a mutable
deque stored as an exchange property, which copies of the exchange
(splitter/multicast with parallel processing) share. This could detect a
circular error handler that is not circular (a sibling copy running the same
route), and the property was never removed. Entries are now tied to the
exchange instance, and the property is removed when empty.
# An exception from *onPrepareFailure* was set on the exchange, which was then
still sent to the dead letter queue / failure processor. The exchange is now
not delivered, and the new exception is handled according to
deadLetterHandleNewException (the original exception is attached as
suppressed). This also covers the processor being wrapped and setting the
exception on the exchange instead of throwing.
# DefaultErrorRegistry recorded every failure-handled event as handled, also
when the onException did not handle the exception. The handled flag now comes
from the exchange (a doCatch, which does not set the error handler flag, is
still handled).
# An exception from *onRedelivery* was set on the exchange which was then
redelivered with the exception on it (a single output processor would process
it anyway). It is now treated as a new failure.
# After continued(true), a later unrelated exception on the same exchange got
the continued exception attached as suppressed (a "previous" exception).
# OnCompletionProcessor did not reset failureHandled before running the
onCompletion, so an onException could not handle a failure inside an
onFailureOnly completion, and a handled failure inside the onCompletion leaked
EXCEPTION_CAUGHT and the error handler handled flag onto the (successful)
exchange.
# RedeliveryTask.run() did not release the pooled task when an unexpected
exception was caught.
The fixes are applied to both the non-redelivery (SimpleTask) and redelivery
(RedeliveryTask) paths.
*Not changed*
* Recursion detection design: a route runs twice before the circuit is
detected, and a dead letter queue route inheriting the dead letter channel.
* The NoErrorHandler bridge case.
* The isSame heuristic in the error handler.
* The ERRORHANDLER_CIRCUIT_DETECTED property is set but not used by Camel.
* The SimpleTask redelivery policy branch that is never used (tracked in
CAMEL-24980).
_Claude Code on behalf of Claus Ibsen_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)