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

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


The following commit(s) were added to refs/heads/master by this push:
     new d7b26b9  CAMEL-15398: Add documentation page about properties binding 
(via camel-main)
d7b26b9 is described below

commit d7b26b927c6174a834e95a99d17fbc3c4d5e29d5
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Wed Aug 12 16:08:53 2020 +0200

    CAMEL-15398: Add documentation page about properties binding (via 
camel-main)
---
 .../camel/support/PropertyBindingSupport.java      |   3 +-
 .../modules/ROOT/pages/rest-component.adoc         |   2 +-
 .../modules/ROOT/pages/configuring-camel.adoc      |   7 +
 .../modules/ROOT/pages/property-binding.adoc       | 198 +++++++++++++++++++++
 4 files changed, 208 insertions(+), 2 deletions(-)

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 5a8308b..fbfd17a 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
@@ -57,7 +57,8 @@ import static org.apache.camel.util.ObjectHelper.isNotEmpty;
  *     <li>list</li> - Properties can refer or add to in List's using list 
syntax, eg foo[0] where foo is the name of the property that is a
  *                     List instance, and 0 is the index. To refer to the last 
element, then use last as key.</li>
  *     <li>reference by property placeholder id - Values can refer to a 
property placeholder key with #property:myKey</li>
- *     <li>reference by bean id - Values can refer to other beans in the 
registry by prefixing with with # or #bean: eg #myBean or #bean:myBean</li>
+ *     <li>reference by bean id - Values can refer to other beans in the 
registry by prefixing with # or #bean: eg #myBean or #bean:myBean.
+ *                                It is recommended to favour using `#bean:` 
syntax to make it obvious it's a bean reference.</li>
  *     <li>reference by type - Values can refer to singleton beans by their 
type in the registry by prefixing with #type: syntax, eg 
#type:com.foo.MyClassType</li>
  *     <li>autowire by type - Values can refer to singleton beans by auto 
wiring by setting the value to #autowired</li>
  *     <li>reference new class - Values can refer to creating new beans by 
their class name by prefixing with #class, eg #class:com.foo.MyClassType.
diff --git a/docs/components/modules/ROOT/pages/rest-component.adoc 
b/docs/components/modules/ROOT/pages/rest-component.adoc
index 7e3612a..62d60b9 100644
--- a/docs/components/modules/ROOT/pages/rest-component.adoc
+++ b/docs/components/modules/ROOT/pages/rest-component.adoc
@@ -90,7 +90,7 @@ with the following path and query parameters:
 | *host* (producer) | Host and port of HTTP service to use (override host in 
openapi schema) |  | String
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy 
(on the first message). By starting lazy you can use this to allow CamelContext 
and routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and [...]
 | *producerComponentName* (producer) | The Camel Rest component to use for 
(producer) the REST transport, such as http, undertow. If no component has been 
explicit configured, then Camel will lookup if there is a Camel component that 
integrates with the Rest DSL, or if a org.apache.camel.spi.RestProducerFactory 
is registered in the registry. If either one is found, then that is being used. 
|  | String
-| *queryParameters* (producer) | Query parameters for the HTTP service to call 
|  | String
+| *queryParameters* (producer) | Query parameters for the HTTP service to 
call. The query parameters can contain multiple parameters separated by 
ampersand such such as foo=123&bar=456. |  | String
 | *basicPropertyBinding* (advanced) | Whether the endpoint should use basic 
property binding (Camel 2.x) or the newer property binding with additional 
capabilities | false | boolean
 | *synchronous* (advanced) | Sets whether synchronous processing should be 
strictly used, or Camel is allowed to use asynchronous processing (if 
supported). | false | boolean
 |===
