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 64d78b0e8b1b CAMEL-26664: camel-dapr - use CamelDaprConfigKeys header 
for configuration operation (#29563)
64d78b0e8b1b is described below

commit 64d78b0e8b1baa6f1f550cc2cca5caf289ffb205
Author: Jiří Ondrušek <[email protected]>
AuthorDate: Wed Nov 11 19:51:34 2026 +0100

    CAMEL-26664: camel-dapr - use CamelDaprConfigKeys header for configuration 
operation (#29563)
    
    camel-dapr: the configuration operation now uses the CamelDaprConfigKeys 
header it validates,
    instead of ignoring it.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../org/apache/camel/catalog/components/dapr.json  |  2 +-
 .../apache/camel/catalog/docs/dapr-component.adoc  | 54 +++++++++++++++++++---
 .../org/apache/camel/component/dapr/dapr.json      |  2 +-
 .../camel-dapr/src/main/docs/dapr-component.adoc   | 54 +++++++++++++++++++---
 .../dapr/DaprConfigurationOptionsProxy.java        | 14 +++++-
 .../apache/camel/component/dapr/DaprConstants.java |  4 +-
 .../dapr/operations/DaprConfigurationTest.java     | 44 ++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |  6 +++
 .../endpoint/dsl/DaprEndpointBuilderFactory.java   |  3 +-
 9 files changed, 164 insertions(+), 19 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dapr.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dapr.json
index 99c175b6f72f..b1a6022acf6a 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dapr.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dapr.json
@@ -100,7 +100,7 @@
     "CamelDaprTraceState": { "index": 29, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Gets additional vendor-specific trace context", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#TRACE_STATE" },
     "CamelDaprBindingName": { "index": 30, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "The name of the Dapr binding to invoke", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#BINDING_NAME" },
     "CamelDaprBindingOperation": { "index": 31, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "String", "deprecated": false, "autowired": false, "secret": false, 
"description": "The operation to perform on the binding", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#BINDING_OPERATION" },
-    "CamelDaprConfigKeys": { "index": 32, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "List of keys for configuration operation", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#CONFIG_KEYS" },
+    "CamelDaprConfigKeys": { "index": 32, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Keys for configuration operation, as a comma-separated String 
or a Collection of keys", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#CONFIG_KEYS" },
     "CamelDaprSubscriptionId": { "index": 33, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "The id for configuration change subscription", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#SUBSCRIPTION_ID" },
     "CamelDaprRawConfigResponse": { "index": 34, "kind": "header", 
"displayName": "", "group": "common", "label": "common", "required": false, 
"javaType": "Map<String, io.dapr.client.domain.ConfigurationItem", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
raw configuration update response", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#RAW_CONFIG_RESPONSE" },
     "CamelDaprLockOperation": { "index": 35, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"LockOperation", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "tryLock", "description": "The lock operation to perform on the 
store. Required for DaprOperation.lock operation", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#LOCK_OPERATION" },
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dapr-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dapr-component.adoc
index 5d5899e99e45..786db40ca8a5 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dapr-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dapr-component.adoc
@@ -529,18 +529,58 @@ YAML::
 
 - `configuration` -
 
-._Java-only: uses `List.of()` to set configuration key list_
+The `CamelDaprConfigKeys` header takes the place of the `configKeys` option. 
It is a comma-separated String or a
+`Collection` of keys.
+
+[tabs]
+====
+Java::
++
 [source,java]
 ----
 from("direct:start")
-    .process(exchange -> {
-        exchange.getIn().setHeader("CamelDaprConfigKeys", List.of("k1", "k2"));
-    })
-    .to("dapr:configuration?configStore=myStore")
-    .log("Received config updates from Dapr: ${body}")
-    .to("mock:result");
+  .setHeader("CamelDaprConfigKeys", constant("k1,k2"))
+  .to("dapr:configuration?configStore=myStore")
+  .log("Received config updates from Dapr: ${body}")
+  .to("mock:result");
 ----
 
+XML::
++
+[source,xml]
+----
+<route>
+  <from uri="direct:start"/>
+  <setHeader name="CamelDaprConfigKeys">
+    <constant>k1,k2</constant>
+  </setHeader>
+  <to uri="dapr:configuration?configStore=myStore"/>
+  <log message="Received config updates from Dapr: ${body}"/>
+  <to uri="mock:result"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:start
+      steps:
+        - setHeader:
+            name: CamelDaprConfigKeys
+            constant: "k1,k2"
+        - to:
+            uri: dapr:configuration
+            parameters:
+              configStore: myStore
+        - log: "Received config updates from Dapr: ${body}"
+        - to:
+            uri: mock:result
+----
+====
+
 - `lock: tryLock` -
 
 [tabs]
diff --git 
a/components/camel-dapr/src/generated/resources/META-INF/org/apache/camel/component/dapr/dapr.json
 
b/components/camel-dapr/src/generated/resources/META-INF/org/apache/camel/component/dapr/dapr.json
index 99c175b6f72f..b1a6022acf6a 100644
--- 
a/components/camel-dapr/src/generated/resources/META-INF/org/apache/camel/component/dapr/dapr.json
+++ 
b/components/camel-dapr/src/generated/resources/META-INF/org/apache/camel/component/dapr/dapr.json
@@ -100,7 +100,7 @@
     "CamelDaprTraceState": { "index": 29, "kind": "header", "displayName": "", 
"group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Gets additional vendor-specific trace context", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#TRACE_STATE" },
     "CamelDaprBindingName": { "index": 30, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "The name of the Dapr binding to invoke", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#BINDING_NAME" },
     "CamelDaprBindingOperation": { "index": 31, "kind": "header", 
"displayName": "", "group": "producer", "label": "producer", "required": false, 
"javaType": "String", "deprecated": false, "autowired": false, "secret": false, 
"description": "The operation to perform on the binding", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#BINDING_OPERATION" },
-    "CamelDaprConfigKeys": { "index": 32, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "List of keys for configuration operation", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#CONFIG_KEYS" },
+    "CamelDaprConfigKeys": { "index": 32, "kind": "header", "displayName": "", 
"group": "producer", "label": "producer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Keys for configuration operation, as a comma-separated String 
or a Collection of keys", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#CONFIG_KEYS" },
     "CamelDaprSubscriptionId": { "index": 33, "kind": "header", "displayName": 
"", "group": "consumer", "label": "consumer", "required": false, "javaType": 
"String", "deprecated": false, "autowired": false, "secret": false, 
"description": "The id for configuration change subscription", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#SUBSCRIPTION_ID" },
     "CamelDaprRawConfigResponse": { "index": 34, "kind": "header", 
"displayName": "", "group": "common", "label": "common", "required": false, 
"javaType": "Map<String, io.dapr.client.domain.ConfigurationItem", 
"deprecated": false, "autowired": false, "secret": false, "description": "The 
raw configuration update response", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#RAW_CONFIG_RESPONSE" },
     "CamelDaprLockOperation": { "index": 35, "kind": "header", "displayName": 
"", "group": "producer", "label": "producer", "required": false, "javaType": 
"LockOperation", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "tryLock", "description": "The lock operation to perform on the 
store. Required for DaprOperation.lock operation", "constantName": 
"org.apache.camel.component.dapr.DaprConstants#LOCK_OPERATION" },
diff --git a/components/camel-dapr/src/main/docs/dapr-component.adoc 
b/components/camel-dapr/src/main/docs/dapr-component.adoc
index 5d5899e99e45..786db40ca8a5 100644
--- a/components/camel-dapr/src/main/docs/dapr-component.adoc
+++ b/components/camel-dapr/src/main/docs/dapr-component.adoc
@@ -529,18 +529,58 @@ YAML::
 
 - `configuration` -
 
-._Java-only: uses `List.of()` to set configuration key list_
+The `CamelDaprConfigKeys` header takes the place of the `configKeys` option. 
It is a comma-separated String or a
+`Collection` of keys.
+
+[tabs]
+====
+Java::
++
 [source,java]
 ----
 from("direct:start")
-    .process(exchange -> {
-        exchange.getIn().setHeader("CamelDaprConfigKeys", List.of("k1", "k2"));
-    })
-    .to("dapr:configuration?configStore=myStore")
-    .log("Received config updates from Dapr: ${body}")
-    .to("mock:result");
+  .setHeader("CamelDaprConfigKeys", constant("k1,k2"))
+  .to("dapr:configuration?configStore=myStore")
+  .log("Received config updates from Dapr: ${body}")
+  .to("mock:result");
 ----
 
+XML::
++
+[source,xml]
+----
+<route>
+  <from uri="direct:start"/>
+  <setHeader name="CamelDaprConfigKeys">
+    <constant>k1,k2</constant>
+  </setHeader>
+  <to uri="dapr:configuration?configStore=myStore"/>
+  <log message="Received config updates from Dapr: ${body}"/>
+  <to uri="mock:result"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:start
+      steps:
+        - setHeader:
+            name: CamelDaprConfigKeys
+            constant: "k1,k2"
+        - to:
+            uri: dapr:configuration
+            parameters:
+              configStore: myStore
+        - log: "Received config updates from Dapr: ${body}"
+        - to:
+            uri: mock:result
+----
+====
+
 - `lock: tryLock` -
 
 [tabs]
diff --git 
a/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConfigurationOptionsProxy.java
 
b/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConfigurationOptionsProxy.java
index b8a1177720f5..9333f3be8329 100644
--- 
a/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConfigurationOptionsProxy.java
+++ 
b/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConfigurationOptionsProxy.java
@@ -18,10 +18,13 @@ package org.apache.camel.component.dapr;
 
 import java.time.Duration;
 import java.time.Instant;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 import java.util.function.Supplier;
+import java.util.stream.Stream;
 
 import io.dapr.client.domain.HttpExtension;
 import io.dapr.client.domain.State;
@@ -166,7 +169,16 @@ public class DaprConfigurationOptionsProxy {
     }
 
     public List<String> getConfigKeysAsList(final Exchange exchange) {
-        return configuration.getConfigKeysAsList();
+        // the header can be a Collection of keys or a comma-separated String
+        Object header = ObjectHelper.isEmpty(exchange) ? null : 
exchange.getIn().getHeader(DaprConstants.CONFIG_KEYS);
+        Object configKeys = ObjectHelper.isEmpty(header) ? 
configuration.getConfigKeys() : header;
+        if (configKeys == null) {
+            return null;
+        }
+        Stream<?> keys = configKeys instanceof Collection<?> collection
+                ? collection.stream()
+                : Arrays.stream(configKeys.toString().split(","));
+        return keys.map(key -> String.valueOf(key).trim()).filter(key -> 
!key.isEmpty()).toList();
     }
 
     public LockOperation getLockOperation(final Exchange exchange) {
diff --git 
a/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConstants.java
 
b/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConstants.java
index 193b2d003b5c..8d50fa7f698f 100644
--- 
a/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConstants.java
+++ 
b/components/camel-dapr/src/main/java/org/apache/camel/component/dapr/DaprConstants.java
@@ -129,7 +129,9 @@ public class DaprConstants {
     public static final String BINDING_NAME = HEADER_PREFIX + "BindingName";
     @Metadata(label = "producer", description = "The operation to perform on 
the binding", javaType = "String")
     public static final String BINDING_OPERATION = HEADER_PREFIX + 
"BindingOperation";
-    @Metadata(label = "producer", description = "List of keys for 
configuration operation", javaType = "String")
+    @Metadata(label = "producer",
+              description = "Keys for configuration operation, as a 
comma-separated String or a Collection of keys",
+              javaType = "String")
     public static final String CONFIG_KEYS = HEADER_PREFIX + "ConfigKeys";
     @Metadata(label = "consumer", description = "The id for configuration 
change subscription", javaType = "String")
     public static final String SUBSCRIPTION_ID = HEADER_PREFIX + 
"SubscriptionId";
diff --git 
a/components/camel-dapr/src/test/java/org/apache/camel/component/dapr/operations/DaprConfigurationTest.java
 
b/components/camel-dapr/src/test/java/org/apache/camel/component/dapr/operations/DaprConfigurationTest.java
index 42f198319bf9..944a85074cab 100644
--- 
a/components/camel-dapr/src/test/java/org/apache/camel/component/dapr/operations/DaprConfigurationTest.java
+++ 
b/components/camel-dapr/src/test/java/org/apache/camel/component/dapr/operations/DaprConfigurationTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.dapr.operations;
 
+import java.util.List;
 import java.util.Map;
 
 import io.dapr.client.DaprClient;
@@ -31,6 +32,7 @@ import org.apache.camel.support.DefaultExchange;
 import org.apache.camel.test.junit6.CamelTestSupport;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import reactor.core.publisher.Mono;
@@ -40,6 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
@@ -74,6 +77,47 @@ public class DaprConfigurationTest extends CamelTestSupport {
         assertEquals(mockResponse, 
operationResponse.getHeaders().get(DaprConstants.RAW_CONFIG_RESPONSE));
     }
 
+    @Test
+    void testConfigKeysFromHeader() {
+        assertEquals(List.of("key1", "key2"), sentConfigKeys("endpointKey", 
"key1,key2"));
+    }
+
+    @Test
+    void testConfigKeysFromListHeader() {
+        assertEquals(List.of("key1", "key2"), sentConfigKeys("endpointKey", 
List.of("key1", " key2 ")));
+    }
+
+    @Test
+    void testConfigKeysFromHeaderAreTrimmed() {
+        assertEquals(List.of("key1", "key2"), sentConfigKeys("endpointKey", " 
key1, ,key2 ,"));
+    }
+
+    @Test
+    void testConfigKeysFromEndpointWithoutHeader() {
+        assertEquals(List.of("k1", "k2"), sentConfigKeys("k1, k2", null));
+    }
+
+    private List<String> sentConfigKeys(String endpointKeys, Object header) {
+        when(endpoint.getClient()).thenReturn(client);
+        
when(client.getConfiguration(any(GetConfigurationRequest.class))).thenReturn(Mono.just(Map.of()));
+
+        DaprConfiguration configuration = new DaprConfiguration();
+        configuration.setOperation(DaprOperation.configuration);
+        configuration.setConfigStore("myStore");
+        configuration.setConfigKeys(endpointKeys);
+        DaprConfigurationOptionsProxy configurationOptionsProxy = new 
DaprConfigurationOptionsProxy(configuration);
+
+        final Exchange exchange = new DefaultExchange(context);
+        exchange.getMessage().setHeader(DaprConstants.CONFIG_KEYS, header);
+
+        final DaprConfigurationHandler operation = new 
DaprConfigurationHandler(configurationOptionsProxy, endpoint);
+        operation.handle(exchange);
+
+        ArgumentCaptor<GetConfigurationRequest> captor = 
ArgumentCaptor.forClass(GetConfigurationRequest.class);
+        verify(client).getConfiguration(captor.capture());
+        return captor.getValue().getKeys();
+    }
+
     @Test
     void testValidateConfiguration() {
         DaprConfiguration configuration = new DaprConfiguration();
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index fbdd21a41b32..0de0af1acc7a 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -1346,6 +1346,12 @@ The other operations do not change: the `state` 
operations still take the key fr
 other operations still take the metadata from the `CamelDaprMetadata` header, 
and the other `CamelDapr*` headers still
 take the place of the options of the endpoint, as before.
 
+=== camel-dapr - the CamelDaprConfigKeys header takes the place of the 
configKeys option
+
+The `configuration` operation of the `dapr` producer ignored the 
`CamelDaprConfigKeys` header and always sent the keys
+of the `configKeys` option of the endpoint. It now sends the keys of the 
header when it is set: a comma-separated String
+or a `Collection` of keys. A route that set this header, but relied on the 
keys of the endpoint, must remove the header.
+
 === camel-consul - no Optional in the body, and the CamelConsulResult header 
of every action
 
 The `GET_SESSIONS` action of `consul:kv`, the `RENEW` action of 
`consul:session` and the `GET` action of
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DaprEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DaprEndpointBuilderFactory.java
index 526d12215aaf..efba2571a82e 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DaprEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/DaprEndpointBuilderFactory.java
@@ -1916,7 +1916,8 @@ public interface DaprEndpointBuilderFactory {
             return "CamelDaprBindingOperation";
         }
         /**
-         * List of keys for configuration operation.
+         * Keys for configuration operation, as a comma-separated String or a
+         * Collection of keys.
          * 
          * The option is a: {@code String} type.
          * 

Reply via email to