This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new abb583953d9 CAMEL-19912: camel-core-model - Add factory-bean parameter
(#11557)
abb583953d9 is described below
commit abb583953d96b6d8d807dec0bcfa5e0f0d6fa548
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Sep 26 13:59:30 2023 +0200
CAMEL-19912: camel-core-model - Add factory-bean parameter (#11557)
CAMEL-19912: camel-core-model - Add factory-bean parameter
---
.../apache/camel/catalog/schemas/camel-spring.xsd | 1 +
.../camel/component/jcr/JcrConverterTest.java | 5 ++
.../apache/camel/spring/spi/SpringInjector.java | 13 ++++--
.../main/java/org/apache/camel/spi/Injector.java | 14 +++++-
.../apache/camel/impl/engine/DefaultInjector.java | 13 ++++--
.../java/org/apache/camel/impl/DefaultModel.java | 21 ++++++++-
.../camel/model/app/RegistryBeanDefinition.java | 10 ++++
.../xml/AbstractCamelContextFactoryBeanTest.java | 5 ++
.../camel/support/PropertyBindingSupportTest.java | 5 ++
.../org/apache/camel/util/ReflectionInjector.java | 26 ++++++++++-
...opertyBindingSupportClassFactoryMethodTest.java | 15 +++---
...indingSupportHelperClassFactoryMethodTest.java} | 54 ++++++++++++++++++----
.../org/apache/camel/support/EndpointHelper.java | 20 +++++++-
.../camel/support/PropertyBindingSupport.java | 42 ++++++++++++++---
.../java/org/apache/camel/xml/in/ModelParser.java | 1 +
.../java/org/apache/camel/xml/out/ModelWriter.java | 1 +
.../org/apache/camel/xml/LwModelToXMLDumper.java | 12 +++--
.../camel/xml/jaxb/JaxbModelToXMLDumper.java | 11 +++--
.../org/apache/camel/yaml/out/ModelWriter.java | 1 +
.../org/apache/camel/yaml/LwModelToYAMLDumper.java | 8 ++--
.../ROOT/pages/camel-4x-upgrade-guide-4_1.adoc | 5 ++
.../modules/ROOT/pages/property-binding.adoc | 3 ++
.../camel/main/download/KameletMainInjector.java | 9 ++++
.../xml/blueprint/BlueprintXmlBeansHandler.java | 12 +++--
.../main/xml/spring/SpringXmlBeansHandler.java | 5 +-
.../src/main/docs/java-xml-io-dsl.adoc | 34 ++++++++++++++
.../camel/dsl/xml/io/XmlRoutesBuilderLoader.java | 6 ++-
.../apache/camel/dsl/xml/io/XmlLoadAppTest.java | 25 +++++++++-
.../apache/camel/dsl/xml/io/beans/MyFacBean.java | 2 +-
.../io/beans/{MyFacBean.java => MyFacHelper.java} | 31 +------------
.../org/apache/camel/dsl/xml/io/camel-app7.xml | 41 ++++++++++++++++
.../dsl/yaml/deserializers/ModelDeserializers.java | 6 +++
.../dsl/yaml/deserializers/BeansDeserializer.java | 20 ++++----
.../generated/resources/schema/camelYamlDsl.json | 3 ++
.../camel-yaml-dsl/src/main/docs/yaml-dsl.adoc | 35 ++++++++++++++
.../org/apache/camel/dsl/yaml/BeansTest.groovy | 24 ++++++++++
.../dsl/yaml/support/model/MyFacHelper.groovy} | 35 ++------------
37 files changed, 449 insertions(+), 125 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 4727a1a81c2..66af7a0e9f2 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
@@ -13604,6 +13604,7 @@ org.apache.camel.builder.RouteBuilder.
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="factoryMethod" type="xs:string"/>
+ <xs:attribute name="factoryBean" type="xs:string"/>
</xs:complexType>
<xs:complexType name="beanConstructorsDefinition">
<xs:sequence>
diff --git
a/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
b/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
index cd4c0decd19..4f6fc8217f9 100644
---
a/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
+++
b/components/camel-jcr/src/test/java/org/apache/camel/component/jcr/JcrConverterTest.java
@@ -59,6 +59,11 @@ public class JcrConverterTest {
return null;
}
+ @Override
+ public <T> T newInstance(Class<T> type, Class<?>
factoryClass, String factoryMethod) {
+ return null;
+ }
+
@Override
public <T> T newInstance(Class<T> type, boolean
postProcessBean) {
return ObjectHelper.newInstance(type);
diff --git
a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringInjector.java
b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringInjector.java
index dc315ca6f2d..bd3c1626e70 100644
---
a/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringInjector.java
+++
b/components/camel-spring/src/main/java/org/apache/camel/spring/spi/SpringInjector.java
@@ -43,16 +43,23 @@ public class SpringInjector implements Injector {
@Override
public <T> T newInstance(Class<T> type, String factoryMethod) {
+ return newInstance(type, null, factoryMethod);
+ }
+
+ @Override
+ public <T> T newInstance(Class<T> type, Class<?> factoryClass, String
factoryMethod) {
+ Class<?> target = factoryClass != null ? factoryClass : type;
T answer = null;
try {
// lookup factory method
- Method fm = type.getMethod(factoryMethod);
- if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers()) && fm.getReturnType() == type) {
+ Method fm = target.getMethod(factoryMethod);
+ if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers())
+ && fm.getReturnType() != Void.class) {
Object obj = fm.invoke(null);
answer = type.cast(obj);
}
} catch (Exception e) {
- throw new RuntimeCamelException("Error invoking factory method: "
+ factoryMethod + " on class: " + type, e);
+ throw new RuntimeCamelException("Error invoking factory method: "
+ factoryMethod + " on class: " + target, e);
}
return answer;
}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/Injector.java
b/core/camel-api/src/main/java/org/apache/camel/spi/Injector.java
index c59bc50f32d..636090a4ccf 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/Injector.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/Injector.java
@@ -18,7 +18,7 @@ package org.apache.camel.spi;
/**
* A pluggable strategy for creating and possibly dependency injecting objects
which could be implemented using straight
- * forward reflection or using Spring or CDI to perform dependency injection.
+ * forward reflection or using Spring or Quarkus to perform dependency
injection.
*/
public interface Injector {
@@ -42,6 +42,18 @@ public interface Injector {
*/
<T> T newInstance(Class<T> type, String factoryMethod);
+ /**
+ * Instantiates a new instance of the given type by using the factory
class (this will not perform bean post
+ * processing)
+ *
+ * @param type the type of object to create
+ * @param factoryClass to create the new instance via factory class
+ * @param factoryMethod to create the new instance via factory method
which must be public static and return the
+ * type
+ * @return a newly created instance
+ */
+ <T> T newInstance(Class<T> type, Class<?> factoryClass, String
factoryMethod);
+
/**
* Instantiates a new instance of the given type; possibly injecting
values into the object in the process (bean
* post processing if enabled)
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
index 2b4b47cdf01..332dd05b64f 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultInjector.java
@@ -49,18 +49,25 @@ public class DefaultInjector implements Injector {
@Override
public <T> T newInstance(Class<T> type, String factoryMethod) {
+ return newInstance(type, null, factoryMethod);
+ }
+
+ @Override
+ public <T> T newInstance(Class<T> type, Class<?> factoryClass, String
factoryMethod) {
+ Class<?> target = factoryClass != null ? factoryClass : type;
T answer = null;
try {
// lookup factory method
- Method fm = type.getMethod(factoryMethod);
- if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers()) && fm.getReturnType() == type) {
+ Method fm = target.getMethod(factoryMethod);
+ if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers())
+ && fm.getReturnType() != Void.class) {
Object obj = fm.invoke(null);
answer = type.cast(obj);
}
// inject camel context if needed
CamelContextAware.trySetCamelContext(answer, camelContext);
} catch (Exception e) {
- throw new RuntimeCamelException("Error invoking factory method: "
+ factoryMethod + " on class: " + type, e);
+ throw new RuntimeCamelException("Error invoking factory method: "
+ factoryMethod + " on class: " + target, e);
}
return answer;
}
diff --git
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
index 729bb3ce5ff..1f651f3fc24 100644
---
a/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
+++
b/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultModel.java
@@ -631,6 +631,22 @@ public class DefaultModel implements Model {
if (className != null && (factoryMethod != null || parameters !=
null)) {
final CamelContext camelContext =
routeTemplateContext.getCamelContext();
final Class<?> clazz =
camelContext.getClassResolver().resolveMandatoryClass(className);
+ Class<?> fc = null;
+ if (factoryMethod != null) {
+ String typeOrRef = StringHelper.before(factoryMethod, ":");
+ if (typeOrRef != null) {
+ // use another class with factory method
+ factoryMethod = StringHelper.after(factoryMethod, ":");
+ // special to support factory method parameters
+ Object existing =
camelContext.getRegistry().lookupByName(typeOrRef);
+ if (existing != null) {
+ fc = existing.getClass();
+ } else {
+ fc =
camelContext.getClassResolver().resolveMandatoryClass(typeOrRef);
+ }
+ }
+ }
+ final Class<?> factoryClass = fc;
final String fqn = className;
final String fm = factoryMethod;
final String fp = parameters;
@@ -642,9 +658,10 @@ public class DefaultModel implements Model {
if (fm != null) {
if (fp != null) {
// special to support factory method parameters
- local =
PropertyBindingSupport.newInstanceFactoryParameters(camelContext, clazz, fm,
params);
+ Class<?> target = factoryClass != null ?
factoryClass : clazz;
+ local =
PropertyBindingSupport.newInstanceFactoryParameters(camelContext, target, fm,
params);
} else {
- local =
camelContext.getInjector().newInstance(clazz, fm);
+ local =
camelContext.getInjector().newInstance(clazz, factoryClass, fm);
}
if (local == null) {
throw new IllegalStateException(
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 39b34c1ff95..70100e769cd 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
@@ -48,6 +48,8 @@ public class RegistryBeanDefinition implements ResourceAware {
private String type;
@XmlAttribute
private String factoryMethod;
+ @XmlAttribute
+ private String factoryBean;
@XmlElement(name = "constructors")
@XmlJavaTypeAdapter(BeanConstructorsAdapter.class)
private Map<Integer, Object> constructors;
@@ -79,6 +81,14 @@ public class RegistryBeanDefinition implements ResourceAware
{
this.factoryMethod = factoryMethod;
}
+ public String getFactoryBean() {
+ return factoryBean;
+ }
+
+ public void setFactoryBean(String factoryBean) {
+ this.factoryBean = factoryBean;
+ }
+
public Map<Integer, Object> getConstructors() {
return constructors;
}
diff --git
a/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
b/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
index 4c112f03c79..524efd90cc7 100644
---
a/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
+++
b/core/camel-core-xml/src/test/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBeanTest.java
@@ -74,6 +74,11 @@ public class AbstractCamelContextFactoryBeanTest {
return null;
}
+ @Override
+ public <T> T newInstance(Class<T> type, Class<?> factoryClass,
String factoryMethod) {
+ return null;
+ }
+
@Override
public <T> T newInstance(Class<T> type, boolean
postProcessBean) {
return ObjectHelper.newInstance(type);
diff --git
a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
index 5c21ba511f4..f308f407b09 100644
---
a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
@@ -408,6 +408,11 @@ public class PropertyBindingSupportTest extends
ContextTestSupport {
return null;
}
+ @Override
+ public <T> T newInstance(Class<T> type, Class<?> factoryClass,
String factoryMethod) {
+ return null;
+ }
+
@Override
public <T> T newInstance(Class<T> type, boolean postProcessBean) {
return null;
diff --git
a/core/camel-core/src/test/java/org/apache/camel/util/ReflectionInjector.java
b/core/camel-core/src/test/java/org/apache/camel/util/ReflectionInjector.java
index 70b6b608de3..b363babc892 100644
---
a/core/camel-core/src/test/java/org/apache/camel/util/ReflectionInjector.java
+++
b/core/camel-core/src/test/java/org/apache/camel/util/ReflectionInjector.java
@@ -25,8 +25,11 @@ import org.apache.camel.support.ObjectHelper;
/**
* A simple implementation of {@link Injector} which just uses reflection to
instantiate new objects using their zero
- * argument constructor. For more complex implementations try the Spring or
CDI implementations.
+ * argument constructor.
+ *
+ * Use {@link org.apache.camel.impl.engine.DefaultInjector} instead.
*/
+@Deprecated
public class ReflectionInjector implements Injector {
@Override
@@ -40,7 +43,8 @@ public class ReflectionInjector implements Injector {
try {
// lookup factory method
Method fm = type.getMethod(factoryMethod);
- if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers()) && fm.getReturnType() == type) {
+ if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers())
+ && fm.getReturnType() != Void.TYPE) {
answer = (T) fm.invoke(null);
}
} catch (Exception e) {
@@ -49,6 +53,24 @@ public class ReflectionInjector implements Injector {
return answer;
}
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T newInstance(Class<T> type, Class<?> factoryClass, String
factoryMethod) {
+ T answer = null;
+ try {
+ // lookup factory method
+ Method fm = factoryClass.getMethod(factoryMethod);
+ if (Modifier.isStatic(fm.getModifiers()) &&
Modifier.isPublic(fm.getModifiers())
+ && fm.getReturnType() != Void.TYPE) {
+ answer = (T) fm.invoke(null);
+ }
+ } catch (Exception e) {
+ throw new RuntimeCamelException(
+ "Error invoking factory method: " + factoryMethod + " on
factory class: " + factoryClass, e);
+ }
+ return answer;
+ }
+
@Override
public <T> T newInstance(Class<T> type, boolean postProcessBean) {
return ObjectHelper.newInstance(type);
diff --git
a/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
b/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
index f48d9c1f23f..2038916ac97 100644
---
a/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
+++
b/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
@@ -42,7 +42,8 @@ public class PropertyBindingSupportClassFactoryMethodTest {
.withCamelContext(context)
.withTarget(target)
.withProperty("name", "Donald")
- .withProperty("myDriver", "#class:" + MyDriver.class.getName()
+ "('localhost:2121', 'scott', 'tiger')")
+ .withProperty("myDriver",
+ "#class:" + MyDriver.class.getName() +
"#createDriver('localhost:2121', 'scott', 'tiger')")
.withRemoveParameters(false).bind();
assertEquals("Donald", target.getName());
@@ -72,7 +73,7 @@ public class PropertyBindingSupportClassFactoryMethodTest {
.withTarget(target)
.withProperty("name", "Donald")
.withProperty("myDriver",
- "#class:" + MyDriver.class.getName() + "('{{myUrl}}',
'{{myUsername}}', '{{myPassword}}')")
+ "#class:" + MyDriver.class.getName() +
"#createDriver('{{myUrl}}', '{{myUsername}}', '{{myPassword}}')")
.withRemoveParameters(false).bind();
assertEquals("Donald", target.getName());
@@ -111,10 +112,12 @@ public class PropertyBindingSupportClassFactoryMethodTest
{
private String username;
private String password;
- public MyDriver(String url, String username, String password) {
- this.url = url;
- this.username = username;
- this.password = password;
+ public static MyDriver createDriver(String url, String username,
String password) {
+ MyDriver driver = new MyDriver();
+ driver.url = url;
+ driver.username = username;
+ driver.password = password;
+ return driver;
}
public String getUrl() {
diff --git
a/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
b/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportHelperClassFactoryMethodTest.java
similarity index 67%
copy from
core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
copy to
core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportHelperClassFactoryMethodTest.java
index f48d9c1f23f..ad713f7872a 100644
---
a/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportClassFactoryMethodTest.java
+++
b/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportHelperClassFactoryMethodTest.java
@@ -28,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Unit test for PropertyBindingSupport
*/
-public class PropertyBindingSupportClassFactoryMethodTest {
+public class PropertyBindingSupportHelperClassFactoryMethodTest {
@Test
public void testFactory() throws Exception {
@@ -42,7 +42,9 @@ public class PropertyBindingSupportClassFactoryMethodTest {
.withCamelContext(context)
.withTarget(target)
.withProperty("name", "Donald")
- .withProperty("myDriver", "#class:" + MyDriver.class.getName()
+ "('localhost:2121', 'scott', 'tiger')")
+ .withProperty("myDriver", "#class:" + MyDriver.class.getName()
+ + "#" +
MyDriverHelper.class.getName()
+ + ":createDriver('localhost:2121',
'scott', 'tiger')")
.withRemoveParameters(false).bind();
assertEquals("Donald", target.getName());
@@ -72,7 +74,35 @@ public class PropertyBindingSupportClassFactoryMethodTest {
.withTarget(target)
.withProperty("name", "Donald")
.withProperty("myDriver",
- "#class:" + MyDriver.class.getName() + "('{{myUrl}}',
'{{myUsername}}', '{{myPassword}}')")
+ "#class:" + MyDriver.class.getName()
+ + "#" +
MyDriverHelper.class.getName()
+ + ":createDriver('{{myUrl}}',
'{{myUsername}}', '{{myPassword}}')")
+ .withRemoveParameters(false).bind();
+
+ assertEquals("Donald", target.getName());
+ assertEquals("localhost:2121", target.getMyDriver().getUrl());
+ assertEquals("scott", target.getMyDriver().getUsername());
+ assertEquals("tiger", target.getMyDriver().getPassword());
+
+ context.stop();
+ }
+
+ @Test
+ public void testFactoryRef() throws Exception {
+ CamelContext context = new DefaultCamelContext();
+
+ context.getRegistry().bind("myDriverHelper", new MyDriverHelper());
+
+ context.start();
+
+ MyApp target = new MyApp();
+
+ PropertyBindingSupport.build()
+ .withCamelContext(context)
+ .withTarget(target)
+ .withProperty("name", "Donald")
+ .withProperty("myDriver", "#class:" + MyDriver.class.getName()
+ +
"#myDriverHelper:createDriver('localhost:2121', 'scott', 'tiger')")
.withRemoveParameters(false).bind();
assertEquals("Donald", target.getName());
@@ -105,18 +135,24 @@ public class PropertyBindingSupportClassFactoryMethodTest
{
}
}
+ public static class MyDriverHelper {
+
+ public static MyDriver createDriver(String url, String username,
String password) {
+ MyDriver driver = new MyDriver();
+ driver.url = url;
+ driver.username = username;
+ driver.password = password;
+ return driver;
+ }
+
+ }
+
public static class MyDriver {
private String url;
private String username;
private String password;
- public MyDriver(String url, String username, String password) {
- this.url = url;
- this.username = username;
- this.password = password;
- }
-
public String getUrl() {
return url;
}
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
index c37820caa3f..11fba313980 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/EndpointHelper.java
@@ -377,11 +377,27 @@ public final class EndpointHelper {
className = StringHelper.before(className, "#");
}
Class<?> clazz =
camelContext.getClassResolver().resolveMandatoryClass(className);
+ Class<?> factoryClass = null;
+ if (factoryMethod != null) {
+ String typeOrRef = StringHelper.before(factoryMethod, ":");
+ if (typeOrRef != null) {
+ // use another class with factory method
+ factoryMethod = StringHelper.after(factoryMethod, ":");
+ // special to support factory method parameters
+ Object existing =
camelContext.getRegistry().lookupByName(typeOrRef);
+ if (existing != null) {
+ factoryClass = existing.getClass();
+ } else {
+ factoryClass =
camelContext.getClassResolver().resolveMandatoryClass(typeOrRef);
+ }
+ }
+ }
if (factoryMethod != null && parameters != null) {
- answer =
PropertyBindingSupport.newInstanceFactoryParameters(camelContext, clazz,
factoryMethod, parameters);
+ Class<?> target = factoryClass != null ? factoryClass : clazz;
+ answer =
PropertyBindingSupport.newInstanceFactoryParameters(camelContext, target,
factoryMethod, parameters);
} else if (factoryMethod != null) {
- answer = camelContext.getInjector().newInstance(type,
factoryMethod);
+ answer = camelContext.getInjector().newInstance(type,
factoryClass, factoryMethod);
} else if (parameters != null) {
answer =
PropertyBindingSupport.newInstanceConstructorParameters(camelContext, clazz,
parameters);
} else {
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
index 986cd2180d9..c8153a261fe 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
@@ -70,8 +70,10 @@ import static
org.apache.camel.util.StringHelper.startsWithIgnoreCase;
* the instance via a factory method then you specify the method as shown:
#class:com.foo.MyClassType#myFactoryMethod.
* And if the factory method requires parameters they can be specified as
follows:
* #class:com.foo.MyClassType#myFactoryMethod('Hello World', 5, true). Or if
you need to create the instance via
- * constructor parameters then you can specify the parameters as shown:
#class:com.foo.MyClass('Hello World', 5,
- * true)</li>.
+ * constructor parameters then you can specify the parameters as shown:
#class:com.foo.MyClass('Hello World', 5, true).
+ * If the factory method is on another bean or class, then you must specify
this as shown:
+ * #class:com.foo.MyClassType#com.foo.MyFactory:myFactoryMethod. Where
com.foo.MyFactory either refers to an class name,
+ * or can refer to an existing bean by id, such as:
#class:com.foo.MyClassType#myFactoryBean:myFactoryMethod.</li>.
* <li>valueAs(type):value</li> - To declare that the value should be
converted to the given type, such as
* #valueAs(int):123 which indicates that the value 123 should be converted to
an integer.
* <li>ignore case - Whether to ignore case for property keys</li>
@@ -1372,11 +1374,26 @@ public final class PropertyBindingSupport {
for (int i = 0; i < found.getParameterCount(); i++) {
Class<?> paramType = found.getParameterTypes()[i];
Object param = params[i];
- Object val =
camelContext.getTypeConverter().convertTo(paramType, param);
+ Object val = null;
+ // special as we may refer to other #bean or #type in the
parameter
+ if (param instanceof String) {
+ String str = param.toString();
+ if (str.startsWith("#")) {
+ Object bean = resolveBean(camelContext, param);
+ if (bean != null) {
+ val = bean;
+ }
+ }
+ }
// unquote text
if (val instanceof String) {
val = StringHelper.removeLeadingAndEndingQuotes((String)
val);
}
+ if (val != null) {
+ val =
camelContext.getTypeConverter().tryConvertTo(paramType, val);
+ } else {
+ val = camelContext.getTypeConverter().convertTo(paramType,
param);
+ }
arr[i] = val;
}
@@ -1558,11 +1575,24 @@ public final class PropertyBindingSupport {
}
Class<?> type =
camelContext.getClassResolver().resolveMandatoryClass(className);
if (factoryMethod != null) {
- if (parameters != null) {
+ Class<?> factoryClass = null;
+ String typeOrRef = StringHelper.before(factoryMethod, ":");
+ if (typeOrRef != null) {
+ // use another class with factory method
+ factoryMethod = StringHelper.after(factoryMethod, ":");
// special to support factory method parameters
- answer = newInstanceFactoryParameters(camelContext, type,
factoryMethod, parameters);
+ Object existing =
camelContext.getRegistry().lookupByName(typeOrRef);
+ if (existing != null) {
+ factoryClass = existing.getClass();
+ } else {
+ factoryClass =
camelContext.getClassResolver().resolveMandatoryClass(typeOrRef);
+ }
+ }
+ if (parameters != null) {
+ Class<?> target = factoryClass != null ? factoryClass :
type;
+ answer = newInstanceFactoryParameters(camelContext,
target, factoryMethod, parameters);
} else {
- answer = camelContext.getInjector().newInstance(type,
factoryMethod);
+ answer = camelContext.getInjector().newInstance(type,
factoryClass, factoryMethod);
}
if (answer == null) {
throw new IllegalStateException(
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 7d49154c5ad..7dcff72a36b 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
@@ -1634,6 +1634,7 @@ public class ModelParser extends BaseParser {
protected RegistryBeanDefinition doParseRegistryBeanDefinition() throws
IOException, XmlPullParserException {
return doParse(new RegistryBeanDefinition(), (def, key, val) -> {
switch (key) {
+ case "factoryBean": def.setFactoryBean(val); break;
case "factoryMethod": def.setFactoryMethod(val); break;
case "name": def.setName(val); break;
case "type": def.setType(val); break;
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 2c2ef105ef5..4e228274c16 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
@@ -2569,6 +2569,7 @@ public class ModelWriter extends BaseWriter {
doWriteAttribute("factoryMethod", def.getFactoryMethod());
doWriteAttribute("name", def.getName());
doWriteAttribute("type", def.getType());
+ doWriteAttribute("factoryBean", def.getFactoryBean());
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 252c86dfce2..7cec1ce562b 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
@@ -324,12 +324,14 @@ public class LwModelToXMLDumper implements
ModelToXMLDumper {
if (type.startsWith("#class:")) {
type = type.substring(7);
}
- String factoryMethod = b.getFactoryMethod();
- if (factoryMethod != null) {
- buffer.write(String.format(" <bean name=\"%s\" type=\"%s\"
factoryMethod=\"%s\">%n", b.getName(), type, factoryMethod));
- } else {
- buffer.write(String.format(" <bean name=\"%s\"
type=\"%s\">%n", b.getName(), type));
+ buffer.write(String.format(" <bean name=\"%s\" type=\"%s\"",
b.getName(), type));
+ if (b.getFactoryBean() != null) {
+ buffer.write(String.format(" factory-bean=\"%s\"",
b.getFactoryBean()));
}
+ if (b.getFactoryMethod() != null) {
+ buffer.write(String.format(" factory-method=\"%s\"",
b.getFactoryMethod()));
+ }
+ buffer.write(">\n");
if (b.getConstructors() != null && !b.getConstructors().isEmpty())
{
buffer.write(String.format(" <constructors>%n"));
for (Map.Entry<Integer, Object> entry :
b.getConstructors().entrySet()) {
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 8fa8b190bc9..02e3078c6b1 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
@@ -337,12 +337,15 @@ public class JaxbModelToXMLDumper implements
ModelToXMLDumper {
if (type.startsWith("#class:")) {
type = type.substring(7);
}
+ buffer.write(String.format(" <bean name=\"%s\" type=\"%s\"",
b.getName(), type));
String factoryMethod = b.getFactoryMethod();
- if (factoryMethod != null) {
- buffer.write(String.format(" <bean name=\"%s\" type=\"%s\"
factoryMethod=\"%s\">%n", b.getName(), type, factoryMethod));
- } else {
- buffer.write(String.format(" <bean name=\"%s\"
type=\"%s\">%n", b.getName(), type));
+ if (b.getFactoryBean() != null) {
+ buffer.write(String.format(" factory-bean=\"%s\"",
b.getFactoryBean()));
}
+ if (b.getFactoryMethod() != null) {
+ buffer.write(String.format(" factory-method=\"%s\"",
b.getFactoryMethod()));
+ }
+ buffer.write(">\n");
if (b.getConstructors() != null && !b.getConstructors().isEmpty())
{
buffer.write(String.format(" <constructors>%n"));
for (Map.Entry<Integer, Object> entry :
b.getConstructors().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 09249ae2272..08c098e8cf0 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
@@ -2569,6 +2569,7 @@ public class ModelWriter extends BaseWriter {
doWriteAttribute("factoryMethod", def.getFactoryMethod());
doWriteAttribute("name", def.getName());
doWriteAttribute("type", def.getType());
+ doWriteAttribute("factoryBean", def.getFactoryBean());
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 7cca44385c9..2507043724a 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
@@ -312,11 +312,13 @@ public class LwModelToYAMLDumper implements
ModelToYAMLDumper {
if (type.startsWith("#class:")) {
type = type.substring(7);
}
- String factoryMethod = b.getFactoryMethod();
buffer.write(String.format(" - name: %s%n", b.getName()));
buffer.write(String.format(" type: \"%s\"%n", type));
- if (factoryMethod != null) {
- buffer.write(String.format(" factoryMethod: \"%s\"%n",
factoryMethod));
+ if (b.getFactoryBean() != null) {
+ buffer.write(String.format(" factoryBean: \"%s\"%n",
b.getFactoryBean()));
+ }
+ if (b.getFactoryMethod() != null) {
+ buffer.write(String.format(" factoryMethod: \"%s\"%n",
b.getFactoryMethod()));
}
if (b.getConstructors() != null && !b.getConstructors().isEmpty())
{
buffer.write(String.format(" constructors:%n"));
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_1.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_1.adoc
index 246b3e864f8..59060d1ec75 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_1.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_1.adoc
@@ -6,6 +6,11 @@ from both 4.0 to 4.1 and 4.1 to 4.2.
== Upgrading Camel 4.0 to 4.1
+=== camel-api
+
+Add method `newInstance(Class<T> type, Class<?> factoryClass, String
factoryMethod)`
+to `org.apache.camel.spi.Injector`.
+
=== camel-management
Dumping routes to JMX no longer includes `customId="true"` in the XML nodes.
diff --git a/docs/user-manual/modules/ROOT/pages/property-binding.adoc
b/docs/user-manual/modules/ROOT/pages/property-binding.adoc
index 267e87a3fae..8687eee222c 100644
--- a/docs/user-manual/modules/ROOT/pages/property-binding.adoc
+++ b/docs/user-manual/modules/ROOT/pages/property-binding.adoc
@@ -28,6 +28,9 @@ The `PropertyBindingSupport` class supports binding String
valued properties to
`#class:com.foo.MyClassType#myFactoryMethod('Hello World', 5, true)`.
Or if you need to create the instance via constructor parameters then
you can specify the parameters as shown:
`#class:com.foo.MyClass('Hello World', 5, true)`.
+ If the factory method is on another bean or class, then you must
specify this as shown:
+ `#class:com.foo.MyClassType#com.foo.MyFactory:myFactoryMethod`. Where
`com.foo.MyFactory` either refers to a FQN classname,
+ or can refer to an existing bean by id, such as:
`#class:com.foo.MyClassType#myFactoryBean:myFactoryMethod`.
- _valueAs(type):value_ - To declare that the value should be converted to the
given type, such as `#valueAs(int):123`
which indicates that the value 123 should be converted to an integer.
- _ignore case_ - Whether to ignore case for property keys (will ignore by
default)
diff --git
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
index c1a691db61e..8e8a7449bdd 100644
---
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
+++
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/KameletMainInjector.java
@@ -56,6 +56,15 @@ public class KameletMainInjector implements Injector {
return delegate.newInstance(type, factoryMethod);
}
+ @Override
+ public <T> T newInstance(Class<T> type, Class<?> factoryClass, String
factoryMethod) {
+ boolean accept = acceptComponent(type);
+ if (!accept) {
+ return (T) delegate.newInstance(StubComponent.class);
+ }
+ return delegate.newInstance(type, factoryClass, factoryMethod);
+ }
+
@Override
public <T> T newInstance(Class<T> type, boolean postProcessBean) {
boolean accept = acceptComponent(type);
diff --git
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/blueprint/BlueprintXmlBeansHandler.java
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/blueprint/BlueprintXmlBeansHandler.java
index 5548661cae2..cba1329dd65 100644
---
a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/blueprint/BlueprintXmlBeansHandler.java
+++
b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/xml/blueprint/BlueprintXmlBeansHandler.java
@@ -107,7 +107,11 @@ public class BlueprintXmlBeansHandler {
rrd.setType(XmlHelper.getAttribute(node, "class"));
rrd.setName(name);
- // factory method
+ // factory bean/method
+ String fb = XmlHelper.getAttribute(node, "factory-ref");
+ if (fb != null) {
+ rrd.setFactoryBean(fb);
+ }
String fm = XmlHelper.getAttribute(node, "factory-method");
if (fm != null) {
rrd.setFactoryMethod(fm);
@@ -210,8 +214,10 @@ public class BlueprintXmlBeansHandler {
type = "#class:" + type;
}
try {
- // factory method
- if (def.getFactoryMethod() != null) {
+ // factory bean/method
+ if (def.getFactoryBean() != null && def.getFactoryMethod() !=
null) {
+ type = type + "#" + def.getFactoryBean() + ":" +
def.getFactoryMethod();
+ } else if (def.getFactoryMethod() != null) {
type = type + "#" + def.getFactoryMethod();
}
// property binding support has constructor arguments as part
of the type
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 61ad9c44fa8..b371c5a2ac0 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
@@ -236,7 +236,10 @@ public class SpringXmlBeansHandler {
rrd.setName(name);
model.addRegistryBean(rrd);
- // factory method
+ // factory bean/method
+ if (def.getFactoryBeanName() != null) {
+ rrd.setFactoryBean(def.getFactoryBeanName());
+ }
if (def.getFactoryMethodName() != null) {
rrd.setFactoryMethod(def.getFactoryMethodName());
}
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 4b1e029eff7..f96371e8a0f 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
@@ -188,6 +188,40 @@ public class MyBean {
NOTE: The factory method must be `public static` and from the same class as
the created class itself.
+=== Creating beans from factory bean
+
+A bean can also be created from a factory bean as shown below:
+
+[source,xml]
+----
+ <bean name="myBean" type="com.acme.MyBean"
+ factoryBean="com.acme.MyHelper" factoryMethod="createMyBean">
+ <constructors>
+ <constructor index="0" value="true"/>
+ <constructor index="1" value="Hello World"/>
+ </constructors>
+ </bean>
+----
+
+TIP: `factoryBean` can also refer to an existing bean by bean id instead of
FQN classname.
+
+When using `factoryBean` and `factoryMethod` then the arguments to this method
is taken from `constructors`.
+So in the example above, this means that class `com.acme.MyHelper` should be
as follows:
+
+[source,java]
+----
+public class MyHelper {
+
+ public static MyBean createMyBean(boolean important, String message) {
+ MyBean answer = ...
+ // create and configure the bean
+ return answer;
+ }
+}
+----
+
+NOTE: The factory method must be `public static`.
+
== See Also
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 541eda03ae2..604378a65ba 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
@@ -327,8 +327,10 @@ public class XmlRoutesBuilderLoader extends
RouteBuilderLoaderSupport {
if (type != null && !type.startsWith("#")) {
type = "#class:" + type;
try {
- // factory method
- if (def.getFactoryMethod() != null) {
+ // factory bean/method
+ if (def.getFactoryBean() != null && def.getFactoryMethod() !=
null) {
+ type = type + "#" + def.getFactoryBean() + ":" +
def.getFactoryMethod();
+ } else if (def.getFactoryMethod() != null) {
type = type + "#" + def.getFactoryMethod();
}
// property binding support has constructor arguments as part
of the type
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 59dddb4ef9d..3f031dccd43 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
@@ -145,7 +145,7 @@ public class XmlLoadAppTest {
}
@Test
- public void testLoadCamelAppWithBeanFactory() throws Exception {
+ public void testLoadCamelAppWithBeanFactoryMethod() throws Exception {
try (DefaultCamelContext context = new DefaultCamelContext()) {
context.start();
@@ -167,4 +167,27 @@ public class XmlLoadAppTest {
}
}
+ @Test
+ public void testLoadCamelAppWithBeanFactoryBeanAndMethod() throws
Exception {
+ try (DefaultCamelContext context = new DefaultCamelContext()) {
+ context.start();
+
+ Resource resource =
PluginHelper.getResourceLoader(context).resolveResource(
+ "/org/apache/camel/dsl/xml/io/camel-app7.xml");
+
+ RoutesLoader routesLoader = PluginHelper.getRoutesLoader(context);
+ routesLoader.preParseRoute(resource, false);
+ routesLoader.loadRoutes(resource);
+
+ assertNotNull(context.getRoute("r7"), "Loaded r7 route should be
there");
+ assertEquals(1, context.getRoutes().size());
+
+ // test that loaded route works
+ MockEndpoint y7 = context.getEndpoint("mock:y7",
MockEndpoint.class);
+ y7.expectedBodiesReceived("Hello Pluto. I am Camel and 44 years
old!");
+ context.createProducerTemplate().sendBody("direct:x7", "Pluto");
+ y7.assertIsSatisfied();
+ }
+ }
+
}
diff --git
a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
index 3db2c39de10..f226415da8b 100644
---
a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
+++
b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
@@ -26,7 +26,7 @@ public class MyFacBean {
return new MyFacBean(field1, field2);
}
- private MyFacBean(String field1, String field2) {
+ MyFacBean(String field1, String field2) {
this.field1 = field1;
this.field2 = field2;
}
diff --git
a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacHelper.java
similarity index 62%
copy from
dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
copy to
dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacHelper.java
index 3db2c39de10..e27b943eafc 100644
---
a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
+++
b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacHelper.java
@@ -16,39 +16,10 @@
*/
package org.apache.camel.dsl.xml.io.beans;
-public class MyFacBean {
-
- private String field1;
- private String field2;
- private int age;
+public class MyFacHelper {
public static MyFacBean createBean(String field1, String field2) {
return new MyFacBean(field1, field2);
}
- private MyFacBean(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 hi(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-app7.xml
b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app7.xml
new file mode 100644
index 00000000000..396f9768418
--- /dev/null
+++
b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app7.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.
+
+-->
+<camel xmlns="http://camel.apache.org/schema/spring"
xmlns:s="http://www.springframework.org/schema/beans">
+
+ <bean name="myHelper"
type="org.apache.camel.dsl.xml.io.beans.MyFacHelper"/>
+
+ <bean name="xml-bean-from-registry"
type="org.apache.camel.dsl.xml.io.beans.MyFacBean"
+ factoryBean="myHelper" factoryMethod="createBean">
+ <constructors>
+ <constructor value="Hello"/>
+ <constructor value="Camel"/>
+ </constructors>
+ <properties>
+ <property key="age" value="44"/>
+ </properties>
+ </bean>
+
+ <route id="r7">
+ <from uri="direct:x7"/>
+ <bean ref="xml-bean-from-registry" method="hi"/>
+ <to uri="mock:y7"/>
+ </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 b8e5b914ec2..45c0068500c 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
@@ -12349,6 +12349,7 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
order =
org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
properties = {
@YamlProperty(name = "constructors", type = "object"),
+ @YamlProperty(name = "factory-bean", type = "string"),
@YamlProperty(name = "factory-method", type = "string"),
@YamlProperty(name = "name", type = "string", required =
true),
@YamlProperty(name = "properties", type = "object"),
@@ -12374,6 +12375,11 @@ public final class ModelDeserializers extends
YamlDeserializerSupport {
target.setConstructors(val);
break;
}
+ case "factory-bean": {
+ String val = asText(node);
+ target.setFactoryBean(val);
+ break;
+ }
case "factory-method": {
String val = asText(node);
target.setFactoryMethod(val);
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 917ea258fd3..905d5a4ce21 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
@@ -91,19 +91,21 @@ public class BeansDeserializer extends
YamlDeserializerSupport implements Constr
beanCache.clear();
}
- public Object newInstance(RegistryBeanDefinition bean, CamelContext
context) throws Exception {
+ public Object newInstance(RegistryBeanDefinition def, CamelContext
context) throws Exception {
- String type = bean.getType();
+ String type = def.getType();
- // factory method
- if (bean.getFactoryMethod() != null) {
- type = type + "#" + bean.getFactoryMethod();
+ // factory bean/method
+ if (def.getFactoryBean() != null && def.getFactoryMethod() != null) {
+ type = type + "#" + def.getFactoryBean() + ":" +
def.getFactoryMethod();
+ } else if (def.getFactoryMethod() != null) {
+ type = type + "#" + def.getFactoryMethod();
}
// property binding support has constructor arguments as part of the
type
StringJoiner ctr = new StringJoiner(", ");
- if (bean.getConstructors() != null &&
!bean.getConstructors().isEmpty()) {
+ if (def.getConstructors() != null && !def.getConstructors().isEmpty())
{
// need to sort constructor args based on index position
- Map<Integer, Object> sorted = new
TreeMap<>(bean.getConstructors());
+ Map<Integer, Object> sorted = new TreeMap<>(def.getConstructors());
for (Object val : sorted.values()) {
String text = val.toString();
if (!StringHelper.isQuoted(text)) {
@@ -116,8 +118,8 @@ public class BeansDeserializer extends
YamlDeserializerSupport implements Constr
final Object target = PropertyBindingSupport.resolveBean(context,
type);
- if (bean.getProperties() != null && !bean.getProperties().isEmpty()) {
- PropertyBindingSupport.setPropertiesOnTarget(context, target,
bean.getProperties());
+ if (def.getProperties() != null && !def.getProperties().isEmpty()) {
+ PropertyBindingSupport.setPropertiesOnTarget(context, target,
def.getProperties());
}
return target;
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 7a3c7e0c5fc..4c298bdbda4 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
@@ -8026,6 +8026,9 @@
"constructors" : {
"type" : "object"
},
+ "factoryBean" : {
+ "type" : "string"
+ },
"factoryMethod" : {
"type" : "string"
},
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
index 49c68aca270..71fd6f385e6 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc
@@ -232,6 +232,41 @@ public class MyBean {
NOTE: The factory method must be `public static` and from the same class as
the created class itself.
+=== Creating beans from factory bean
+
+A bean can also be created from a factory bean as shown below:
+
+[source,yaml]
+----
+- beans:
+ - name: myBean
+ type: com.acme.MyBean
+ factoryBean: com.acme.MyHelper
+ factoryMethod: createMyBean
+ constructors:
+ 0: true
+ 1: "Hello World"
+----
+
+TIP: `factoryBean` can also refer to an existing bean by bean id instead of
FQN classname.
+
+When using `factoryBean` and `factoryMethod` then the arguments to this method
is taken from `constructors`.
+So in the example above, this means that class `com.acme.MyHelper` should be
as follows:
+
+[source,java]
+----
+public class MyHelper {
+
+ public static MyBean createMyBean(boolean important, String message) {
+ MyBean answer = ...
+ // create and configure the bean
+ return answer;
+ }
+}
+----
+
+NOTE: The factory method must be `public static`.
+
== Configuring options on languages
Some xref:components:languages:index.adoc[Languages] have additional
configurations
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 eb24f59d604..1d3209c6627 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
@@ -20,6 +20,7 @@ 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
import org.apache.camel.dsl.yaml.support.model.MyFacBean
+import org.apache.camel.dsl.yaml.support.model.MyFacHelper
class BeansTest extends YamlTestSupport {
@@ -154,5 +155,28 @@ class BeansTest extends YamlTestSupport {
}
}
+ def "beans with factory helper"() {
+ when:
+ loadRoutes """
+ - beans:
+ - name: myFac
+ type: ${MyFacBean.class.name}
+ factoryBean: ${MyFacHelper.class.name}
+ factoryMethod: createBean
+ constructors:
+ 0: 'fac1'
+ 1: 'fac2'
+ properties:
+ age: 43
+ """
+
+ then:
+ with(context.registry.lookupByName('myFac'), MyFacBean) {
+ it.field1 == 'fac1'
+ it.field2 == 'fac2'
+ it.age == 43
+ }
+ }
+
}
diff --git
a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/model/MyFacHelper.groovy
similarity index 54%
copy from
dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
copy to
dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/model/MyFacHelper.groovy
index 3db2c39de10..93e19d044ed 100644
---
a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyFacBean.java
+++
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/model/MyFacHelper.groovy
@@ -14,41 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.dsl.xml.io.beans;
+package org.apache.camel.dsl.yaml.support.model
-public class MyFacBean {
+class MyFacHelper {
- private String field1;
- private String field2;
- private int age;
-
- public static MyFacBean createBean(String field1, String field2) {
+ static MyFacBean createBean(String field1, String field2) {
return new MyFacBean(field1, field2);
}
- private MyFacBean(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 hi(String body) {
- return field1 + " " + body + ". I am " + field2 + " and " + age + "
years old!";
- }
-
}