allthingssecurity opened a new pull request, #28779:
URL: https://github.com/apache/camel/pull/28779

   # Description
   
   [CAMEL-26421](https://issues.apache.org/jira/browse/CAMEL-26421)
   
   When a `doTry` calls another route (`direct`, `seda` with 
`waitForTaskToComplete`, `enrich`, ...) from its steps, or from its `doCatch` 
or `doFinally` blocks, the routing slip, dynamic router, multicast and 
recipient list of the called route do not wrap their outputs in the error 
handler, although the called route has its own error handler (a plain `to()` in 
it is redelivered as usual):
   
   - a routing slip redelivers the whole slip, so an endpoint that already 
succeeded gets the message again;
   - a multicast or recipient list does not redeliver the failed output;
   - a dynamic router that counts its calls in an exchange property, as in the 
dynamic router documentation, loses the failure.
   
   ```java
   
onException(IllegalStateException.class).maximumRedeliveries(2).redeliveryDelay(0);
   
from("direct:r0").doTry().to("direct:r1").doCatch(Exception.class).to("mock:caught").end();
   from("direct:r1").routingSlip(constant("mock:m1,direct:fail"));
   // without the doTry: mock:m1 gets 1 message, direct:fail 3 attempts; with 
it: mock:m1 gets 3
   ```
   
   Cause: `TryProcessor` sets the exchange property `TryRouteBlock` while the 
steps of the doTry (and its doCatch and doFinally blocks) run, so that 
`RoutingSlip.createErrorHandler` and `MulticastProcessor.wrapInErrorHandler` 
(CAMEL-7275) do not add an error handler to outputs of steps that have none. 
The property stayed set while the called route ran. A split is not affected: 
its steps are channels with the route's error handler.
   
   Changes:
   - `CamelInternalProcessor.RouteLifecycleAdvice` removes `TryRouteBlock` when 
an exchange enters a route and sets the caller's value again when the route is 
done. The value is the advice's state, so a route that completes asynchronously 
or calls itself is covered. A `doTry` inside the called route still turns off 
the error handler per output of its own steps.
   - The cost per route entry: outside a doTry, two removes on the exchange's 
internal properties (a remove creates no internal property map when there is 
none, CAMEL-26426); inside one, one remove and one put. Plus one slot in the 
advice state array, which the unit of work advice already allocates.
   - The same applies to a route called from the steps of a circuit breaker, 
which sets the property too: such a route now redelivers as well.
   - Upgrade guide (4.24): the called route can make more delivery attempts 
than before; when the called route handles failures (dead letter channel, or 
`onException` with `handled(true)`), a failed multicast output is now handled 
there (after its redeliveries) and no longer reaches the caller's `doCatch` 
(the routing slip, dynamic router and recipient list steps already had the 
route's error handler as a step, so for them this was already so). To turn the 
error handler per output off again: the EIP in a `doTry` with only a 
`doFinally` in the called route, or `errorHandler(noErrorHandler())` on that 
route (which also turns it off for its other steps). Neither option brings back 
the redelivery of a whole routing slip or dynamic router.
   
   Related: CAMEL-25114 restored the marker after a nested doTry (also one in a 
route called from a doTry). CAMEL-26332 (#28755, merged) and CAMEL-26333 
(#28756) fix two other defects of a route called from a doTry, in other 
properties and classes (`CamelExceptionHandled`, the error-handler-handled 
marks of `FinallyProcessor`). CAMEL-26422 (in this batch) makes the circuit 
breakers restore the same marker instead of removing it. None of them conflict 
with this change: this branch is on a main that has #28755, and `git 
merge-tree` with the branches of #28756 and CAMEL-26422 is clean. With all 
three merged on main, the doTry/doCatch/doFinally, routing slip, recipient 
list, multicast and dynamic router tests of camel-core pass (478 tests, 0 
failures, including the new tests of the three). #28750 (CAMEL-26327, routing 
slip redelivery after a nested slip) is independent: routes called from a doTry 
now take the same routing slip redelivery path as routes called without one, 
which #28750 fi
 xes for both.
   
   Tests:
   - `DoTryCalledRouteErrorHandlerTest` (camel-core, 19 tests): routing slip 
(also asynchronous), multicast, recipient list, dynamic router, a doCatch 
caller, a seda and an enrich caller, recursion, a multicast in a called route 
with a dead letter channel (handled there, the caller's doCatch does not run), 
a doTry inside the called route, and the caller's scope after a call that 
succeeded and after one that continued a failure. 10 fail on main and pass with 
the change; the other 9 (plain callers, split, a plain `to()`, a doTry inside 
the called route, the restore of the caller's scope) are controls that pass on 
both. The two restore tests fail when the restore in `after()` is replaced by a 
plain remove.
   - All tests of the core modules up to camel-core (one run): camel-core 8568 
tests, 45 skipped; camel-util 320, camel-support 145 and the other core modules 
0 failures. 21 camel-core tests in 6 classes failed: `RouteChecksumTest` (7), 
`SimpleSyntaxHintsTest` (6), `SimpleTest` (3), 
`FileProducerChecksumOfWrittenFileTest` (3), 
`FilePollEnrichDynamicFileNameTest` and `RouteWatcherReloadChangedRoutesTest`. 
Each of them fails the same way with the `CamelInternalProcessor` of main in my 
local offline build, and none of them uses a doTry. The formatter and 
import-sort plugins ran and changed nothing.
   - The new class 20 times in one JVM (380 tests) and once in each of 20 JVMs 
(380 tests): 0 failures.
   
   How it was found: a Rocq specification of Camel's routing semantics, written 
from the documentation, was compared with real Camel on generated routes; the 
case was then reduced to a plain Java DSL test.
   
   Backport: no, it changes the number of delivery attempts. 4.22.1 and 4.23.0 
behave the same as main.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 
uses the `main` branch)
   
   # Tracking
   - [x] If this is a large change, bug fix, or code improvement, I checked 
there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL-26421) 
filed for the change (usually before you start working on it): 
[CAMEL-26421](https://issues.apache.org/jira/browse/CAMEL-26421).
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful 
subject line and body.
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder 
and I have committed all auto-generated changes.
     (I built the core modules and ran the tests above, including the formatter 
and import-sort plugins. No generated file changes. I did not run the full root 
build.)
   
   # AI-assisted contributions
   
   - [x] If this PR includes AI-generated code, commits have proper 
co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR 
description identifies the AI tool used.
     The first version of the fix was written with OpenAI Codex (GPT-6); it was 
then reviewed, extended (tests, upgrade guide) and verified with Claude Code 
(Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer for each.
   
   _Claude Code on behalf of allthingssecurity_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to