You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/09/25 12:05:00 UTC

[camel] branch ctr created (now 4f7cfe30aed)

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

davsclaus pushed a change to branch ctr
in repository https://gitbox.apache.org/repos/asf/camel.git


      at 4f7cfe30aed CAMEL-19820: camel-core-model - Add <constructor> to <bean> to make it easier and more tooling friendly to specify constructor args

This branch includes the following new commits:

     new 4f7cfe30aed CAMEL-19820: camel-core-model - Add <constructor> to <bean> to make it easier and more tooling friendly to specify constructor args

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[camel] 01/01: CAMEL-19820: camel-core-model - Add to to make it easier and more tooling friendly to specify constructor args

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch ctr
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4f7cfe30aed60c27b8c69f822b01a75d5eb6b86a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Sep 25 14:00:07 2023 +0200

    CAMEL-19820: camel-core-model - Add <constructor> to <bean> to make it easier and more tooling friendly to specify constructor args
---
 .../apache/camel/catalog/schemas/camel-spring.xsd  | 11 +++
 .../org/apache/camel/model/app/jaxb.index          |  2 +
 .../camel/model/app/BeanConstructorDefinition.java | 55 +++++++++++++++
 .../camel/model/app/BeanConstructorsAdapter.java   | 69 +++++++++++++++++++
 .../model/app/BeanConstructorsDefinition.java      | 41 +++++++++++
 .../camel/model/app/RegistryBeanDefinition.java    | 11 +++
 .../java/org/apache/camel/xml/in/ModelParser.java  | 29 ++++++--
 .../java/org/apache/camel/xml/out/ModelWriter.java | 18 +++++
 .../org/apache/camel/xml/LwModelToXMLDumper.java   | 13 ++++
 .../org/apache/camel/xml/in/ModelParserTest.java   | 29 +++++++-
 .../src/test/resources/beansWithConstructors.xml   | 41 +++++++++++
 .../camel/xml/jaxb/JaxbModelToXMLDumper.java       | 13 ++++
 .../org/apache/camel/yaml/out/ModelWriter.java     | 18 +++++
 .../org/apache/camel/yaml/LwModelToYAMLDumper.java | 12 ++++
 .../main/xml/spring/SpringXmlBeansHandler.java     | 28 ++++----
 .../src/main/docs/java-xml-io-dsl.adoc             | 41 +++++++++++
 .../camel/dsl/xml/io/XmlRoutesBuilderLoader.java   | 18 +++++
 .../apache/camel/dsl/xml/io/XmlLoadAppTest.java    | 23 +++++++
 .../apache/camel/dsl/xml/io/beans/MyCtrBean.java   | 50 ++++++++++++++
 .../org/apache/camel/dsl/xml/io/camel-app5.xml     | 38 ++++++++++
 .../dsl/yaml/deserializers/ModelDeserializers.java | 80 ++++++++++++++++++++++
 .../deserializers/ModelDeserializersResolver.java  |  2 +
 .../dsl/yaml/deserializers/BeansDeserializer.java  | 24 ++++++-
 .../generated/resources/schema/camelYamlDsl.json   | 28 ++++++++
 .../org/apache/camel/dsl/yaml/BeansTest.groovy     | 44 ++++++++++++
 .../camel/dsl/yaml/support/model/MyCtrBean.groovy  | 44 ++++++++++++
 26 files changed, 764 insertions(+), 18 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 8882c7ddb24..c52b32f6558 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -13598,11 +13598,22 @@ org.apache.camel.builder.RouteBuilder.
   </xs:complexType>
   <xs:complexType name="registryBeanDefinition">
     <xs:sequence>
+      <xs:element minOccurs="0" name="constructors" type="tns:beanConstructorsDefinition"/>
       <xs:element minOccurs="0" name="properties" type="tns:beanPropertiesDefinition"/>
     </xs:sequence>
     <xs:attribute name="name" type="xs:string" use="required"/>
     <xs:attribute name="type" type="xs:string" use="required"/>
   </xs:complexType>
+  <xs:complexType name="beanConstructorsDefinition">
+    <xs:sequence>
+      <xs:element maxOccurs="unbounded" minOccurs="0" name="constructor" type="tns:beanConstructorDefinition"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="beanConstructorDefinition">
+    <xs:sequence/>
+    <xs:attribute name="index" type="xs:int"/>
+    <xs:attribute name="value" type="xs:string" use="required"/>
+  </xs:complexType>
   <xs:complexType name="restConfigurationDefinition">
     <xs:sequence>
       <xs:element maxOccurs="unbounded" minOccurs="0" name="componentProperty" type="tns:restPropertyDefinition">
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index
index 5a0a73a15d0..d5d2a547b9d 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/app/jaxb.index
@@ -1,5 +1,7 @@
 # Generated by camel build tools - do NOT edit this file!
 ApplicationDefinition
