allthingssecurity opened a new pull request, #28757: URL: https://github.com/apache/camel/pull/28757
# Description [CAMEL-26334](https://issues.apache.org/jira/browse/CAMEL-26334) `OnceConsumer` created a `java.util.Timer` in its constructor (`new Timer(endpoint.getName())`, a non-daemon thread named after the endpoint) and never cancelled it; `doStop` only cancelled the `TimerTask`. The thread stayed alive after the route was stopped and after the CamelContext was stopped, and after the route was removed it ended only when the consumer was garbage collected (the cleaner of `java.util.Timer`). So every once route that was created, or reloaded in dev mode, kept a non-daemon thread until then. A once route that was stopped and started again did not start: `doStart` scheduled the cancelled `TimerTask` again and failed with `IllegalStateException: Task already scheduled or cancelled`. A CamelContext with a once route that was stopped and started again failed to start the same way, and so did the resume of a suspended once route (the consumer cannot be suspended, so the route controller stops and starts it). Changes (`OnceConsumer`): - The consumer fires on a single thread scheduled executor that `doStart` creates through the `ExecutorServiceManager` (`newSingleThreadScheduledExecutor(this, endpoint.getName())`, so the thread is named `Camel (<context>) thread #N - <name>` and the pool is managed like the other Camel pools). - `doStop` cancels the pending fire with `cancel(false)`, so a fire that is routing an exchange is not interrupted (as with `TimerTask.cancel()`), and shuts the executor down. - Each start schedules a new fire, so a restarted route fires again, which is what `doStop` resetting `scheduled` meant. - `scheduleTask(TimerTask, Timer)` is replaced by `scheduleTask()`; it does nothing before the consumer started (no executor yet). - This also removes the `TimerTask` from camel-once, which CAMEL-22957 listed for virtual thread support. Docs: upgrade guide 4.24, a `camel-once` entry (the thread name, the restart, the protected method). Tests: new `OnceConsumerLifecycleTest` (5 tests, latches and `Thread.join`, no sleeps; JUnit assertions, the module has no AssertJ dependency): - `theThreadEndsWhenTheCamelContextStops` - `theThreadEndsWhenTheRouteIsRemovedBeforeItFired` (`delay=3600000`) - `noThreadIsLeftPerRouteThatWasAddedAndRemoved` (20 routes added, fired, stopped and removed) - `aRouteThatIsStartedAgainFiresAgain` - `aRouteFiresAgainWhenTheCamelContextIsStartedAgain` All 5 fail on main (the first three list the non-daemon threads still alive after 10 s, the last two with the `IllegalStateException`) and pass with the fix. camel-once: 16 tests, 0 failures. Also checked with a throwaway test: a suspended and resumed once route fires again (on main the resume fails with the same exception), and a route with `autoStartup=false` fires only when it is started, as on main. The formatter and import-sort plugins ran on the final files (a second run: 0 formatted, already sorted). Backport: the same code is on 4.18.x and 4.22.x (since 4.17.0). The thread name changes, so it can stay on main, or go back with the guide note. # 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-26334) filed for the change (usually before you start working on it): [CAMEL-26334](https://issues.apache.org/jira/browse/CAMEL-26334). # 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 camel-once with the core modules and ran its tests, including the formatter and import-sort plugins. No option or 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. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _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]
