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 d486c012c7aa CAMEL-23772: dataformat component honors global 
camel.dataformat.* configuration
d486c012c7aa is described below

commit d486c012c7aaab9a921c7f584219167bac684f7c
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Jun 16 19:04:37 2026 +0200

    CAMEL-23772: dataformat component honors global camel.dataformat.* 
configuration
    
    The dataformat: component created a fresh, unconfigured DataFormat
    instance and bound only the endpoint URI parameters, ignoring the
    global camel.dataformat.<name>.* configuration from application.properties.
    This fix copies the auto-configured template's option values onto the
    new instance before binding endpoint URI parameters (which keep
    precedence), aligning the component path with the marshal()/unmarshal()
    DSL behaviour fixed in CAMEL-22352.
    
    Closes #24050
---
 components/camel-csv/pom.xml                       |  5 ++
 .../component/DataFormatComponentConfigTest.java   | 57 ++++++++++++++++++++++
 .../csv/component/DataFormatComponentRoute.java    | 32 ++++++++++++
 .../component/dataformat/DataFormatComponent.java  | 56 ++++++++++++++++++++-
 .../ROOT/pages/camel-4x-upgrade-guide-4_21.adoc    |  9 ++++
 5 files changed, 158 insertions(+), 1 deletion(-)

diff --git a/components/camel-csv/pom.xml b/components/camel-csv/pom.xml
index c707dabb9850..cc0b783b922a 100644
--- a/components/camel-csv/pom.xml
+++ b/components/camel-csv/pom.xml
@@ -51,6 +51,11 @@
             <artifactId>camel-main</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-dataformat</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-spring-xml</artifactId>
diff --git 
a/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/component/DataFormatComponentConfigTest.java
 
b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/component/DataFormatComponentConfigTest.java
new file mode 100644
index 000000000000..150477e76dd8
--- /dev/null
+++ 
b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/component/DataFormatComponentConfigTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.csv.component;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.main.Main;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Verifies that a {@code dataformat:} component endpoint honors the global 
{@code camel.dataformat.csv.*} configuration
+ * (here {@code ignore-surrounding-spaces=true}) the same way the {@code 
unmarshal()} DSL does (CAMEL-23772).
+ */
+public class DataFormatComponentConfigTest {
+
+    @Test
+    public void testGlobalConfigAppliedToDataFormatComponent() throws 
Exception {
+        Main main = new Main();
+        
main.configure().withBasePackageScan("org.apache.camel.dataformat.csv.component");
+        main.start();
+        try {
+            CamelContext camelContext = main.getCamelContext();
+            assertNotNull(camelContext);
+            assertEquals(1, camelContext.getRoutes().size());
+
+            MockEndpoint mock = camelContext.getEndpoint("mock:result", 
MockEndpoint.class);
+            mock.expectedMessageCount(1);
+            mock.assertIsSatisfied();
+
+            Object body = 
mock.getReceivedExchanges().get(0).getMessage().getBody();
+            assertNotNull(body);
+            // global camel.dataformat.csv.ignore-surrounding-spaces=true must 
be applied, so the
+            // surrounding spaces are stripped; without the fix the component 
ignores it and the
+            // spaces would be preserved
+            assertEquals("[[One], [Two], [Three]]", body.toString());
+        } finally {
+            main.stop();
+        }
+    }
+}
diff --git 
a/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/component/DataFormatComponentRoute.java
 
b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/component/DataFormatComponentRoute.java
new file mode 100644
index 000000000000..e460236a5216
--- /dev/null
+++ 
b/components/camel-csv/src/test/java/org/apache/camel/dataformat/csv/component/DataFormatComponentRoute.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.csv.component;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class DataFormatComponentRoute extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        // use the dataformat: component instead of the unmarshal() DSL; it 
must honor the global
+        // camel.dataformat.csv.* configuration from application.properties 
(CAMEL-23772)
+        from("timer:tick?repeatCount=1")
+                .setBody().constant("One   \r\nTwo   \r\nThree   \r\n")
+                .to("dataformat:csv:unmarshal")
+                .to("mock:result");
+    }
+}
diff --git 
a/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatComponent.java
 
b/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatComponent.java
index cc4a11e1c7d4..75da315ab5c2 100644
--- 
a/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatComponent.java
+++ 
b/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatComponent.java
@@ -16,15 +16,19 @@
  */
 package org.apache.camel.component.dataformat;
 
+import java.util.LinkedHashMap;
 import java.util.Map;
 
