This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch builder-class in repository https://gitbox.apache.org/repos/asf/camel.git
commit ae4e3bb4273ec523626a182920b2109d17a745e4 Author: Claus Ibsen <[email protected]> AuthorDate: Thu Nov 30 10:16:54 2023 +0100 CAMEL-20130: camel-xml-io-dsl - Allow to use bean builder classes when defining beans --- .../src/main/docs/java-xml-io-dsl.adoc | 21 +++++++++++ .../camel/dsl/xml/io/XmlRoutesBuilderLoader.java | 14 ++++++- .../apache/camel/dsl/xml/io/XmlLoadAppTest.java | 31 +++++++++++++-- .../org/apache/camel/dsl/xml/io/beans/MyBean.java | 35 +++++++++++++++++ .../camel/dsl/xml/io/beans/MyBeanBuilder.java | 44 ++++++++++++++++++++++ .../org/apache/camel/dsl/xml/io/camel-app10.xml | 37 ++++++++++++++++++ .../camel-yaml-dsl/src/main/docs/yaml-dsl.adoc | 22 +++++++++++ 7 files changed, 200 insertions(+), 4 deletions(-) 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 138021c6990..289c0c92ae5 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,27 @@ public class MyBean { NOTE: The factory method must be `public static` and from the same class as the created class itself. +=== Creating beans from builder classes + +A bean can also be created from another builder class as shown below: + +[source,xml] +---- + <bean name="myBean" type="com.acme.MyBean" + builderClass="com.acme.MyBeanBuilder" builderMethod="createMyBean"> + <properties> + <property key="id" value="123"/> + <property key="name" value="Acme"/> + </constructors> + </bean> +---- + +NOTE: The builder class must be `public` and have a no-arg default constructor. + +The builder class is then used to create the actual bean by using fluent builder style configuration. +So the properties will be set on the builder class, and the bean is created by invoking the `builderMethod` +at the end. The invocation of this method is done via Java reflection. + === Creating beans from factory bean A bean can also be created from a factory bean as shown below: 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 2b3d858b849..e19fb750a58 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 @@ -385,7 +385,19 @@ public class XmlRoutesBuilderLoader extends RouteBuilderLoaderSupport { if (target == null) { throw new NoSuchBeanException(def.getName(), "Creating bean using script returned null"); } - + } else if (def.getBuilderClass() != null) { + // builder class and method + Class<?> clazz = context.getClassResolver().resolveMandatoryClass(def.getBuilderClass()); + Object builder = context.getInjector().newInstance(clazz); + String bm = def.getBuilderMethod() != null ? def.getBuilderMethod() : "build"; + + // create bean via builder and assign as target output + target = PropertyBindingSupport.build() + .withCamelContext(context) + .withTarget(builder) + .withRemoveParameters(true) + .withProperties(def.getProperties()) + .build(Object.class, bm); } else { // factory bean/method if (def.getFactoryBean() != null && def.getFactoryMethod() != null) { 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 4039d20dd97..83700f09df1 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 @@ -243,10 +243,35 @@ public class XmlLoadAppTest { assertEquals(1, context.getRoutes().size()); // test that loaded route works - MockEndpoint y8 = context.getEndpoint("mock:y9", MockEndpoint.class); - y8.expectedBodiesReceived("Hi World from groovy Uranus"); + MockEndpoint y9 = context.getEndpoint("mock:y9", MockEndpoint.class); + y9.expectedBodiesReceived("Hi World from groovy Uranus"); context.createProducerTemplate().sendBody("direct:x9", "I'm Uranus"); - y8.assertIsSatisfied(); + y9.assertIsSatisfied(); + + context.stop(); + } + } + + @Test + public void testLoadCamelAppWithBeanBuilderClass() throws Exception { + try (DefaultCamelContext context = new DefaultCamelContext()) { + context.start(); + + Resource resource = PluginHelper.getResourceLoader(context).resolveResource( + "/org/apache/camel/dsl/xml/io/camel-app10.xml"); + + RoutesLoader routesLoader = PluginHelper.getRoutesLoader(context); + routesLoader.preParseRoute(resource, false); + routesLoader.loadRoutes(resource); + + assertNotNull(context.getRoute("r10"), "Loaded r10 route should be there"); + assertEquals(1, context.getRoutes().size()); + + // test that loaded route works + MockEndpoint y10 = context.getEndpoint("mock:y10", MockEndpoint.class); + y10.expectedBodiesReceived("Hi World. I am Camel and 44 years old!"); + context.createProducerTemplate().sendBody("direct:x10", "Hi"); + y10.assertIsSatisfied(); context.stop(); } diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyBean.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyBean.java new file mode 100644 index 00000000000..66212bda235 --- /dev/null +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyBean.java @@ -0,0 +1,35 @@ +/* + * 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 MyBean { + + private String field1; + private String field2; + private int age; + + public MyBean(String field1, String field2, int age) { + this.field1 = field1; + this.field2 = field2; + this.age = age; + } + + public String hi(String body) { + return body + " " + field1 + ". I am " + field2 + " and " + age + " years old!"; + } + +} diff --git a/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyBeanBuilder.java b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyBeanBuilder.java new file mode 100644 index 00000000000..e5e06393878 --- /dev/null +++ b/dsl/camel-xml-io-dsl/src/test/java/org/apache/camel/dsl/xml/io/beans/MyBeanBuilder.java @@ -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.xml.io.beans; + +public class MyBeanBuilder { + + private String field1; + private String field2; + private int age; + + public MyBeanBuilder field1(String field1) { + this.field1 = field1; + return this; + } + + public MyBeanBuilder field2(String field2) { + this.field2 = field2; + return this; + } + + public MyBeanBuilder age(int age) { + this.age = age; + return this; + } + + public MyBean createTheBean() { + return new MyBean(field1, field2, age); + } + +} diff --git a/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app10.xml b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app10.xml new file mode 100644 index 00000000000..9a5843ce93e --- /dev/null +++ b/dsl/camel-xml-io-dsl/src/test/resources/org/apache/camel/dsl/xml/io/camel-app10.xml @@ -0,0 +1,37 @@ +<?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.MyBean" + builderClass="org.apache.camel.dsl.xml.io.beans.MyBeanBuilder" builderMethod="createTheBean"> + <properties> + <property key="field1" value="World"/> + <property key="field2" value="Camel"/> + <property key="age" value="44"/> + </properties> + </bean> + + <route id="r10"> + <from uri="direct:x10"/> + <bean ref="xml-bean-from-registry"/> + <to uri="mock:y10"/> + </route> + +</camel> 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 7886335c75d..25d60874613 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 @@ -267,6 +267,28 @@ public class MyHelper { NOTE: The factory method must be `public static`. +=== Creating beans from builder classes + +A bean can also be created from another builder class as shown below: + +[source,yaml] +---- +- beans: + - name: myBean + type: com.acme.MyBean + builderClass: com.acme.MyBeanBuilder + builderMethod: createMyBean + properties: + id: 123 + name: 'Acme' +---- + +NOTE: The builder class must be `public` and have a no-arg default constructor. + +The builder class is then used to create the actual bean by using fluent builder style configuration. +So the properties will be set on the builder class, and the bean is created by invoking the `builderMethod` +at the end. The invocation of this method is done via Java reflection. + === Creating beans using script language For advanced use-cases then Camel allows to inline a script language, such as groovy, java, javascript, etc, to create the bean.
