CAMEL-20199: Migrate context-passing ThreadLocals to ContextValue - #25242
CAMEL-20199: Migrate context-passing ThreadLocals to ContextValue#25242gnodet wants to merge 1 commit into
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
🔬 Scalpel shadow comparison — Scalpel: 475 tested, 29 compile-only — current: 475 all testedMaveniverse Scalpel detected 504 affected modules (current approach: 475).
|
gnodet
left a comment
There was a problem hiding this comment.
Mechanically correct ThreadLocal-to-ContextValue migration that passes CI on JDK 17 and 25. The choice of ContextValue.newThreadLocal() is appropriate for the mutable set()/get()/remove() pattern used at all call sites.
Public API compatibility note:
Three public API signatures change from ThreadLocal<Exchange> to ContextValue<Exchange>. Since ContextValue is an interface (not a subclass of ThreadLocal), these are binary-incompatible changes — compiled code referencing the old types will fail at runtime with NoSuchMethodError/NoSuchFieldError. Source compatibility is preserved since ContextValue exposes the same get()/set()/remove() methods.
The affected APIs:
CML.getExchange()return type — low external impact (datasonnet integration internals)JqFunctions.EXCHANGE_LOCALfield type — most impactful, as custom JQ functions loaded via ServiceLoader use this field to access the Exchange during evaluationMessageVariableResolverconstructor parameter type — very low impact (only called internally byXPathBuilder)
Per project conventions, consider adding a brief entry in docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc noting the type changes in camel-datasonnet, camel-jq, and camel-xpath. The 4.22 upgrade guide is thorough at documenting every user-visible change.
Minor improvement opportunity (not blocking):
The set()/try/finally { remove() } pattern in DatasonnetExpression.evaluate() and JqExpression.evaluate() is exactly the pattern that ContextValue.where() was designed to replace — it would provide safer scoped binding and prepare for a future migration to ContextValue.newInstance() (ScopedValue on JDK 25+).
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
Summary
Claude Code on behalf of gnodet
Part of CAMEL-20199: Complete support of Virtual Threads.
Migrates
ThreadLocalusages that pass context (Exchange, config, headers) during processing toContextValue.newThreadLocal(). This is a drop-in replacement that preserves the sameget()/set()/remove()API but will automatically switch toScopedValueon JDK 25+, enabling proper virtual thread support.Components migrated:
XPathBuilder.javaandMessageVariableResolver.java:ThreadLocal<Exchange>for XPath variable resolutionCML.java:ThreadLocal<Exchange>for DataSonnet library function accessJqFunctions.java:EXCHANGE_LOCALThreadLocal for JQ custom functionsAS2ServerConnection.java:CURRENT_CONSUMER_CONFIGThreadLocal for request-scoped MDN processingHeaderRowProcessor.java:ThreadLocal<String[]>for parsed CSV/TSV headersTest plan
🤖 Generated with Claude Code