+import org.apache.camel.CamelContext;
 import org.apache.camel.Endpoint;
 import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
 import org.apache.camel.spi.PropertyConfigurer;
 import org.apache.camel.spi.annotations.Component;
 import org.apache.camel.support.DefaultComponent;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.support.PropertyBindingSupport;
+import org.apache.camel.support.PropertyConfigurerHelper;
 import org.apache.camel.util.StringHelper;
 
 /**
@@ -47,6 +51,7 @@ public class DataFormatComponent extends DefaultComponent {
         // create new data format as it is configured from the given parameters
         String name = StringHelper.before(remaining, ":");
         DataFormat df = getCamelContext().createDataFormat(name);
+        boolean created = df != null;
         if (df == null) {
             // if not, try to lookup existing data format
             df = getCamelContext().resolveDataFormat(name);
@@ -58,7 +63,15 @@ public class DataFormatComponent extends DefaultComponent {
         // find configurer if any
         PropertyConfigurer configurer = 
PluginHelper.getConfigurerResolver(getCamelContext())
                 .resolvePropertyConfigurer(name + "-dataformat", 
getCamelContext());
-        // bind properties to data format
+
+        // when a brand-new instance was created, first copy any global 
camel.dataformat.<name>.*
+        // configuration from the auto-configured data format onto it, so the 
dataformat: component
+        // honors global configuration the same way the marshal()/unmarshal() 
DSL does (CAMEL-22352)
+        if (created) {
+            copyGlobalConfiguration(name, df, configurer);
+        }
+
+        // bind the endpoint parameters; these take precedence over the global 
configuration
         PropertyBindingSupport.Builder builder = new 
PropertyBindingSupport.Builder();
         builder.withConfigurer(configurer);
         builder.bind(getCamelContext(), df, parameters);
@@ -69,4 +82,45 @@ public class DataFormatComponent extends DefaultComponent {
         setProperties(endpoint, parameters);
         return endpoint;
     }
+
+    /**
+     * Copies the configuration of an auto-configured data format (e.g. set up 
via global
+     * {@code camel.dataformat.<name>.*} properties) onto the newly created 
data format instance, so that
+     * {@code dataformat:} endpoints honor global configuration. The endpoint 
URI parameters are bound afterwards and
+     * therefore take precedence over the copied values.
+     */
+    private void copyGlobalConfiguration(String name, DataFormat target, 
PropertyConfigurer configurer) {
+        CamelContext context = getCamelContext();
+        // only relevant when a generic data format has been auto-configured, 
e.g. via camel.dataformat.<name>.*
+        if (!context.getDataFormatNames().contains(name)) {
+            return;
+        }
+        DataFormat template = context.resolveDataFormat(name);
+        if (template == null || template == target) {
+            return;
+        }
+        PropertyConfigurer getter = configurer;
+        if (getter == null) {
+            getter = 
PropertyConfigurerHelper.resolvePropertyConfigurer(context, template);
+        }
+        if (getter instanceof ExtendedPropertyConfigurerGetter eg) {
+            Map<String, Object> properties = new LinkedHashMap<>();
+            for (String key : eg.getAllOptions(template).keySet()) {
+                Object value = eg.getOptionValue(template, key, true);
+                if (value != null) {
+                    properties.put(key, value);
+                }
+            }
+            if (!properties.isEmpty()) {
+                PropertyBindingSupport.build()
+                        .withCamelContext(context)
+                        .withTarget(target)
+                        .withReference(true)
+                        .withIgnoreCase(true)
+                        .withConfigurer(configurer)
+                        .withProperties(properties)
+                        .bind();
+            }
+        }
+    }
 }
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
index 4c3d8e5d43a1..903886d1cd74 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc
@@ -25,6 +25,15 @@ When `fromRouteId` is not available (for example, on 
Exchanges created by `Produ
 This ensures Prometheus-compatible metric export when Route triggered and 
ProducerTemplate Exchanges are mixed.
 Dashboards or alerts that assumed the `routeId` label was absent must be 
updated to treat `routeId=""` accordingly.
 
+=== camel-dataformat
+
+The `dataformat:` component now applies the global `camel.dataformat.<name>.*` 
configuration (for example from
+`application.properties`) when it creates the data format instance. Previously 
a `dataformat:` endpoint such as
+`to("dataformat:beanio:unmarshal")` ignored this global configuration and used 
only the options provided on the
+endpoint URI, which could leave the data format incompletely configured. This 
aligns the component with the
+`marshal()` / `unmarshal()` DSL, which already honors the global 
configuration. Options specified on the endpoint URI
+continue to take precedence over the global configuration.
+
 === camel-core
 
 ==== Simple language: internal builder classes reorganized

Reply via email to