+BeanConstructorDefinition
+BeanConstructorsDefinition
 BeanPropertiesDefinition
 BeanPropertyDefinition
 BeansDefinition
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorDefinition.java
new file mode 100644
index 00000000000..72ce4c9f1ab
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorDefinition.java
@@ -0,0 +1,55 @@
+/*
+ * 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.model.app;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlType;
+
+@XmlType
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BeanConstructorDefinition {
+
+    @XmlAttribute
+    private Integer index;
+    @XmlAttribute(required = true)
+    private String value;
+
+    public Integer getIndex() {
+        return index;
+    }
+
+    /**
+     * Constructor index
+     */
+    public void setIndex(Integer index) {
+        this.index = index;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * The argument value for the constructor.
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorsAdapter.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorsAdapter.java
new file mode 100644
index 00000000000..4e09122732b
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorsAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * 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.model.app;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import jakarta.xml.bind.annotation.adapters.XmlAdapter;
+
+public class BeanConstructorsAdapter extends XmlAdapter<BeanConstructorsDefinition, Map<Integer, Object>> {
+
+    @Override
+    public Map<Integer, Object> unmarshal(BeanConstructorsDefinition v) {
+        if (v == null) {
+            return null;
+        }
+        int counter = 0;
+        Map<Integer, Object> result = new LinkedHashMap<>();
+        for (BeanConstructorDefinition pd : v.getConstructors()) {
+            Integer idx = pd.getIndex();
+            if (idx == null) {
+                idx = counter;
+                counter++;
+            }
+            result.put(idx, pd.getValue());
+        }
+
+        return result;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public BeanConstructorsDefinition marshal(Map<Integer, Object> v) {
+        if (v == null) {
+            return null;
+        }
+        final BeanConstructorDefinition[] result = new BeanConstructorDefinition[v.size()];
+        int pos = 0;
+        for (Map.Entry<Integer, Object> entry : v.entrySet()) {
+            Integer idx = entry.getKey();
+            Object value = entry.getValue();
+            BeanConstructorDefinition pd = new BeanConstructorDefinition();
+            if (idx != null) {
+                pd.setIndex(idx);
+            }
+            pd.setValue(value.toString());
+            result[pos++] = pd;
+        }
+        BeanConstructorsDefinition def = new BeanConstructorsDefinition();
+        def.setConstructors(Arrays.asList(result));
+        return def;
+    }
+
+}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorsDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorsDefinition.java
new file mode 100644
index 00000000000..11daaacd9cf
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/BeanConstructorsDefinition.java
@@ -0,0 +1,41 @@
+/*
+ * 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.model.app;
+
+import java.util.List;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+@XmlType
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BeanConstructorsDefinition {
+
+    @XmlElement(name = "constructor")
+    private List<BeanConstructorDefinition> constructors;
+
+    public List<BeanConstructorDefinition> getConstructors() {
+        return constructors;
+    }
+
+    public void setConstructors(List<BeanConstructorDefinition> constructors) {
+        this.constructors = constructors;
+    }
+
+}
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java
index 524428a4e3e..43ea6c01f6c 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/app/RegistryBeanDefinition.java
@@ -46,6 +46,9 @@ public class RegistryBeanDefinition implements ResourceAware {
     private String name;
     @XmlAttribute(required = true)
     private String type;
+    @XmlElement(name = "constructors")
+    @XmlJavaTypeAdapter(BeanConstructorsAdapter.class)
+    private Map<Integer, Object> constructors;
     @XmlElement(name = "properties")
     @XmlJavaTypeAdapter(BeanPropertiesAdapter.class)
     private Map<String, Object> properties;
@@ -66,6 +69,14 @@ public class RegistryBeanDefinition implements ResourceAware {
         this.type = type;
     }
 
+    public Map<Integer, Object> getConstructors() {
+        return constructors;
+    }
+
+    public void setConstructors(Map<Integer, Object> constructors) {
+        this.constructors = constructors;
+    }
+
     public Map<String, Object> getProperties() {
         return properties;
     }
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index d8890ea2ce6..fc4ee8275e5 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -1640,11 +1640,12 @@ public class ModelParser extends BaseParser {
             }
             return true;
         }, (def, key) -> {
-            if ("properties".equals(key)) {
-                def.setProperties(new BeanPropertiesAdapter().unmarshal(doParseBeanPropertiesDefinition()));
-                return true;
+            switch (key) {
+                case "constructors": def.setConstructors(new BeanConstructorsAdapter().unmarshal(doParseBeanConstructorsDefinition())); break;
+                case "properties": def.setProperties(new BeanPropertiesAdapter().unmarshal(doParseBeanPropertiesDefinition())); break;
+                default: return false;
             }
-            return false;
+            return true;
         }, noValueHandler());
     }
     protected RestConfigurationDefinition doParseRestConfigurationDefinition() throws IOException, XmlPullParserException {
@@ -1687,6 +1688,26 @@ public class ModelParser extends BaseParser {
             return true;
         }, noValueHandler());
     }
+    protected BeanConstructorDefinition doParseBeanConstructorDefinition() throws IOException, XmlPullParserException {
+        return doParse(new BeanConstructorDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "index": def.setIndex(Integer.valueOf(val)); break;
+                case "value": def.setValue(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected BeanConstructorsDefinition doParseBeanConstructorsDefinition() throws IOException, XmlPullParserException {
+        return doParse(new BeanConstructorsDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            if ("constructor".equals(key)) {
+                doAdd(doParseBeanConstructorDefinition(), def.getConstructors(), def::setConstructors);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
     protected BeanPropertyDefinition doParseBeanPropertyDefinition() throws IOException, XmlPullParserException {
         return doParse(new BeanPropertyDefinition(), (def, key, val) -> {
             switch (key) {
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index 2e89e6409c4..51ae6036ef8 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -2496,6 +2496,23 @@ public class ModelWriter extends BaseWriter {
         doWriteBeansDefinitionElements(def);
         endElement(name);
     }
+    protected void doWriteBeanConstructorDefinition(
+            String name,
+            BeanConstructorDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteAttribute("index", toString(def.getIndex()));
+        doWriteAttribute("value", def.getValue());
+        endElement(name);
+    }
+    protected void doWriteBeanConstructorsDefinition(
+            String name,
+            BeanConstructorsDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteList(null, "constructor", def.getConstructors(), this::doWriteBeanConstructorDefinition);
+        endElement(name);
+    }
     protected void doWriteBeanPropertiesDefinition(
             String name,
             BeanPropertiesDefinition def)
@@ -2551,6 +2568,7 @@ public class ModelWriter extends BaseWriter {
         startElement(name);
         doWriteAttribute("name", def.getName());
         doWriteAttribute("type", def.getType());
+        doWriteElement("constructors", new BeanConstructorsAdapter().marshal(def.getConstructors()), this::doWriteBeanConstructorsDefinition);
         doWriteElement("properties", new BeanPropertiesAdapter().marshal(def.getProperties()), this::doWriteBeanPropertiesDefinition);
         endElement(name);
     }
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java
index 39c7c513250..577d4bec4b4 100644
--- a/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/LwModelToXMLDumper.java
@@ -325,6 +325,19 @@ public class LwModelToXMLDumper implements ModelToXMLDumper {
                 type = type.substring(7);
             }
             buffer.write(String.format("    <bean name=\"%s\" type=\"%s\">%n", b.getName(), type));
+            if (b.getConstructors() != null && !b.getConstructors().isEmpty()) {
+                buffer.write(String.format("        <constructors>%n"));
+                for (Map.Entry<Integer, Object> entry : b.getConstructors().entrySet()) {
+                    Integer idx = entry.getKey();
+                    Object value = entry.getValue();
+                    if (idx != null) {
+                        buffer.write(String.format("            <constructor index=\"%d\" value=\"%s\"/>%n", idx, value));
+                    } else {
+                        buffer.write(String.format("            <constructor value=\"%s\"/>%n", value));
+                    }
+                }
+                buffer.write(String.format("        </constructors>%n"));
+            }
             if (b.getProperties() != null && !b.getProperties().isEmpty()) {
                 buffer.write(String.format("        <properties>%n"));
                 for (Map.Entry<String, Object> entry : b.getProperties().entrySet()) {
diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
index f5efc6a8bf3..17a9111179d 100644
--- a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
+++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
@@ -259,7 +259,7 @@ public class ModelParserTest {
         assertEquals("v2a", ((Map<String, Object>) b1.getProperties().get("nested")).get("p2"));
 
         assertEquals("b2", b2.getName());
-        assertEquals("org.apache.camel.xml.in.ModelParserTest.MyBean", b1.getType());
+        assertEquals("org.apache.camel.xml.in.ModelParserTest.MyBean", b2.getType());
         assertEquals("v1", b2.getProperties().get("p1"));
         assertEquals("v2", b2.getProperties().get("p2"));
         assertNull(b2.getProperties().get("nested"));
@@ -267,6 +267,33 @@ public class ModelParserTest {
         assertEquals("v2a", b2.getProperties().get("nested.p2"));
     }
 
+    @Test
+    public void testBeansWithConstructors() throws Exception {
+        Path dir = getResourceFolder();
+        Path path = new File(dir.toFile(), "beansWithConstructors.xml").toPath();
+        ModelParser parser = new ModelParser(Files.newInputStream(path), NAMESPACE);
+        BeansDefinition beans = parser.parseBeansDefinition().orElse(null);
+        assertNotNull(beans);
+        assertEquals(2, beans.getBeans().size());
+        assertTrue(beans.getSpringBeans().isEmpty());
+
+        RegistryBeanDefinition b1 = beans.getBeans().get(0);
+        RegistryBeanDefinition b2 = beans.getBeans().get(1);
+
+        assertEquals("b1", b1.getName());
+        assertEquals("org.apache.camel.xml.in.ModelParserTest.MyBean", b1.getType());
+        assertEquals(2, b1.getConstructors().size());
+        assertEquals("c1", b1.getConstructors().get(0));
+        assertEquals("c2", b1.getConstructors().get(1));
+
+        assertEquals("b2", b2.getName());
+        assertEquals("org.apache.camel.xml.in.ModelParserTest.MyBean", b2.getType());
+        assertEquals(1, b2.getConstructors().size());
+        assertEquals("c1", b2.getConstructors().get(0));
+        assertEquals("v1", b2.getProperties().get("p1"));
+        assertEquals("v2", b2.getProperties().get("p2"));
+    }
+
     @Test
     public void testSpringBeans() throws Exception {
         Path dir = getResourceFolder();
diff --git a/core/camel-xml-io/src/test/resources/beansWithConstructors.xml b/core/camel-xml-io/src/test/resources/beansWithConstructors.xml
new file mode 100644
index 00000000000..6c7e158c239
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/beansWithConstructors.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://camel.apache.org/schema/spring file:/data/sources/github.com/apache/camel-upstream/components/camel-spring-xml/target/classes/camel-spring.xsd">
+
+	<bean name="b1" type="org.apache.camel.xml.in.ModelParserTest.MyBean">
+		<constructors>
+			<!-- index is optional -->
+			<constructor value="c1" />
+			<constructor value="c2" />
+		</constructors>
+	</bean>
+
+	<bean name="b2" type="org.apache.camel.xml.in.ModelParserTest.MyBean">
+		<constructors>
+			<constructor index="0" value="c1" />
+		</constructors>
+		<properties>
+			<property key="p1" value="v1" />
+			<property key="p2" value="v2" />
+		</properties>
+	</bean>
+
+</beans>
diff --git a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
index 6ed3af7c46b..1ffbd95c74b 100644
--- a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
+++ b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
@@ -338,6 +338,19 @@ public class JaxbModelToXMLDumper implements ModelToXMLDumper {
                 type = type.substring(7);
             }
             buffer.write(String.format("    <bean name=\"%s\" type=\"%s\">%n", b.getName(), type));
+            if (b.getConstructors() != null && !b.getConstructors().isEmpty()) {
+                buffer.write(String.format("        <constructors>%n"));
+                for (Map.Entry<Integer, Object> entry : b.getConstructors().entrySet()) {
+                    Integer idx = entry.getKey();
+                    Object value = entry.getValue();
+                    if (idx != null) {
+                        buffer.write(String.format("            <constructor index=\"%d\" value=\"%s\"/>%n", idx, value));
+                    } else {
+                        buffer.write(String.format("            <constructor value=\"%s\"/>%n", value));
+                    }
+                }
+                buffer.write(String.format("        </constructors>%n"));
+            }
             if (b.getProperties() != null && !b.getProperties().isEmpty()) {
                 buffer.write(String.format("        <properties>%n"));
                 for (Map.Entry<String, Object> entry : b.getProperties().entrySet()) {
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 3010257af60..7d73b3ebb96 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -2496,6 +2496,23 @@ public class ModelWriter extends BaseWriter {
         doWriteBeansDefinitionElements(def);
         endElement(name);
     }
+    protected void doWriteBeanConstructorDefinition(
+            String name,
+            BeanConstructorDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteAttribute("index", toString(def.getIndex()));
+        doWriteAttribute("value", def.getValue());
+        endElement(name);
+    }
+    protected void doWriteBeanConstructorsDefinition(
+            String name,
+            BeanConstructorsDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteList(null, "constructor", def.getConstructors(), this::doWriteBeanConstructorDefinition);
+        endElement(name);
+    }
     protected void doWriteBeanPropertiesDefinition(
             String name,
             BeanPropertiesDefinition def)
@@ -2551,6 +2568,7 @@ public class ModelWriter extends BaseWriter {
         startElement(name);
         doWriteAttribute("name", def.getName());
         doWriteAttribute("type", def.getType());
+        doWriteElement("constructors", new BeanConstructorsAdapter().marshal(def.getConstructors()), this::doWriteBeanConstructorsDefinition);
         doWriteElement("properties", new BeanPropertiesAdapter().marshal(def.getProperties()), this::doWriteBeanPropertiesDefinition);
         endElement(name);
     }
diff --git a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
index d07d18826d2..0ab28843b2a 100644
--- a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
+++ b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/LwModelToYAMLDumper.java
@@ -314,6 +314,18 @@ public class LwModelToYAMLDumper implements ModelToYAMLDumper {
             }
             buffer.write(String.format("    - name: %s%n", b.getName()));
             buffer.write(String.format("      type: \"%s\"%n", type));
+            if (b.getConstructors() != null && !b.getConstructors().isEmpty()) {
+                buffer.write(String.format("      constructors:%n"));
+                int counter = 0;
+                for (Map.Entry<Integer, Object> entry : b.getConstructors().entrySet()) {
+                    Integer key = entry.getKey();
+                    Object value = entry.getValue();
+                    if (key == null) {
+                        key = counter++;
+                    }
+                    buffer.write(String.format("        %d: \"%s\"%n", key, value));
+                }
+            }
             if (b.getProperties() != null && !b.getProperties().isEmpty()) {
                 buffer.write(String.format("      properties:%n"));
                 for (Map.Entry<String, Object> entry : b.getProperties().entrySet()) {
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/spring/SpringXmlBeansHandler.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/spring/SpringXmlBeansHandler.java
index 34b2159169c..aeeced8d905 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/spring/SpringXmlBeansHandler.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/spring/SpringXmlBeansHandler.java
@@ -26,7 +26,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.StringJoiner;
 import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -238,19 +237,24 @@ public class SpringXmlBeansHandler {
             model.addRegistryBean(rrd);
 
             // constructor arguments
-            ConstructorArgumentValues ctr = def.getConstructorArgumentValues();
-            StringJoiner sj = new StringJoiner(", ");
-            for (ConstructorArgumentValues.ValueHolder v : ctr.getIndexedArgumentValues().values()) {
-                Object val = v.getValue();
-                if (val instanceof TypedStringValue tsv) {
-                    sj.add("'" + extractValue(camelContext, tsv.getValue(), false) + "'");
-                } else if (val instanceof BeanReference br) {
-                    sj.add("'#bean:" + extractValue(camelContext, br.getBeanName(), false) + "'");
+            if (def.hasConstructorArgumentValues()) {
+                Map<Integer, Object> constructors = new LinkedHashMap<>();
+                rrd.setConstructors(constructors);
+
+                ConstructorArgumentValues ctrs = def.getConstructorArgumentValues();
+                for (int i = 0; i < ctrs.getArgumentCount(); i++) {
+                    ConstructorArgumentValues.ValueHolder vh = ctrs.getArgumentValue(i, Object.class);
+                    if (vh != null) {
+                        Object val = vh.getValue();
+                        if (val instanceof TypedStringValue tsv) {
+                            constructors.put(i, extractValue(camelContext, tsv.getValue(), false));
+                        } else if (val instanceof BeanReference br) {
+                            constructors.put(i, "#bean:" + extractValue(camelContext, br.getBeanName(), false));
+                        }
+                    }
                 }
             }
-            if (sj.length() > 0) {
-                rrd.setType("#class:" + def.getBeanClassName() + "(" + sj + ")");
-            }
+
             // property values
             if (def.hasPropertyValues()) {
                 Map<String, Object> properties = new LinkedHashMap<>();
diff --git a/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc b/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc
index d2f5d7b66fc..5493e2a5e0f 100644
--- a/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc
+++ b/dsl/camel-xml-io-dsl/src/main/docs/java-xml-io-dsl.adoc
@@ -116,6 +116,47 @@ A `my-route` route is referring to `greeter` bean which is defined using Spring
 
 More examples can be found in xref:manual:ROOT:camel-jbang.adoc#_using_spring_beans_in_camel_xml_dsl[Camel JBang] page.
 
+=== Using bean with constructors
+
+When beans must be created with constructor arguments, then this is made easier in Camel 4.1 onwards.
+
+For example as shown below:
+
+[source,xml]
+----
+<camel>
+
+	<bean name="beanFromProps" type="com.acme.MyBean">
+        <constructors>
+          <constructor index="0" value="true"/>
+          <constructor index="1" value="Hello World"/>
+        </constructors>
+        <!-- and you can still have properties -->
+		<properties>
+			<property key="field1" value="f1_p" />
+			<property key="field2" value="f2_p" />
+			<property key="nested.field1" value="nf1_p" />
+			<property key="nested.field2" value="nf2_p" />
+		</properties>
+	</bean>
+
+</camel>
+----
+
+If you use Camel 4.0, then constructor arguments must be defined in the `type` attribute:
+
+[source,xml]
+----
+<bean name="beanFromProps" type="com.acme.MyBean(true, 'Hello World')">
+    <properties>
+        <property key="field1" value="f1_p" />
+        <property key="field2" value="f2_p" />
+        <property key="nested.field1" value="nf1_p" />
+        <property key="nested.field2" value="nf2_p" />
+    </properties>
+</bean>
+----
+
 == See Also
 
 See xref:manual:ROOT:dsl.adoc[DSL]
diff --git a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
index e5bcc4014c1..472506f2158 100644
--- a/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
+++ b/dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
@@ -22,6 +22,8 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
+import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -50,6 +52,7 @@ import org.apache.camel.spi.annotations.RoutesLoader;
 import org.apache.camel.support.CachedResource;
 import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.support.scan.PackageScanHelper;
+import org.apache.camel.util.StringHelper;
 import org.apache.camel.xml.io.util.XmlStreamDetector;
 import org.apache.camel.xml.io.util.XmlStreamInfo;
 import org.slf4j.Logger;
@@ -324,6 +327,21 @@ public class XmlRoutesBuilderLoader extends RouteBuilderLoaderSupport {
         if (type != null && !type.startsWith("#")) {
             type = "#class:" + type;
             try {
+                // property binding support has constructor arguments as part of the type
+                StringJoiner ctr = new StringJoiner(", ");
+                if (def.getConstructors() != null && !def.getConstructors().isEmpty()) {
+                    // need to sort constructor args based on index position
+                    Map<Integer, Object> sorted = new TreeMap<>(def.getConstructors());
+                    for (Object val : sorted.values()) {
+                        String text = val.toString();
+                        if (!StringHelper.isQuoted(text)) {
+                            text = "\"" + text + "\"";
+                        }
+                        ctr.add(text);
+                    }
+                    type = type + "(" + ctr + ")";
+                }
+
                 final Object target = PropertyBindingSupport.resolveBean(getCamelContext(), type);
 
                 if (def.getProperties() != null && !def.getProperties().isEmpty()) {
diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java
index 867e086a69c..1baf549658e 100644
--- a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java
+++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/XmlLoadAppTest.java
@@ -121,4 +121,27 @@ public class XmlLoadAppTest {
         }
     }
 
+    @Test
+    public void testLoadCamelAppWithBeanCtr() throws Exception {
+        try (DefaultCamelContext context = new DefaultCamelContext()) {
+            context.start();
+
+            Resource resource = PluginHelper.getResourceLoader(context).resolveResource(
+                    "/org/apache/camel/dsl/xml/io/camel-app5.xml");
+
+            RoutesLoader routesLoader = PluginHelper.getRoutesLoader(context);
+            routesLoader.preParseRoute(resource, false);
+            routesLoader.loadRoutes(resource);
+
+            assertNotNull(context.getRoute("r5"), "Loaded r5 route should be there");
+            assertEquals(1, context.getRoutes().size());
+
+            // test that loaded route works
+            MockEndpoint y5 = context.getEndpoint("mock:y5", MockEndpoint.class);
+            y5.expectedBodiesReceived("Hello World. I am Camel and 42 years old!");
+            context.createProducerTemplate().sendBody("direct:x5", "World");
+            y5.assertIsSatisfied();
+        }
+    }
+
 }
diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyCtrBean.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyCtrBean.java
new file mode 100644
index 00000000000..c5abd8959a7
--- /dev/null
+++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyCtrBean.java
@@ -0,0 +1,50 @@
+/*
+ * 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.dsl.xml.io.beans;
+
+public class MyCtrBean {
+
+    private String field1;
+    private String field2;
+    private int age;
+
+    public MyCtrBean(String field1, String field2) {
+        this.field1 = field1;
+        this.field2 = field2;
+    }
+
+    public String getField1() {
+        return field1;
+    }
+
+    public String getField2() {
+        return field2;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public String hello(String body) {
+        return field1 + " " + body + ". I am " + field2 + " and " + age + " years old!";
+    }
+
+}
diff --git a/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app5.xml b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app5.xml
new file mode 100644
index 00000000000..b125a3f5048
--- /dev/null
+++ b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app5.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<camel xmlns="http://camel.apache.org/schema/spring" xmlns:s="http://www.springframework.org/schema/beans">
+
+    <bean name="xml-bean-from-registry" type="org.apache.camel.dsl.xml.io.beans.MyCtrBean">
+        <constructors>
+            <constructor value="Hello"/>
+            <constructor value="Camel"/>
+        </constructors>
+        <properties>
+            <property key="age" value="42"/>
+        </properties>
+    </bean>
+
+    <route id="r5">
+        <from uri="direct:x5"/>
+        <bean ref="xml-bean-from-registry" method="hello"/>
+        <to uri="mock:y5"/>
+    </route>
+
+</camel>
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 0655b5bdd82..5cb80ff5430 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -99,6 +99,8 @@ import org.apache.camel.model.WhenDefinition;
 import org.apache.camel.model.WhenSkipSendToEndpointDefinition;
 import org.apache.camel.model.WireTapDefinition;
 import org.apache.camel.model.app.ApplicationDefinition;
+import org.apache.camel.model.app.BeanConstructorDefinition;
+import org.apache.camel.model.app.BeanConstructorsDefinition;
 import org.apache.camel.model.app.BeanPropertiesDefinition;
 import org.apache.camel.model.app.BeanPropertyDefinition;
 import org.apache.camel.model.app.BeansDefinition;
@@ -1068,6 +1070,78 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
+    @YamlType(
+            types = org.apache.camel.model.app.BeanConstructorDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            properties = {
+                    @YamlProperty(name = "index", type = "number"),
+                    @YamlProperty(name = "value", type = "string", required = true)
+            }
+    )
+    public static class BeanConstructorDefinitionDeserializer extends YamlDeserializerBase<BeanConstructorDefinition> {
+        public BeanConstructorDefinitionDeserializer() {
+            super(BeanConstructorDefinition.class);
+        }
+
+        @Override
+        protected BeanConstructorDefinition newInstance() {
+            return new BeanConstructorDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(BeanConstructorDefinition target, String propertyKey,
+                String propertyName, Node node) {
+            switch(propertyKey) {
+                case "index": {
+                    String val = asText(node);
+                    target.setIndex(java.lang.Integer.valueOf(val));
+                    break;
+                }
+                case "value": {
+                    String val = asText(node);
+                    target.setValue(val);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    @YamlType(
+            types = org.apache.camel.model.app.BeanConstructorsDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            properties = @YamlProperty(name = "constructor", type = "array:org.apache.camel.model.app.BeanConstructorDefinition")
+    )
+    public static class BeanConstructorsDefinitionDeserializer extends YamlDeserializerBase<BeanConstructorsDefinition> {
+        public BeanConstructorsDefinitionDeserializer() {
+            super(BeanConstructorsDefinition.class);
+        }
+
+        @Override
+        protected BeanConstructorsDefinition newInstance() {
+            return new BeanConstructorsDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(BeanConstructorsDefinition target, String propertyKey,
+                String propertyName, Node node) {
+            switch(propertyKey) {
+                case "constructor": {
+                    java.util.List<org.apache.camel.model.app.BeanConstructorDefinition> val = asFlatList(node, org.apache.camel.model.app.BeanConstructorDefinition.class);
+                    target.setConstructors(val);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
     @YamlType(
             nodes = "bean",
             inline = true,
@@ -12274,6 +12348,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
             types = org.apache.camel.model.app.RegistryBeanDefinition.class,
             order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
             properties = {
+                    @YamlProperty(name = "constructors", type = "object"),
                     @YamlProperty(name = "name", type = "string", required = true),
                     @YamlProperty(name = "properties", type = "object"),
                     @YamlProperty(name = "type", type = "string", required = true)
@@ -12293,6 +12368,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         protected boolean setProperty(RegistryBeanDefinition target, String propertyKey,
                 String propertyName, Node node) {
             switch(propertyKey) {
+                case "constructors": {
+                    java.util.Map val = asMap(node);
+                    target.setConstructors(val);
+                    break;
+                }
                 case "name": {
                     String val = asText(node);
                     target.setName(val);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index 960fdb05881..fa4f77c4ec4 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -35,6 +35,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "org.apache.camel.model.rest.BasicAuthDefinition": return new ModelDeserializers.BasicAuthDefinitionDeserializer();
             case "batch-config": return new ModelDeserializers.BatchResequencerConfigDeserializer();
             case "org.apache.camel.model.config.BatchResequencerConfig": return new ModelDeserializers.BatchResequencerConfigDeserializer();
+            case "org.apache.camel.model.app.BeanConstructorDefinition": return new ModelDeserializers.BeanConstructorDefinitionDeserializer();
+            case "org.apache.camel.model.app.BeanConstructorsDefinition": return new ModelDeserializers.BeanConstructorsDefinitionDeserializer();
             case "bean": return new ModelDeserializers.BeanDefinitionDeserializer();
             case "org.apache.camel.model.BeanDefinition": return new ModelDeserializers.BeanDefinitionDeserializer();
             case "org.apache.camel.model.app.BeanPropertiesDefinition": return new ModelDeserializers.BeanPropertiesDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
index 7ac54a605ec..d6f62a66482 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/main/java/org/apache/camel/dsl/yaml/deserializers/BeansDeserializer.java
@@ -19,7 +19,10 @@ package org.apache.camel.dsl.yaml.deserializers;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
+import java.util.TreeMap;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.dsl.yaml.common.YamlDeserializationContext;
@@ -33,6 +36,7 @@ import org.apache.camel.spi.annotations.YamlProperty;
 import org.apache.camel.spi.annotations.YamlType;
 import org.apache.camel.support.PropertyBindingSupport;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
 import org.snakeyaml.engine.v2.api.ConstructNode;
 import org.snakeyaml.engine.v2.nodes.Node;
 import org.snakeyaml.engine.v2.nodes.SequenceNode;
@@ -88,7 +92,25 @@ public class BeansDeserializer extends YamlDeserializerSupport implements Constr
     }
 
     public Object newInstance(RegistryBeanDefinition bean, CamelContext context) throws Exception {
-        final Object target = PropertyBindingSupport.resolveBean(context, bean.getType());
+
+        String type = bean.getType();
+
+        // property binding support has constructor arguments as part of the type
+        StringJoiner ctr = new StringJoiner(", ");
+        if (bean.getConstructors() != null && !bean.getConstructors().isEmpty()) {
+            // need to sort constructor args based on index position
+            Map<Integer, Object> sorted = new TreeMap<>(bean.getConstructors());
+            for (Object val : sorted.values()) {
+                String text = val.toString();
+                if (!StringHelper.isQuoted(text)) {
+                    text = "\"" + text + "\"";
+                }
+                ctr.add(text);
+            }
+            type = type + "(" + ctr + ")";
+        }
+
+        final Object target = PropertyBindingSupport.resolveBean(context, type);
 
         if (bean.getProperties() != null && !bean.getProperties().isEmpty()) {
             PropertyBindingSupport.setPropertiesOnTarget(context, target, bean.getProperties());
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index b1022f4f969..fcb2e9a20a0 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -7895,6 +7895,31 @@
           }
         }
       },
+      "org.apache.camel.model.app.BeanConstructorDefinition" : {
+        "type" : "object",
+        "additionalProperties" : false,
+        "properties" : {
+          "index" : {
+            "type" : "number"
+          },
+          "value" : {
+            "type" : "string"
+          }
+        },
+        "required" : [ "value" ]
+      },
+      "org.apache.camel.model.app.BeanConstructorsDefinition" : {
+        "type" : "object",
+        "additionalProperties" : false,
+        "properties" : {
+          "constructor" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/items/definitions/org.apache.camel.model.app.BeanConstructorDefinition"
+            }
+          }
+        }
+      },
       "org.apache.camel.model.app.BeanPropertiesDefinition" : {
         "type" : "object",
         "additionalProperties" : false,
@@ -7998,6 +8023,9 @@
         "type" : "object",
         "additionalProperties" : false,
         "properties" : {
+          "constructors" : {
+            "type" : "object"
+          },
           "name" : {
             "type" : "string"
           },
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/BeansTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/BeansTest.groovy
index cccbc24ab24..4b1e5253ce9 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/BeansTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/BeansTest.groovy
@@ -18,6 +18,7 @@ package org.apache.camel.dsl.yaml
 
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
 import org.apache.camel.dsl.yaml.support.model.MyBean
+import org.apache.camel.dsl.yaml.support.model.MyCtrBean
 
 class BeansTest extends YamlTestSupport {
 
@@ -87,4 +88,47 @@ class BeansTest extends YamlTestSupport {
                 it.nested.foo == 'f3'
             }
     }
+
+    def "beans with constructor"() {
+        when:
+        loadRoutes """
+                - beans:
+                  - name: myCtr
+                    type: ${MyCtrBean.class.name}
+                    constructors:
+                      0: 'f1'
+                      1: 'f2'
+                    properties:
+                      age: 42 
+            """
+
+        then:
+        with(context.registry.lookupByName('myCtr'), MyCtrBean) {
+            it.field1 == 'f1'
+            it.field2 == 'f2'
+            it.age == 42
+        }
+    }
+
+    def "beans with constructor sorted"() {
+        when:
+        loadRoutes """
+                - beans:
+                  - name: myCtr
+                    type: ${MyCtrBean.class.name}
+                    constructors:
+                      1: 'f2'
+                      0: 'f1'
+                    properties:
+                      age: 43 
+            """
+
+        then:
+        with(context.registry.lookupByName('myCtr'), MyCtrBean) {
+            it.field1 == 'f1'
+            it.field2 == 'f2'
+            it.age == 43
+        }
+    }
+
 }
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/model/MyCtrBean.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/model/MyCtrBean.groovy
new file mode 100644
index 00000000000..40ca33e356c
--- /dev/null
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/model/MyCtrBean.groovy
@@ -0,0 +1,44 @@
+/*
+ * 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.dsl.yaml.support.model
+
+class MyCtrBean {
+    String field1
+    String field2
+    int age;
+
+    MyCtrBean(String field1, String field2) {
+        this.field1 = field1
+        this.field2 = field2
+    }
+
+    String getField1() {
+        return field1
+    }
+
+    String getField2() {
+        return field2
+    }
+
+    int getAge() {
+        return age
+    }
+
+    void setAge(int age) {
+        this.age = age
+    }
+}