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:01 UTC
[camel] 01/01: CAMEL-19820: camel-core-model - Add to to make it easier and more tooling friendly to specify constructor args
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
+ }
+}