This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 178cd10ff955 CAMEL-20199: Migrate context-passing ThreadLocals to
ContextValue
178cd10ff955 is described below
commit 178cd10ff9554f7cf6deb8a090f79676af66d42d
Author: Guillaume Nodet <[email protected]>
AuthorDate: Mon Aug 3 07:46:41 2026 +0200
CAMEL-20199: Migrate context-passing ThreadLocals to ContextValue
Migrate ThreadLocal usages that pass context (Exchange, config, headers)
during processing to ContextValue.newThreadLocal() in camel-xpath,
camel-datasonnet, camel-jq, camel-as2, and camel-univocity-parsers.
This is a drop-in replacement that preserves the same get()/set()/remove()
API but will automatically switch to ScopedValue on JDK 25+, enabling
proper virtual thread support.
Closes #25242
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
.../java/org/apache/camel/component/as2/api/AS2ServerConnection.java | 4 +++-
.../src/main/java/org/apache/camel/language/datasonnet/CML.java | 5 +++--
.../src/main/java/org/apache/camel/language/jq/JqFunctions.java | 3 ++-
.../org/apache/camel/dataformat/univocity/HeaderRowProcessor.java | 3 ++-
.../org/apache/camel/language/xpath/MessageVariableResolver.java | 5 +++--
.../src/main/java/org/apache/camel/language/xpath/XPathBuilder.java | 3 ++-
6 files changed, 15 insertions(+), 8 deletions(-)
diff --git
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
index ac0d565f329d..e99112afc581 100644
---
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
+++
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
@@ -42,6 +42,7 @@ import
org.apache.camel.component.as2.api.entity.MultipartSignedEntity;
import org.apache.camel.component.as2.api.io.AS2BHttpServerConnection;
import org.apache.camel.component.as2.api.protocol.ResponseMDN;
import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.concurrent.ContextValue;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.EntityDetails;
@@ -124,7 +125,8 @@ public class AS2ServerConnection {
* Stores the request-specific AS2ConsumerConfiguration and path. Used for
post-processing logic (like asynchronous
* MDN) after the main HttpService handling is complete.
*/
- private static final ThreadLocal<ThreadLocalConfigWrapper>
CURRENT_CONSUMER_CONFIG = new ThreadLocal<>();
+ private static final ContextValue<ThreadLocalConfigWrapper>
CURRENT_CONSUMER_CONFIG
+ = ContextValue.newThreadLocal("AS2ConsumerConfig");
/**
* Configuration data holding all necessary security material (signing
keys/certs and decryption keys/certs) for a
diff --git
a/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/CML.java
b/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/CML.java
index 3d82d5986919..3058ecd95e23 100644
---
a/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/CML.java
+++
b/components/camel-datasonnet/src/main/java/org/apache/camel/language/datasonnet/CML.java
@@ -42,10 +42,11 @@ import com.datasonnet.spi.DataFormatService;
import com.datasonnet.spi.Library;
import com.datasonnet.spi.PluginException;
import org.apache.camel.Exchange;
+import org.apache.camel.util.concurrent.ContextValue;
public final class CML extends Library {
private static final CML INSTANCE = new CML();
- private final ThreadLocal<Exchange> exchange = new ThreadLocal<>();
+ private final ContextValue<Exchange> exchange =
ContextValue.newThreadLocal("DataSonnetExchange");
private CML() {
}
@@ -54,7 +55,7 @@ public final class CML extends Library {
return INSTANCE;
}
- public ThreadLocal<Exchange> getExchange() {
+ public ContextValue<Exchange> getExchange() {
return exchange;
}
diff --git
a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
index 1022447b1367..a0fa85ed33a7 100644
---
a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
+++
b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqFunctions.java
@@ -35,12 +35,13 @@ import net.thisptr.jackson.jq.path.Path;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.StreamCache;
+import org.apache.camel.util.concurrent.ContextValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class JqFunctions {
- public static final ThreadLocal<Exchange> EXCHANGE_LOCAL = new
ThreadLocal<>();
+ public static final ContextValue<Exchange> EXCHANGE_LOCAL =
ContextValue.newThreadLocal("JqExchange");
private static final Logger LOGGER =
LoggerFactory.getLogger(JqFunctions.class);
diff --git
a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/HeaderRowProcessor.java
b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/HeaderRowProcessor.java
index 2b4ee4b06dbf..f4430ad68efd 100644
---
a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/HeaderRowProcessor.java
+++
b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/HeaderRowProcessor.java
@@ -18,12 +18,13 @@ package org.apache.camel.dataformat.univocity;
import com.univocity.parsers.common.ParsingContext;
import com.univocity.parsers.common.processor.RowProcessor;
+import org.apache.camel.util.concurrent.ContextValue;
/**
* This class is used by the unmarshaller in order to retrieve the headers.
*/
final class HeaderRowProcessor implements RowProcessor {
- private final static ThreadLocal<String[]> headers = new ThreadLocal<>();
+ private static final ContextValue<String[]> headers =
ContextValue.newThreadLocal("UnivocityHeaders");
/**
* Called when the processing starts, it clears the headers
diff --git
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/MessageVariableResolver.java
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/MessageVariableResolver.java
index ec43edcffdfd..a713a8aaf264 100644
---
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/MessageVariableResolver.java
+++
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/MessageVariableResolver.java
@@ -24,6 +24,7 @@ import javax.xml.xpath.XPathVariableResolver;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
+import org.apache.camel.util.concurrent.ContextValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,9 +44,9 @@ public class MessageVariableResolver implements
XPathVariableResolver {
private static final Logger LOG =
LoggerFactory.getLogger(MessageVariableResolver.class);
private Map<String, Object> variables = new HashMap<>();
- private final ThreadLocal<Exchange> exchange;
+ private final ContextValue<Exchange> exchange;
- public MessageVariableResolver(ThreadLocal<Exchange> exchange) {
+ public MessageVariableResolver(ContextValue<Exchange> exchange) {
this.exchange = exchange;
}
diff --git
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
index 80f9ebfe30d3..da44704e201a 100644
---
a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
+++
b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java
@@ -70,6 +70,7 @@ import org.apache.camel.support.service.ServiceSupport;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.concurrent.ContextValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -105,7 +106,7 @@ public class XPathBuilder extends ServiceSupport
private final Queue<XPathExpression> pool = new ConcurrentLinkedQueue<>();
private final Queue<XPathExpression> poolLogNamespaces = new
ConcurrentLinkedQueue<>();
private final String text;
- private final ThreadLocal<Exchange> exchange = new ThreadLocal<>();
+ private final ContextValue<Exchange> exchange =
ContextValue.newThreadLocal("XPathExchange");
private final MessageVariableResolver variableResolver = new
MessageVariableResolver(exchange);
private final Map<String, String> namespaces = new ConcurrentHashMap<>();
private boolean preCompile = true;