This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch context-value-scoped-value-support
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 5eb137717f8f1154f20028fc2410eb4ef6d00337
Author: Guillaume Nodet <[email protected]>
AuthorDate: Thu Feb 19 13:18:56 2026 +0100

    Fix ContextValue scoping issues with KameletProcessor and JDK 25 compilation
    
    The ContextValue abstraction properly scopes createRoute/createProcessor
    ThreadLocals, but KameletEndpoint.doInit() relied on a leaked ThreadLocal
    value from a bug in the old createRoute(null) which cleared isSetupRoutes
    instead of isCreateRoute. Fix by capturing the route/processor context in
    KameletReifier (within the createProcessor scope) and passing them to
    KameletProcessor, which restores them during doInit() so the endpoint can
    inherit error handlers correctly.
    
    Also fix JDK 25 ScopedValue.Carrier API: use call() instead of get().
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../camel/component/kamelet/KameletProcessor.java  | 29 +++++++++++++++++++++-
 .../camel/component/kamelet/KameletReifier.java    |  8 +++++-
 .../camel/util/concurrent/ContextValueFactory.java |  3 +--
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
index 80cd3fe9b53f..0f4012e7c7c6 100644
--- 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
+++ 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletProcessor.java
@@ -43,6 +43,8 @@ public class KameletProcessor extends BaseProcessorSupport
 
     private final String name;
     private final AsyncProcessor processor;
+    private final String parentRouteId;
+    private final String parentProcessorId;
     private KameletProducer producer;
     private KameletComponent component;
     private CamelContext camelContext;
@@ -50,9 +52,16 @@ public class KameletProcessor extends BaseProcessorSupport
     private String routeId;
 
     public KameletProcessor(CamelContext camelContext, String name, Processor 
processor) throws Exception {
+        this(camelContext, name, processor, null, null);
+    }
+
+    public KameletProcessor(CamelContext camelContext, String name, Processor 
processor,
+                            String parentRouteId, String parentProcessorId) 
throws Exception {
         this.camelContext = camelContext;
         this.name = name;
         this.processor = AsyncProcessorConverterHelper.convert(processor);
+        this.parentRouteId = parentRouteId;
+        this.parentProcessorId = parentProcessorId;
     }
 
     @ManagedAttribute(description = "Kamelet name 
(templateId/routeId?options)")
@@ -118,7 +127,25 @@ public class KameletProcessor extends BaseProcessorSupport
     @Override
     protected void doInit() throws Exception {
         this.component = camelContext.getComponent("kamelet", 
KameletComponent.class);
-        this.producer = (KameletProducer) 
camelContext.getEndpoint("kamelet://" + name).createAsyncProducer();
+
+        // set the route/processor context so the KameletEndpoint.doInit() can 
pick them up
+        // these were captured during construction (within the createProcessor 
scope)
+        if (parentRouteId != null) {
+            camelContext.getCamelContextExtension().createRoute(parentRouteId);
+        }
+        if (parentProcessorId != null) {
+            
camelContext.getCamelContextExtension().createProcessor(parentProcessorId);
+        }
+        try {
+            this.producer = (KameletProducer) 
camelContext.getEndpoint("kamelet://" + name).createAsyncProducer();
+        } finally {
+            if (parentRouteId != null) {
+                camelContext.getCamelContextExtension().createRoute(null);
+            }
+            if (parentProcessorId != null) {
+                camelContext.getCamelContextExtension().createProcessor(null);
+            }
+        }
 
         ServiceHelper.initService(processor, producer);
 
diff --git 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
index dd544eacc95c..587b2e144d87 100644
--- 
a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
+++ 
b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletReifier.java
@@ -40,8 +40,14 @@ public class KameletReifier extends 
ProcessorReifier<KameletDefinition> {
         // wrap in uow
         String outputId = 
definition.idOrCreate(camelContext.getCamelContextExtension().getContextPlugin(NodeIdFactory.class));
         final Processor childProcessor = processor;
+        // capture route/processor context now (within createProcessor scope) 
for later use by KameletProcessor
+        final String parentRouteId = 
camelContext.getCamelContextExtension().getCreateRoute();
         return 
camelContext.getCamelContextExtension().createProcessor(outputId, () -> {
-            Processor answer = new KameletProcessor(camelContext, 
parseString(definition.getName()), childProcessor);
+            final String parentProcessorId = 
camelContext.getCamelContextExtension().getCreateProcessor();
+            Processor answer
+                    = new KameletProcessor(
+                            camelContext, parseString(definition.getName()), 
childProcessor,
+                            parentRouteId, parentProcessorId);
             if (answer instanceof DisabledAware da) {
                 da.setDisabled(isDisabled(camelContext, definition));
             }
diff --git 
a/core/camel-util/src/main/java25/org/apache/camel/util/concurrent/ContextValueFactory.java
 
b/core/camel-util/src/main/java25/org/apache/camel/util/concurrent/ContextValueFactory.java
index d6ce66128e38..8575a1f91705 100644
--- 
a/core/camel-util/src/main/java25/org/apache/camel/util/concurrent/ContextValueFactory.java
+++ 
b/core/camel-util/src/main/java25/org/apache/camel/util/concurrent/ContextValueFactory.java
@@ -81,8 +81,7 @@ class ContextValueFactory {
      */
     static <T, R> R where(ContextValue<T> key, T value, Supplier<R> operation) 
{
         if (key instanceof ScopedValueContextValue<T> svKey) {
-            // In JDK 25+, ScopedValue.where() returns a Carrier that has 
get() method
-            return ScopedValue.where(svKey.scopedValue, value).get(operation);
+            return ScopedValue.where(svKey.scopedValue, 
value).call(operation::get);
         } else if (key instanceof ThreadLocalContextValue<T> tlKey) {
             T oldValue = tlKey.get();
             try {

Reply via email to