diff --git a/docs/user-manual/modules/ROOT/pages/configuring-camel.adoc 
b/docs/user-manual/modules/ROOT/pages/configuring-camel.adoc
index 0124d90..b818cfc 100644
--- a/docs/user-manual/modules/ROOT/pages/configuring-camel.adoc
+++ b/docs/user-manual/modules/ROOT/pages/configuring-camel.adoc
@@ -70,4 +70,11 @@ schema then you'd hack that file to add your component &
 xref:contributing.adoc[contribute a patch] to the camel XSD. Otherwise
 you could write your own namespace & schema if you prefer.
 
+[[ConfiguringCamel-PropertyBinding]]
+== Configuring using properties
 
+Camel is very configurable with properties using the following features:
+
+- xref:property-binding.adoc[Property Binding]
+- xref:using-propertyplaceholder.adoc[Property Placeholders]
+- xref:components::properties-component.adoc[Properties Component]
diff --git a/docs/user-manual/modules/ROOT/pages/property-binding.adoc 
b/docs/user-manual/modules/ROOT/pages/property-binding.adoc
new file mode 100644
index 0000000..02f87da
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/property-binding.adoc
@@ -0,0 +1,198 @@
+[[PropertyBinding-PropertyBinding]]
+= Property binding in Camel
+
+Camel supports binding property values (key=value) in many places such as 
configuration of Camel
+components, endpoints, EIPs, and Camel bootstrap configuration.
+
+Together with property placeholders, property placeholder functions, then 
there is plenty of power, but also
+something that takes a little learning to master.
+
+== Property binding features
+
+The core of Camels property binding is implemented in 
`PropertyBindingSupport.java` which is used internally in Camel,
+and as well can be used by Camel component developers.
+
+The `PropertyBindingSupport` class supports binding String valued properties 
to an instance which uses a set of conventions:
+
+- _property placeholders_ - Keys and values using Camels property placeholder 
will be resolved.
+- _nested_ - Properties can be nested using the dot syntax (OGNL and builder 
pattern using with as prefix), eg `foo.bar=123`.
+- _map_ - Properties can lookup in Map's using map syntax, eg `foo[bar]` where 
foo is the name of the property that is a Map instance, and bar is the name of 
the key.
+- _list_ - Properties can refer or add to in List's using list syntax, eg 
`foo[0]` where foo is the name of the property that is a List instance, and 0 
is the index. To refer to the last element, then use `last` as key.
+- _reference by property placeholder id_ - Values can refer to a property 
placeholder key with `#property:myKey`
+- _reference by bean id_ - Values can refer to other beans in the registry by 
prefixing with `#` or `#bean:` eg `#myBean` or `#bean:myBean`. It is 
recommended to favour using `#bean:` syntax to make it obvious it's a bean 
reference.
+- _reference by type_ - Values can refer to singleton beans by their type in 
the registry by prefixing with `#type:` syntax, eg `#type:com.foo.MyClassType`.
+- _autowire by type_ - Values can refer to singleton beans by auto wiring by 
setting the value to `#autowired`.
+- _reference new class_ - Values can refer to creating new beans by their 
class name by prefixing with `#class`, eg `#class:com.foo.MyClassType`.
+       The class is created using a default no-arg constructor, however if you 
need to create 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)`.
+- _ignore case_ - Whether to ignore case for property keys (will ignore by 
default)
+
+== Property binding basics
+
+Do not get overwhelmed by the set of features and what they really do.
+
+At the basics the property binding are used for setting values on Java objects 
from string values (key=value).
+
+For example to set brokers on the Kafka component you can do:
+
+[source,properties]
+----
+camel.component.kafka.brokers = mykafka1,mykafka2
+----
+
+This will essentially be equivavlent to configuring Kafka component in regular 
Java code via setters:
+
+[source,java]
+----
+KafkaComponent kafka = ...
+kafka.setBrokers("mykafka1,mykafka2");
+----
+
+NOTE: For configuring Camel components in Java code, there is also 
xref:component-dsl.adoc[Component DSL].
+
+The configuration of Camel components, endpoints, routes etc can often require 
more flexibility and therefore
+the property binding has many features to bind by looking up existing objects 
by id, or anonymously by their type,
+and as well to walk down an object graph to bind nested parameters.
+
+== Using PropertyBindingSupport in Java
+
+Although `PropertyBindingSupport` is not primary intended for end users to 
use, but nevertheless its possible to use,
+and also you may get a better understanding of this feature by seeing how this 
class is used with pure Java.
+
+Suppose we have the following two POJOs `Foo.java` and `Bar.java`:
+
+[source,java]
+----
+public class Foo {
+    private String name;
+    private Bar bar = new Bar();
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Bar getBar() {
+        return bar;
+    }
+
+    public void setBar(Bar bar) {
+        this.bar = bar;
+    }
+}
+
+public class Bar {
+    private int age;
+    private boolean rider;
+
+    public int getAge() {
+        return age;
+    }
+
+    public boolean isRider() {
+        return rider;
+    }
+
+    // this has no setter but only builders and mix the builders with both 
styles
+
+    public Bar withAge(int age) {
+        this.age = age;
+        return this;
+    }
+
+    public Bar withRider(boolean rider) {
+        this.rider = rider;
+        return this;
+    }
+}
+----
+
+Then we can use `PropertyBindingSupport` to bind properties to these POJOs:
+
+[source,java]
+----
+Foo foo = new Foo();
+
+Map<String, Object> prop = new HashMap<>();
+prop.put("name", "James");
+prop.put("bar.age", "33");
+prop.put("bar.rider", "true");
+
+PropertyBindingSupport.bindProperties(context, foo, prop);
+----
+
+This will then set the POJOs to have the following values:
+
+----
+Foo.name = James
+Foo.Bar.age = 33
+Foo.Bar.rider = true
+----
+
+Instead of providing a map with all the parameters then a single parameter can 
also be set using builder style as shown:
+
+[source,java]
+----
+Foo foo = new Foo();
+
+PropertyBindingSupport.build().bind(context, foo, "name", "James");
+PropertyBindingSupport.build().bind(context, foo, "bar.age", "33");
+PropertyBindingSupport.build().bind(context, foo, "bar.rider", "true");
+----
+
+Which is more common to do as follows:
+
+[source,java]
+----
+Foo foo = new Foo();
+
+PropertyBindingSupport.build().withCamelContext(context).withTarget(foo)
+    .withProperty("name", "James");
+    .withProperty("bar.age", "33");
+    .withProperty("bar.rider", "true")
+    .bind();
+----
+
+In the example above then we are setting nested values on foo via `bar.age` 
and `bar.rider`. This is possible because
+Foo class has a `getBar` method that returns the `Bar` instance to use:
+
+[source,java]
+----
+    private Bar bar = new Bar();
+
+    public Bar getBar() {
+        return bar;
+    }
+----
+
+It's a common practice for POJO classes to not create nested instances, but 
instead on demand. So suppose
+`private Bar bar = new Bar();` was not present in the Foo class. In this 
situation then Camel will automatic
+create a new instance of `Bar` using its default no-arg constructor. For more 
advanced use-cases then you
+can specify how the Bar instance should be created, such as via a factory 
method, or pass in constructor parameters.
+
+For example suppose Bar has a constructor parameter that accepts a boolean, we 
can pass that information via `#class:` as shown:
+
+[source,java]
+----
+PropertyBindingSupport.build().withCamelContext(context).withTarget(foo)
+    .withProperty("name", "James");
+    .withProperty("bar", "#class:com.mycompany.Bar(true)")
+    .withProperty("bar.age", "33");
+    .withProperty("bar.rider", "true")
+    .bind();
+----
+
+== More details
+
+Property binding is noteably used when running Camel in standalone mode with 
Camel Main, or using Camel Spring Boot, Camel K,
+Camel Kafka Connector, or Camel Quarkus. All these runtimes have a similar way 
of configuring via property bindings such
+as from `application.properties` files.
+
+See more at xref:components:others:main.adoc[Camel Main]

Reply via email to