-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Add ContextValue abstraction for ScopedValue support on JDK 25+ #20702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This commit introduces a new ContextValue abstraction that provides a unified API for thread-scoped data sharing, with implementations using either ThreadLocal (JDK 17+) or ScopedValue (JDK 25+ with virtual threads). Key changes: - Add ContextValue interface in camel-util with factory methods for creating context values and executing operations within scoped contexts - Add ContextValueFactory with ThreadLocal implementation for base JDK - Add Java 25 multi-release JAR variant using ScopedValue when available - Deprecate NamedThreadLocal in favor of ContextValue.newThreadLocal() - Add new scoped API methods to ExtendedCamelContext: - setupRoutes(Runnable) and setupRoutes(Callable) - createRoute(String, Runnable) and createRoute(String, Callable) - createProcessor(String, Runnable) and createProcessor(String, Callable) - Deprecate the old boolean/void signaling methods (setupRoutes(boolean), createRoute(String), createProcessor(String)) - Update DefaultCamelContextExtension to use ContextValue.where() for scoped execution, enabling proper ScopedValue support on virtual threads - Update DefaultReactiveExecutor to use ContextValue instead of NamedThreadLocal - Simplify Worker class by removing cached stats field The ContextValue abstraction allows Camel to leverage ScopedValue on JDK 25+ when virtual threads are enabled, providing better performance characteristics for virtual thread workloads while maintaining backward compatibility with ThreadLocal on older JDK versions. Documentation added to ContextValue explaining that ThreadLocal variants should hold lightweight objects to avoid memory leaks with pooled threads.
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🤖 CI automation will test this PR automatically. 🐫 Apache Camel Committers, please review the following items:
|
Add two disabled load test classes that can be run manually to compare
performance between platform threads and virtual threads:
- VirtualThreadsLoadTest: Uses SEDA with concurrent consumers to test
throughput with simulated I/O delays
- VirtualThreadsWithThreadsDSLLoadTest: Uses threads() DSL to exercise
the ContextValue/ScopedValue code paths
Tests are disabled by default and configurable via system properties:
- loadtest.messages: Number of messages to process (default: 5000)
- loadtest.producers: Number of producer threads (default: 50)
- loadtest.consumers: Number of concurrent consumers (default: 100)
- loadtest.delay: Simulated I/O delay in ms (default: 5-10)
Run with:
mvn test -Dtest=VirtualThreadsLoadTest \
-Djunit.jupiter.conditions.deactivate='org.junit.*DisabledCondition' \
-Dcamel.threads.virtual.enabled=true
|
I think its best to wait this kind of changes in core until after 4.18 LTS next month. Then we have an open path to do more bigger changes leading up for SB v4, Jackson 3, JUnit 6, Java 25 and other tasks that are more impactful. Camel 4.18 LTS is expected to be similar to 4.14.x but as the last release supporting SB 3 that end users can use as a stable place. |
Extract template method hooks in SedaConsumer to allow subclasses to customize polling behavior without duplicating the entire doRun() loop: - beforePoll(): Called before polling, returns true to proceed or false to skip this iteration. Allows acquiring resources like permits. - afterPollEmpty(): Called when poll returns no message. Allows releasing resources. - processPolledExchange(Exchange): Processes the polled exchange. Default is inline processing; can be overridden to dispatch to another thread. Also made these methods protected for subclass access: - createExecutor(int poolSize): Creates the executor service - setupTasks(): Sets up thread pool and tasks - shutdownExecutor(): Shuts down executors - isShutdownPending()/setShutdownPending(): Access shutdown state - pollTimeout field: Made protected ThreadPerTaskSedaConsumer now simply overrides these hooks instead of duplicating the entire polling loop, reducing code from 223 to 158 lines and improving maintainability.
Summary
This PR introduces a new
ContextValueabstraction that provides a unified API for thread-scoped data sharing, with implementations using eitherThreadLocal(JDK 17+) orScopedValue(JDK 25+ with virtual threads).Related to: https://issues.apache.org/jira/browse/CAMEL-20199
Key Changes
New ContextValue API
ContextValueinterface in camel-util with factory methods for creating context values and executing operations within scoped contextsContextValueFactorywith ThreadLocal implementation for base JDKScopedValuewhen available and virtual threads are enabledAPI Improvements in ExtendedCamelContext
setupRoutes(Runnable)andsetupRoutes(Callable<T>)createRoute(String, Runnable)andcreateRoute(String, Callable<T>)createProcessor(String, Runnable)andcreateProcessor(String, Callable<T>)setupRoutes(boolean),createRoute(String),createProcessor(String))Deprecations
NamedThreadLocalin favor ofContextValue.newThreadLocal()Implementation Updates
DefaultCamelContextExtensionto useContextValue.where()for scoped executionDefaultReactiveExecutorto useContextValueinstead ofNamedThreadLocalWorkerclass by removing cachedstatsfield (now readsstatisticsEnableddirectly)Benefits
The
ContextValueabstraction allows Camel to leverageScopedValueon JDK 25+ when virtual threads are enabled, providing:ThreadLocalon older JDK versionsDocumentation
Added documentation to
ContextValueexplaining that ThreadLocal variants should hold lightweight objects to avoid memory leaks with pooled threads.