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 c65bdb48409e7ee05d7523a53c604267db7386fc Author: Claus Ibsen <[email protected]> AuthorDate: Thu Nov 30 09:32:43 2023 +0100 CAMEL-20130: camel-core - PropertyBuilderSupport add support for fluent builder classes. --- .../PropertyBindingSupportBuildMethodTest.java | 104 +++++++++++++++++++++ .../camel/support/PropertyBindingSupport.java | 31 ++++++ .../modules/ROOT/pages/property-binding.adoc | 51 ++++++++++ 3 files changed, 186 insertions(+) diff --git a/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportBuildMethodTest.java b/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportBuildMethodTest.java new file mode 100644 index 00000000000..507b686f704 --- /dev/null +++ b/core/camel-main/src/test/java/org/apache/camel/main/PropertyBindingSupportBuildMethodTest.java @@ -0,0 +1,104 @@ +/* + * 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.main; + +import org.apache.camel.CamelContext; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.support.PropertyBindingSupport; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Unit test for PropertyBindingSupport + */ +public class PropertyBindingSupportBuildMethodTest { + + @Test + public void testBuildClass() throws Exception { + CamelContext context = new DefaultCamelContext(); + + context.start(); + + MyDriver driver = PropertyBindingSupport.build() + .withCamelContext(context) + .withTarget(new MyDriverBuilder()) + .withFluentBuilder(true) + .withProperty("url", "localhost:1234") + .withProperty("username", "scott") + .withProperty("password", "tiger") + .build(MyDriver.class); + + Assertions.assertNotNull(driver); + Assertions.assertEquals("localhost:1234", driver.getUrl()); + Assertions.assertEquals("scott", driver.getUsername()); + Assertions.assertEquals("tiger", driver.getPassword()); + + context.stop(); + } + + public static class MyDriver { + + private final String url; + private final String username; + private final String password; + + public MyDriver(String url, String username, String password) { + this.url = url; + this.username = username; + this.password = password; + } + + public String getUrl() { + return url; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + } + + public static class MyDriverBuilder { + + private String url; + private String username; + private String password; + + public MyDriverBuilder url(String url) { + this.url = url; + return this; + } + + public MyDriverBuilder username(String username) { + this.username = username; + return this; + } + + public MyDriverBuilder password(String password) { + this.password = password; + return this; + } + + public MyDriver build() { + return new MyDriver(url, username, password); + } + } + +} 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 7d766645ee1..5f6bcaae369 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 @@ -38,6 +38,7 @@ import java.util.stream.Collectors; import org.apache.camel.CamelContext; import org.apache.camel.Component; import org.apache.camel.PropertyBindingException; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.BeanIntrospection; import org.apache.camel.spi.PropertiesComponent; import org.apache.camel.spi.PropertyConfigurer; @@ -1874,6 +1875,36 @@ public final class PropertyBindingSupport { return this; } + /** + * Binds the properties to the target object, and builds the output as the given type, by invoking the build + * method (uses build as name) + * + * @param type the type of the output class + */ + public <T> T build(Class<T> type) { + return build(type, "build"); + } + + /** + * Binds the properties to the target object, and builds the output as the given type, by invoking the build + * method (via reflection). + * + * @param type the type of the output class + * @param buildMethod the name of the builder method to invoke + */ + public <T> T build(Class<T> type, String buildMethod) { + // first bind + bind(); + + // then invoke the build method on target via reflection + try { + Object out = ObjectHelper.invokeMethodSafe(buildMethod, target); + return camelContext.getTypeConverter().convertTo(type, out); + } catch (Exception e) { + throw RuntimeCamelException.wrapRuntimeException(e); + } + } + /** * Binds the properties to the target object, and removes the property that was bound from properties. * diff --git a/docs/user-manual/modules/ROOT/pages/property-binding.adoc b/docs/user-manual/modules/ROOT/pages/property-binding.adoc index 8687eee222c..31d578cebd6 100644 --- a/docs/user-manual/modules/ROOT/pages/property-binding.adoc +++ b/docs/user-manual/modules/ROOT/pages/property-binding.adoc @@ -193,6 +193,57 @@ PropertyBindingSupport.build().withCamelContext(context).withTarget(foo) .bind(); ---- +=== Using fluent builder class + +When you are in need to configure a bean via _fluent builder class_, such as the following example: + +[source,java] +---- +public class MyDriverBuilder { + + private String url; + private String username; + private String password; + + public MyDriverBuilder url(String url) { + this.url = url; + return this; + } + + public MyDriverBuilder username(String username) { + this.username = username; + return this; + } + + public MyDriverBuilder password(String password) { + this.password = password; + return this; + } + + public MyDriver build() { + return new MyDriver(url, username, password); + } +} +---- + +And you want to create an instance of `MyDriver` via the `MyDriverBuilder` class, then this can be done as follows: + +[source,java] +---- +MyDriver driver = PropertyBindingSupport.build() + .withCamelContext(context) + .withTarget(new MyDriverBuilder()) + .withFluentBuilder(true) + .withProperty("url", "localhost:1234") + .withProperty("username", "scott") + .withProperty("password", "tiger") + .build(MyDriver.class); +---- + +Notice how we use the `build(MyDriver.class)` to build the bean via the target class `.withTarget(new MyDriverBuilder())`. +The build method will by default invoke `build` as the builder method, but you can specify the name, such as `.build(MyDriver.class, "myBuilderMethod");` + + == More details Property binding is notably used when running Camel in standalone mode with Camel Main, or using Camel Spring Boot, Camel K,
