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 c1dc4f3be68e CAMEL-23806: Split and condense user manual docs
c1dc4f3be68e is described below
commit c1dc4f3be68e4cb8a60ea1495dbd3514fe9351e8
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Jun 20 19:21:04 2026 +0200
CAMEL-23806: Split and condense user manual docs
Split and condense overly long user manual documentation pages:
- Property Placeholders: Extract functions reference (vault syntax,
Kubernetes, custom functions) into a focused sub-page, reducing
using-propertyplaceholder.adoc from ~1,480 to ~747 lines
- Route Templates: Extract bean binding (advanced) section into a focused
sub-page, reducing route-template.adoc from ~1,390 to ~759 lines
- Security: Condense vault configuration sections by factoring out repeated
Java/XML/YAML tab blocks into a single "Vault Usage Syntax" reference with a
provider prefix table, reducing security.adoc by ~60% (~1,225 lines removed)
Co-Authored-By: Claude <[email protected]>
---
docs/user-manual/modules/ROOT/nav.adoc | 2 +
.../ROOT/pages/property-placeholder-functions.adoc | 743 ++++++++++
.../ROOT/pages/route-template-bean-binding.adoc | 641 ++++++++
.../modules/ROOT/pages/route-template.adoc | 639 +-------
docs/user-manual/modules/ROOT/pages/security.adoc | 1557 +++-----------------
.../ROOT/pages/using-propertyplaceholder.adoc | 741 +---------
6 files changed, 1560 insertions(+), 2763 deletions(-)
diff --git a/docs/user-manual/modules/ROOT/nav.adoc
b/docs/user-manual/modules/ROOT/nav.adoc
index 76239ecd48a6..b3d74e9d0d06 100644
--- a/docs/user-manual/modules/ROOT/nav.adoc
+++ b/docs/user-manual/modules/ROOT/nav.adoc
@@ -27,6 +27,7 @@
** xref:error-handler.adoc[Error handler]
** xref:error-registry.adoc[Error Registry]
** xref:using-propertyplaceholder.adoc[How to use Camel property placeholders]
+*** xref:property-placeholder-functions.adoc[Property Placeholder Functions]
** xref:variables.adoc[How to use Variables]
** xref:testing.adoc[Testing]
*** xref:test-infra.adoc[Test Infra]
@@ -97,6 +98,7 @@
** xref:route-reload.adoc[RouteReload]
** xref:route-diagram.adoc[Visual Route Diagrams]
** xref:route-template.adoc[RouteTemplate]
+*** xref:route-template-bean-binding.adoc[Bean Binding]
** xref:routes.adoc[Routes]
** xref:startup-condition.adoc[Startup Condition]
** xref:stream-caching.adoc[Stream caching]
diff --git
a/docs/user-manual/modules/ROOT/pages/property-placeholder-functions.adoc
b/docs/user-manual/modules/ROOT/pages/property-placeholder-functions.adoc
new file mode 100644
index 000000000000..14c4c05fe2d1
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/property-placeholder-functions.adoc
@@ -0,0 +1,743 @@
+= Property Placeholder Functions
+:tabs-sync-option:
+
+xref:using-propertyplaceholder.adoc[Back to Property Placeholders]
+
+The xref:components::properties-component.adoc[Properties] component includes
the following functions out of the box:
+
+* `env` - A function to lookup the property from OS environment variables
+* `sys` - A function to lookup the property from Java JVM system properties
+* `bean` - A function to lookup the property from the return value of bean's
method (requires `camel-bean` JAR)
+* `boolean` - A function to evaluate if a property key matches a condition and
returns either `true` or `false`
+* `service` - A function to lookup the property from OS environment variables
using the service naming idiom
+* `service.name` - A function to lookup the property from OS environment
variables using the service naming idiom returning the hostname part only
+* `service.port` - A function to lookup the property from OS environment
variables using the service naming idiom returning the port part only
+
+These functions are intended to make it easy to lookup values from the
environment, as shown in the example below:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .to("{{env:SOMENAME}}")
+ .to("{{sys:MyJvmPropertyName}}");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <to uri="{{env:SOMENAME}}"/>
+ <to uri="{{sys:MyJvmPropertyName}}"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - to:
+ uri: "{{env:SOMENAME}}"
+ - to:
+ uri: "{{sys:MyJvmPropertyName}}"
+----
+====
+
+You can use default values as well, so if the property does not exist, you can
define a default value as shown below, where the default value is a `log:foo`
and `log:bar` value.
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .to("{{env:SOMENAME:log:foo}}")
+ .to("{{sys:MyJvmPropertyName:log:bar}}");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <to uri="{{env:SOMENAME:log:foo}}"/>
+ <to uri="{{sys:MyJvmPropertyName:log:bar}}"/>
+</route>
+----
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - to:
+ uri: "{{env:SOMENAME:log:foo}}"
+ - to:
+ uri: "{{sys:MyJvmPropertyName:log:bar}}"
+----
+====
+
+The boolean function is intended for more flexibility when enabling or
disabling EIP options.
+
+For example given we have a property with key `region` that has the value
`EMEA`:
+
+[source,properties]
+----
+region = EMEA
+----
+
+We can then configure EIPs whether they are disabled based on this condition
as follows:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .choice().disabled("{{boolean:region == 'EMEA'}}")
+ .when(simple("${header.RetryAttempts} == null"))
+ .setProperty("HttpMessageMethod", constant("SET"))
+ .process("SetOriginalMessageProcessor")
+ .end();
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <choice disabled="{{boolean:region == 'EMEA'}}">
+ <when>
+ <simple>${header.RetryAttempts} == null</simple>
+ <setProperty name="HttpMessageMethod">
+ <constant>SET</constant>
+ </setProperty>
+ <process ref="SetOriginalMessageProcessor"/>
+ </when>
+ </choice>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - choice:
+ disabled: "{{boolean:region == 'EMEA'}}"
+ when:
+ - expression:
+ simple:
+ expression: "${header.RetryAttempts} == null"
+ steps:
+ - setProperty:
+ name: "HttpMessageMethod"
+ expression:
+ constant: "SET"
+ - process:
+ ref: "SetOriginalMessageProcessor"
+----
+====
+
+[NOTE]
+====
+Property placeholders can also be used in `application.properties` files, also
with the functions such as ENV as shown:
+
+[source,properties]
+----
+# server name read from ENV and fallback to use localhost as default value
+myserver = {{env:MY_SERVER_NAME:localhost}}
+----
+====
+
+TIP: The boolean function uses the
xref:components:languages:simple-language.adoc[Simple] language which has many
functions and operators to build the condition.
+
+The service function is for looking up a service which is defined using OS
environment variables using the service naming idiom, to refer to a service
location using `hostname : port`
+
+* __NAME__**_SERVICE_HOST**
+* __NAME__**_SERVICE_PORT**
+
+in other words the service uses `_SERVICE_HOST` and `_SERVICE_PORT` as prefix.
+So if the service is named FOO, then the OS environment variables should be
set as
+
+[source,bash]
+----
+export $FOO_SERVICE_HOST=myserver
+export $FOO_SERVICE_PORT=8888
+----
+
+For example if the FOO service a remote HTTP service, then we can refer to the
service in the Camel endpoint uri, and use the HTTP component to make the HTTP
call:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .to("http://{{service:FOO}}/myapp");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <to uri="http://{{service:FOO}}/myapp"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - to:
+ uri: "http://{{service:FOO}}/myapp"
+----
+====
+
+And we can use default values if the service has not been defined, for example
to call a service on localhost, maybe for unit testing.
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .to("http://{{service:FOO:localhost:8080}}/myapp");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <to uri="http://{{service:FOO:localhost:8080}}/myapp"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - to:
+ uri: "http://{{service:FOO:localhost:8080}}/myapp"
+----
+====
+
+The bean function (you need to have `camel-bean` JAR on classpath) is for
looking up the property from the return value of bean's method.
+
+Assuming we have registered a bean named 'foo' that has a method called 'bar'
that returns a directory name, then we can refer to the bean's method in the
camel endpoint url, and use the file component to poll a directory:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("file:{{bean:foo.bar}}")
+ .to("direct:result");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="file:{{bean:foo.bar}}"/>
+ <to uri="direct:result"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: file:{{bean:foo.bar}}
+ steps:
+ - to:
+ uri: "direct:result"
+----
+====
+
+IMPORTANT: The method must be a public no-arg method (i.e. no parameters) and
return a value such as a String, boolean, int.
+
+== Using Kubernetes property placeholder functions
+
+The `camel-kubernetes` component include the following functions:
+
+* `configmap` - A function to lookup the string property from Kubernetes
ConfigMaps.
+* `configmap-binary` - A function to lookup the binary property from
Kubernetes ConfigMaps.
+* `secret` - A function to lookup the string property from Kubernetes Secrets.
+* `secret-binary` - A function to lookup the binary property from Kubernetes
Secrets.
+
+The syntax for both functions are:
+
+[source,text]
+----
+configmap:name/key[:defaultValue]
+----
+
+Where the default value is optional, for example the following will lookup
`myKey`,
+and fail if there is no such configmap.
+
+[source,text]
+----
+configmap:mymap/mykey
+----
+
+In this example then it would not fail as a default value is provided:
+
+[source,text]
+----
+configmap:mymap/mykey:123
+----
+
+If the value stored in the configmap is in binary format, so it is stored as
`Binary Data`, it will be downloaded in a file, and it returns the absolute
path of the file
+
+[source,text]
+----
+configmap-binary:mymap/mybinkey
+----
+
+it returns a path like `/tmp/camel11787545916150467474/mybinkey`
+
+Before the Kubernetes property placeholder functions can be used they need to
be configured with either (or both)
+
+- path - A _mount path_ that must be mounted to the running pod, to load the
configmaps or secrets from local disk.
+- kubernetes client - *Autowired* An
`io.fabric8.kubernetes.client.KubernetesClient` instance to use for connecting
to the Kubernetes API server.
+
+Camel will first use _mount paths_ (if configured) to lookup, and then
fallback to use the `KubernetesClient`.
+
+=== Configuring mount paths for ConfigMaps and Secrets
+
+The configuration of the _mount path_ are used by the given order:
+
+1. Reading configuration property with keys
`camel.kubernetes-config.mount-path-configmaps` and
`camel.kubernetes-config.mount-path-secrets`.
+2. Use JVM system property with key `camel.k.mount-path.configmaps` and
`camel.k.mount-path.secrets` (Camel K compatible).
+3. Use OS ENV variable with key `CAMEL_K_MOUNT_PATH_CONFIGMAPS` and
`CAMEL_K_MOUNT_PATH_SECRETS` (Camel K compatible).
+
+For example to use `/etc/camel/resources/` as mount path, you can configure
this in the `application.properties`:
+
+[source,properties]
+----
+camel.kubernetes-config.mount-path-configmaps = /etc/camel/myconfig/
+camel.kubernetes-config.mount-path-secrets = /etc/camel/mysecrets/
+----
+
+=== Configuring Kubernetes Client
+
+Camel will autowire the `KubernetesClient` if a single instance of the client
exists in the running application (lookup via the xref:registry.adoc[Registry]).
+Otherwise, a new `KubernetesClient` is created. The client can be configured
from either
+
+- Using `camel.kubernetes-config.client.` properties (see below for example)
+- Attempt to auto-configure itself by a combination of OS Environment
variables, reading from `~./kube/config` configuration,
+and service account token file. For more details see the
https://github.com/fabric8io/kubernetes-client documentation.
+
+You most likely only need to explicit configure the `KubernetesClient` when
you want to connect
+from a local computer to a remote Kubernetes cluster, where you can specify
various options,
+such as the masterUrl and oauthToken as shown:
+
+[source,properties]
+----
+camel.kubernetes-config.client.masterUrl = https://127.0.0.1:50179/
+camel.kubernetes-config.client.oauthToken = eyJhbGciOiJSUzI1NiIsImtpZCI...
+----
+
+TIP: The `KubernetesClient` has many options, see the
https://github.com/fabric8io/kubernetes-client[Kubernetes Client] documentation
for more information for these options.
+
+If you only use _mount paths_, then it is good practice to disable
`KubernetesClient` which can be done by setting enabled to false as show:
+
+[source,properties]
+----
+camel.kubernetes-config.client-enabled = false
+----
+
+When running your Camel applications inside an existing Kubernetes cluster,
then you often
+would not need to explicit configure the `KubernetesClient` and can rely on
default settings.
+
+TIP: If you use Camel Quarkus, then it is recommended to use their
https://quarkus.io/guides/kubernetes-config
+which automatic pre-configure the `KubernetesClient` which Camel then will
reuse.
+
+=== Using configmap with Kubernetes
+
+Given a configmap named `myconfig` in Kubernetes that has two entries:
+
+[source,properties]
+----
+drink = beer
+first = Carlsberg
+----
+
+Then these values can be used in your Camel routes such as:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .log("What {{configmap:myconfig/drink}} do you want?")
+ .log("I want {{configmap:myconfig/first}}");
+----
+
+XML::
++
+[source,xml]
+----
+ <route>
+ <from uri="direct:start"/>
+ <log message="What {{configmap:myconfig/drink}} do you want?"/>
+ <log message="I want {{configmap:myconfig/first}}"/>
+ </route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - log:
+ message: "What {{configmap:myconfig/drink}} do you want?"
+ - log:
+ message: "I want {{configmap:myconfig/first}}"
+----
+====
+
+You can also provide a default value in case a key does not exist, such as
`Heiniken` being the default value:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .log("What {{configmap:myconfig/drink}} do you want?")
+ .log("I want {{configmap:myconfig/second:Heineken}}");
+----
+
+XML::
++
+[source,xml]
+----
+ <route>
+ <from uri="direct:start"/>
+ <log message="What {{configmap:myconfig/drink}} do you want?"/>
+ <log message="I want {{configmap:myconfig/second:Heineken}}"/>
+ </route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - log:
+ message: "What {{configmap:myconfig/drink}} do you want?"
+ - log:
+ message: "I want {{configmap:myconfig/second:Heineken}}"
+----
+====
+
+=== Using secrets with Kubernetes
+
+Camel reads ConfigMaps from the Kubernetes API Server. And when RBAC is
enabled on the cluster,
+the ServiceAccount that is used to run the application needs to have the
proper permissions for such access.
+
+A secret named `mydb` could contain username and passwords to connect to a
database such as:
+
+[source,properties]
+----
+myhost = killroy
+myport = 5555
+myuser = scott
+mypass = tiger
+----
+
+This can be used in Camel with for example the Postgres Sink Kamelet:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+String sink =
+"""
+ kamelet:postgresql-sink?serverName={{secret:mydb/myhost}}?
+ &serverPort={{secret:mydb/myport}}
+ &username={{secret:mydb/myuser}}
+ &password={{secret:mydb/mypass}}
+ &databaseName=cities
+ &query=INSERT INTO accounts (username,city) VALUES (:#username,:#city)
+""";
+
+from("direct:rome")
+ .setBody(constant("{ \"username\":\"oscerd\", \"city\":\"Rome\"}"))
+ .to(sink);
+----
+
+XML::
++
+[source,xml]
+----
+ <route>
+ <from uri="direct:rome"/>
+ <setBody>
+ <constant>{ "username":"oscerd", "city":"Rome"}</constant>
+ </setBody>
+ <to uri="kamelet:postgresql-sink?serverName={{secret:mydb/myhost}}
+ &serverPort={{secret:mydb/myport}}
+ &username={{secret:mydb/myuser}}
+ &password={{secret:mydb/mypass}}
+ &databaseName=cities
+ &query=INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"/>
+ </route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct
+ parameters:
+ name: rome
+ steps:
+ - setBody:
+ expression:
+ constant:
+ expression: "{ \"username\":\"oscerd\", \"city\":\"Rome\"}"
+ - to:
+ uri: kamelet
+ parameters:
+ templateId: postgresql-sink
+ serverName: "{{secret:mydb/myhost}}"
+ serverPort: "{{secret:mydb/myport}}"
+ username: "{{secret:mydb/myuser}}"
+ password: "{{secret:mydb/mypass}}"
+ databaseName: 'cities'
+ query: "INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"
+----
+====
+
+The postgres-sink Kamelet can also be configured in `application.properties`
which reduces the configuration
+in the route above:
+
+[source,properties]
+----
+camel.component.kamelet.postgresql-sink.databaseName={{secret:mydb/myhost}}
+camel.component.kamelet.postgresql-sink.serverPort={{secret:mydb/myport}}
+camel.component.kamelet.postgresql-sink.username={{secret:mydb/myuser}}
+camel.component.kamelet.postgresql-sink.password={{secret:mydb/mypass}}
+----
+
+Which reduces the route to:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:rome")
+ .setBody(constant("{ \"username\":\"oscerd\", \"city\":\"Rome\"}"))
+ .to("kamelet:postgresql-sink?databaseName=cities&query=INSERT INTO accounts
(username,city) VALUES (:#username,:#city)");
+----
+
+XML::
++
+[source,xml]
+----
+ <route>
+ <from uri="direct:rome"/>
+ <setBody>
+ <constant>{ "username":"oscerd", "city":"Rome"}</constant>
+ </setBody>
+ <to uri="kamelet:postgresql-sink?databaseName=cities
+ &query=INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"/>
+ </route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:rome
+ steps:
+ - setBody:
+ expression:
+ constant:
+ expression: "{ \"username\":\"oscerd\", \"city\":\"Rome\"}"
+ - to:
+ uri: kamelet
+ parameters:
+ templateId: postgresql-sink
+ databaseName: cities
+ query: "INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"
+----
+====
+
+=== Using configmap or secrets in local-mode
+
+During development, you may want to run in _local mode_ where you do not need
acces to a Kubernetes cluster, to lookup the configmap.
+In the local mode, then Camel will lookup the configmap _keys_ from local
properties, eg:
+
+For example the example above with the Postgres kamelet, that was configured
using a secret:
+
+[source,properties]
+----
+camel.component.kamelet.postgresql-sink.databaseName={{secret:mydb/myhost}}
+camel.component.kamelet.postgresql-sink.serverPort={{secret:mydb/myport}}
+camel.component.kamelet.postgresql-sink.username={{secret:mydb/myuser}}
+camel.component.kamelet.postgresql-sink.password={{secret:mydb/mypass}}
+----
+
+Now suppose we have a local Postgres database we want to use, then we can turn
on _local mode_
+and specify the credentials in the same properties file:
+
+[source,properties]
+----
+camel.kubernetes-config.local-mode = true
+mydb/myhost=localhost
+mydb/myport=1234
+mydb/myuser=scott
+mydb/mypass=tiger
+----
+
+NOTE: Notice how the key is prefixed with the name of the secret and a slash,
eg `name/key`. This makes it easy to copy/paste
+from the actual use of the configmap/secret and into the
`application.properties` file.
+
+
+== Using custom property placeholder functions
+
+The xref:components::properties-component.adoc[Properties] component allow to
plugin 3rd party functions which can be used during parsing of the property
placeholders.
+These functions are then able to do custom logic to resolve the placeholders,
such as looking up in databases, do custom computations, or whatnot.
+The name of the function becomes the prefix used in the placeholder.
+
+This is best illustrated in the example route below, where we use `beer` as
the prefix:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .to("{{beer:FOO}}")
+ .to("{{beer:BAR}}");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <to uri="{{beer:FOO}}"/>
+ <to uri="{{beer:BAR}}"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - to:
+ uri: "{{beer:FOO}}"
+ - to:
+ uri: "{{beer:BAR}}"
+----
+====
+
+The implementation of the function is only two methods as shown below:
+
+[source,java]
+----
[email protected]("beer")
+public class MyBeerFunction implements PropertiesFunction {
+
+ @Override
+ public String getName() {
+ return "beer";
+ }
+
+ @Override
+ public String apply(String remainder) {
+ return "mock:" + remainder.toLowerCase();
+ }
+}
+----
+
+The function must implement the `org.apache.camel.spi.PropertiesFunction`
interface.
+The method `getName` is the name of the function (beer).
+And the `apply` method is where we implement the custom logic to do.
+As the sample code is from a unit test, it just returns a value to refer to a
mock endpoint.
+
+You also need to have `camel-component-maven-plugin` Maven plugin as part of
building the component will
+then ensure that this custom properties function has necessary source code
generated that makes Camel
+able to automatically discover the function.
+
+NOTE: If the custom properties function need logic to startup and shutdown,
then the function can extend `ServiceSupport`
+and have this logic in `doStart` and `doStop` methods.
+
+TIP: For an example see the `camel-base64` component.
+
+
diff --git
a/docs/user-manual/modules/ROOT/pages/route-template-bean-binding.adoc
b/docs/user-manual/modules/ROOT/pages/route-template-bean-binding.adoc
new file mode 100644
index 000000000000..bee62f0330af
--- /dev/null
+++ b/docs/user-manual/modules/ROOT/pages/route-template-bean-binding.adoc
@@ -0,0 +1,641 @@
+= Route Template Bean Binding
+:tabs-sync-option:
+
+xref:route-template.adoc[Back to Route Templates]
+
+The route template allows binding beans that are locally scoped and only used
as part of creating routes from the template.
+This allows using the same template to create multiple routes, where beans are
local (private) for each created route.
+
+For example, given the following route template where we use `templateBean` to
set up the local bean as shown:
+
+._Java-only: templateBean with lambda supplier_
+[source,java]
+----
+routeTemplate("s3template")
+ .templateParameter("region")
+ .templateParameter("bucket")
+ .templateBean("myClient", S3Client.class, rtc ->
+ S3Client.builder().region(rtc.getProperty("region",
Region.class)).build();
+ )
+ .from("direct:s3-store")
+ // must refer to the bean with {{myClient}}
+ .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
+----
+
+The template has two parameters to specify the AWS region and the S3 bucket.
To connect to S3
+then a `software.amazon.awssdk.services.s3.S3Client` bean is necessary.
+
+To create this bean, we specify this with the `templateBean` DSL where we
specify the bean id as `myClient`.
+The type of the bean can be specified (`S3Client.class`), however, it is
optional, and
+can be used if you need to let beans be discovered by type and not by name.
+
+This ensures that the code creating the bean is executed later (when Camel is
creating a route from the template),
+then the code must be specified as a _supplier_. Because we want during
creation of the bean access to template parameters,
+we use a Camel `BeanSupplier` which gives access to `RouteTemplateContext`
that is the `_rtc_` variable in the code above.
+
+IMPORTANT: The local bean with id `myClient` *must* be referred to using
Camel's property placeholder syntax, eg `{\{myClient}}`
+in the route template, as shown above with the _to_ endpoint. This is because
the local
+bean must be made unique and Camel will internally re-assign the bean id to
use a unique id instead of `myClient`. And this is done with the help
+of the property placeholder functionality.
+
+If multiple routes are created from this template, then each of the created
routes have their own
+`S3Client` bean created.
+
+== Binding beans to route templates from template builder
+
+The `TemplatedRouteBuilder` also allows to bind local beans (which allows
specifying those beans) when
+creating routes from existing templates.
+
+Suppose the route template below is defined in XML:
+
+._XML-only: route template without bean binding_
+[source,xml]
+----
+ <routeTemplate id="s3template">
+ <templateParameter name="region"/>
+ <templateParameter name="bucket"/>
+ <route>
+ <from uri="direct:s3-store"/>
+ <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
+ </route>
+ </routeTemplate>
+----
+
+The template has no bean bindings for `#{\{myClient}}` which would be required
for creating the template.
+
+When creating routes form the template via `TemplatedRouteBuilder` then you
can provide the bean binding
+if you desire the bean to be locally scoped (not shared with others):
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+TemplatedRouteBuilder.builder(context, "s3template")
+ .parameter("region", "US-EAST-1")
+ .parameter("bucket", "myBucket")
+ .bean("myClient", S3Client.class,
+ S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build())
+ .routeId("mys3route")
+ .add();
+----
++
+As you can see the binding is similar to when using `templateBean` directly in
the route template.
+
+Java DSL::
++
+[source,java]
+----
+templatedRoute("s3template")
+ .parameter("region", "US-EAST-1")
+ .parameter("bucket", "myBucket")
+ .bean("myClient", S3Client.class,
+ rtc -> S3Client.builder() // <1>
+ .region(rtc.getProperty("region", Region.class))
+ .build())
+ .routeId("mys3route");
+----
+<1> Note that the third parameter of the `bean` method is not directly the
bean but rather a factory method that will be used to create the bean, here we
use a lambda expression as factory method.
+
+XML::
++
+[source,xml]
+----
+ <templatedRoute routeTemplateRef="s3template" routeId="mys3route">
+ <parameter name="region" value="US-EAST-1"/>
+ <parameter name="bucket" value="myBucket"/>
+ <bean name="myClient" type="software.amazon.awssdk.services.s3.S3Client"
+ scriptLanguage="groovy"> <!--1-->
+ <script>
+ import software.amazon.awssdk.services.s3.S3Client
+ S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build()
+ </script>
+ </bean>
+ </templatedRoute>
+----
+<1> For non-Java DSL, in case of a complex bean factory, you can still rely on
a language like `groovy` to define your bean factory inside a `script` element.
+
+YAML::
++
+[source,yaml]
+----
+- templatedRoute:
+ routeTemplateRef: "s3template"
+ routeId: "mys3route"
+ parameters:
+ - name: "region"
+ value: "US-EAST-1"
+ - name: "bucket"
+ value: "myBucket"
+ beans:
+ - name: "myClient"
+ type: "software.amazon.awssdk.services.s3.S3Client"
+ scriptLanguage: "groovy"
+ script: | # <1>
+ import software.amazon.awssdk.services.s3.S3Client
+ S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build()
+----
+<1> For non-Java DSL, in case of a complex bean factory, you can still rely on
a language like `groovy` to define your bean factory as value of the `script`
key.
+====
+
+Instead of binding the beans from the template builder, you could also create
the bean outside the template,
+and bind it by reference.
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+final S3Client myClient = S3Client.builder().region(Region.US_EAST_1).build();
+
+TemplatedRouteBuilder.builder(context, "s3template")
+ .parameter("region", Region.US_EAST_1)
+ .parameter("bucket", "myBucket")
+ .bean("myClient", myClient)
+ .routeId("mys3route")
+ .add();
+----
+
+Java DSL::
++
+[source,java]
+----
+final S3Client myClient = S3Client.builder().region(Region.US_EAST_1).build();
+
+templatedRoute("s3template")
+ .parameter("region", "US-EAST-1")
+ .parameter("bucket", "myBucket")
+ .bean("myClient", S3Client.class, rtc -> myClient)
+ .routeId("mys3route");
+----
+====
+
+NOTE: You should prefer to create the local beans directly from within the
template (if possible) because this
+ensures the route template has this out of the box. Otherwise, the bean must
be created or provided every time
+a new route is created from the route template. However, the latter gives
freedom to create the bean in any other custom way.
+
+
+== Binding beans to route templates using bean types
+
+You can create a local bean by referring to a fully qualified class name which
Camel will use to create
+a new local bean instance. When using this, the created bean is created via
default constructor of the class.
+
+The bean instance can be configured with properties via getter/setter style.
+The previous example with creating the AWS S3Client would not support this
kind as this uses _fluent builder_ pattern (not getter/setter).
+
+TIP: In *Camel 4.6* onwards, you can also use constructor arguments for beans
+
+So suppose we have a class as follows:
+
+._Java-only: bean class with getter/setter properties_
+[source,java]
+----
+public class MyBar {
+ private String name;
+ private String address;
+
+ // getter/setter omitted
+
+ public String location() {
+ return "The bar " + name + " is located at " + address;
+ }
+}
+----
+
+Then we can use the `MyBar` class as a local bean in a route template as
follows:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+routeTemplate("barTemplate")
+ .templateParameter("bar")
+ .templateParameter("street")
+ .templateBean("myBar")
+ .typeClass("com.foo.MyBar")
+ .property("name", "{{bar}}")
+ .property("address", "{{street}}")
+ .end()
+ .from("direct:going-out")
+ .to("bean:{{myBar}}");
+----
++
+With Java DSL, you can also refer to the bean class using type safe way in
`typeClass` by referring to the `.class` as follows:
++
+[source,java]
+----
+routeTemplate("barTemplate")
+ .templateParameter("bar")
+ .templateParameter("street")
+ .templateBean("myBar")
+ .typeClass(MyBar.class)
+ .property("name", "{{bar}}")
+ .property("address", "{{street}}")
+ .end()
+ .from("direct:going-out")
+ .to("bean:{{myBar}}");
+----
+
+XML::
++
+In XML, we specify the class FQN name using `#class:` syntax as shown:
++
+[source,xml]
+----
+<routeTemplate id="myBar">
+ <templateParameter name="bar"/>
+ <templateParameter name="street"/>
+ <templateBean name="myBean" type="#class:com.foo.MyBar">
+ <properties>
+ <property key="name" value="{{bar}}"/>
+ <property key="address" value="{{street}}"/>
+ </properties>
+ </templateBean>
+ <route>
+ <from uri="direct:going-out"/>
+ <to uri="bean:{{myBar}}"/>
+ </route>
+</routeTemplate>
+----
+
+YAML::
++
+In YAML, we specify the class FQN name using `#class:` syntax as shown:
++
+[source,yaml]
+----
+- routeTemplate:
+ id: "myBar"
+ parameters:
+ - name: "bar"
+ - name: "street"
+ beans:
+ - name: "myBean"
+ type: "#class:com.foo.MyBar"
+ properties:
+ name: "{{bar}}"
+ address: "{{street}}"
+ from:
+ uri: direct:going-out
+ steps:
+ - to:
+ uri: "bean:{{myBar}}"
+----
+====
+
+
+== Binding beans to route templates using scripting languages (advanced)
+
+You can use scripting languages like Groovy, Java, to create the bean.
+This allows defining route templates with the scripting language supported by
Camel such as Groovy.
+
+For example, creating the AWS S3 client can be done as shown in Java (with
inlined Groovy code):
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+routeTemplate("s3template")
+ .templateParameter("region")
+ .templateParameter("bucket")
+ .templateBean("myClient", "groovy",
+ "software.amazon.awssdk.services.s3.S3Client.S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build()"
+ )
+ .from("direct:s3-store")
+ // must refer to the bean with {{myClient}}
+ .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
+----
+
+XML::
++
+Notice how the Groovy code can be inlined directly in the route template in
XML also.
++
+[source,xml]
+----
+ <routeTemplate id="s3template">
+ <templateParameter name="region"/>
+ <templateParameter name="bucket"/>
+ <templateBean name="myClient" scriptLanguage="groovy">
+ <script>
+ import software.amazon.awssdk.services.s3.S3Client
+ S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build()
+ </script>
+ </templateBean>
+ <route>
+ <from uri="direct:s3-store"/>
+ <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
+ </route>
+ </routeTemplate>
+----
+
+YAML::
++
+Notice how the Groovy code can be inlined directly in the route template in
DSL also.
++
+[source,yaml]
+----
+- routeTemplate:
+ id: "s3template"
+ parameters:
+ - name: "region"
+ - name: "bucket"
+ beans:
+ - name: "myClient"
+ scriptLanguage: "groovy"
+ script: |
+ import software.amazon.awssdk.services.s3.S3Client
+ S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build()
+ from:
+ uri: direct:s3-store
+ steps:
+ - to:
+ uri: "aws2-s3:{{bucket}}"
+ parameters:
+ amazonS3Client: "#{{myClient}}"
+----
+====
+
+The groovy code can be externalized into a file on the classpath or file
system, by using `resource:` as prefix, such as:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+routeTemplate("s3template")
+ .templateParameter("region")
+ .templateParameter("bucket")
+ .templateBean("myClient", "groovy", "resource:classpath:s3bean.groovy")
+ .from("direct:s3-store")
+ // must refer to the bean with {{myClient}}
+ .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
+----
+
+XML::
++
+Notice how we can tell Camel the type of the bean is
`software.amazon.awssdk.services.s3.S3Client` which allows
+Camel to better understand, and also makes the bean able for autowiring and
binding via type. The `type` is optional
+and can be omitted. For example in this example as we inject the bean via its
bean id `myClient`.
++
+[source,xml]
+----
+ <routeTemplate id="s3template">
+ <templateParameter name="region"/>
+ <templateParameter name="bucket"/>
+ <templateBean name="myClient" scriptLanguage="groovy"
+ type="software.amazon.awssdk.services.s3.S3Client">
+ <script>resource:classpath:s3bean.groovy</script>
+ </templateBean>
+ <route>
+ <from uri="direct:s3-store"/>
+ <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
+ </route>
+ </routeTemplate>
+----
+
+YAML::
++
+Notice how we can tell Camel the type of the bean is
`software.amazon.awssdk.services.s3.S3Client` which allows
+Camel to better understand, and also makes the bean able for autowiring and
binding via type. The `type` is optional
+and can be omitted. For example in this example as we inject the bean via its
bean id `myClient`.
++
+[source,yaml]
+----
+- routeTemplate:
+ id: "s3template"
+ parameters:
+ - name: "region"
+ - name: "bucket"
+ beans:
+ - name: "myClient"
+ scriptLanguage: "groovy"
+ type: "software.amazon.awssdk.services.s3.S3Client"
+ script: "resource:classpath:s3bean.groovy"
+ from:
+ uri: direct:s3-store
+ steps:
+ - to:
+ uri: "aws2-s3:{{bucket}}"
+ parameters:
+ amazonS3Client: "#{{myClient}}"
+----
+====
+
+Then create the file `s3bean.groovy` in the classpath root:
+
+.s3bean.groovy
+[source,groovy]
+----
+import software.amazon.awssdk.services.s3.S3Client
+
+S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build()
+----
+
+The languages supported you can specify as `scriptLanguage` are:
+
+[width="100%",cols="2s,8",options="header"]
+|===
+| Type | Description
+| bean | Calling a method on a Java class to create the bean.
+| groovy | Using a groovy script to create the bean.
+| java | Java code which is runtime compiled (using jOOR library) to create
the bean.
+| mvel | To use a MVEL template script to create the bean.
+| ognl | To use OGNL template script to create the bean.
+| _name_ | To use a third-party language by the given `_name_` to create the
bean.
+|===
+
+Camel will bind `RouteTemplateContext` as the root object with name `rtc` when
evaluating the script.
+This means you can get access to all the information from
`RouteTemplateContext` and `CamelContext` via `rtc`.
+
+This is what we have done in the scripts in the previous examples where we get
hold of a template parameter with:
+
+[source,groovy]
+----
+rtc.getProperty('region', String.class)
+----
+
+To get access to `CamelContext` you can do:
+
+[source,groovy]
+----
+var cn = rtc.getCamelContext().getName()
+----
+
+The most powerful languages to use are groovy and java. The other languages
are limited in flexibility
+as they are not complete programming languages, but are more suited for
templating needs.
+
+It is recommended to either use groovy or java, if creating the local bean
requires coding,
+and the route templates are not defined using Java code.
+
+The bean language can be used when creating the local bean from an existing
Java method (static or not-static method),
+and the route templates are not defined using Java code.
+
+For example suppose there is a class named `com.foo.MyAwsHelper` that has a
method called `createS3Client`
+then you can call this method from the route template as shown in the
following:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+routeTemplate("s3template")
+ .templateParameter("region")
+ .templateParameter("bucket")
+ .templateBean("myClient", "beam",
"com.foo.MyAwsHelper?method=createS3Client")
+ .from("direct:s3-store")
+ // must refer to the bean with {{myClient}}
+ .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
+----
+
+XML::
++
+[source,xml]
+----
+ <routeTemplate id="s3template">
+ <templateParameter name="region"/>
+ <templateParameter name="bucket"/>
+ <templateBean name="myClient" type="bean">
+ <script>com.foo.MyAwsHelper?method=createS3Client</script>
+ </templateBean>
+ <route>
+ <from uri="direct:s3-store"/>
+ <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
+ </route>
+ </routeTemplate>
+----
+
+YAML::
++
+[source,yaml]
+----
+- routeTemplate:
+ id: "s3template"
+ parameters:
+ - name: "region"
+ - name: "bucket"
+ beans:
+ - name: "myClient"
+ scriptLanguage: "bean"
+ script: "com.foo.MyAwsHelper?method=createS3Client"
+ from:
+ uri: direct:s3-store
+ steps:
+ - to:
+ uri: "aws2-s3:{{bucket}}"
+ parameters:
+ amazonS3Client: "#{{myClient}}"
+----
+====
+
+The method signature of `createS3Client` method **MUST** then have one
parameter for the `RouteTemplateContext` as shown:
+
+._Java-only: bean factory method signature_
+[source,java]
+----
+public static S3Client createS3Client(RouteTemplateContext rtc) {
+ return S3Client.builder()
+ .region(rtc.getProperty("region", Region.class))
+ .build();
+}
+----
+
+If you are using pure Java code (both template and creating local bean),
+then you can create the local bean using Java lambda style as previously
documented.
+
+
+== Configuring the type of the created bean
+
+The `type` must be set to define what FQN class the created bean.
+
+In the following route template we want to tell Camel that the bean is a
`software.amazon.awssdk.services.s3.S3Client` type.
+
+
+[tabs]
+====
+
+Java::
++
+In Java DSL you can refer to the type via its class (ie `S3Client.java` which
is a type safe way:
++
+[source,java]
+----
+routeTemplate("s3template")
+ .templateParameter("region")
+ .templateParameter("bucket")
+ .templateBean("myClient", S3Client.class, "bean",
"com.foo.MyAwsHelper?method=createS3Client")
+ .from("direct:s3-store")
+ // must refer to the bean with {{myClient}}
+ .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
+----
+
+XML::
++
+[source,xml]
+----
+ <routeTemplate id="s3template">
+ <templateParameter name="region"/>
+ <templateParameter name="bucket"/>
+ <templateBean name="myClient" scriptLanguage="bean"
+ type="software.amazon.awssdk.services.s3.S3Client">
+ <script>com.foo.MyAwsHelper?method=createS3Client</script>
+ </templateBean>
+ <route>
+ <from uri="direct:s3-store"/>
+ <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
+ </route>
+ </routeTemplate>
+----
+
+YAML::
++
+[source,yaml]
+----
+- routeTemplate:
+ id: "s3template"
+ parameters:
+ - name: "region"
+ - name: "bucket"
+ beans:
+ - name: "myClient"
+ scriptLanguage: "bean"
+ type: "software.amazon.awssdk.services.s3.S3Client"
+ script: "com.foo.MyAwsHelper?method=createS3Client"
+ from:
+ uri: direct:s3-store
+ steps:
+ - to:
+ uri: "aws2-s3:{{bucket}}"
+ parameters:
+ amazonS3Client: "#{{myClient}}"
+----
+====
+
+
diff --git a/docs/user-manual/modules/ROOT/pages/route-template.adoc
b/docs/user-manual/modules/ROOT/pages/route-template.adoc
index 8a6434324929..e06ab30d8d51 100644
--- a/docs/user-manual/modules/ROOT/pages/route-template.adoc
+++ b/docs/user-manual/modules/ROOT/pages/route-template.adoc
@@ -643,643 +643,12 @@ Then we can create a 2nd route with a different
_prefixId`:
----
====
-== Binding beans to route template (advanced)
+== Binding Beans to Route Templates
-The route template allows binding beans that are locally scoped and only used
as part of creating routes from the template.
-This allows using the same template to create multiple routes, where beans are
local (private) for each created route.
-
-For example, given the following route template where we use `templateBean` to
set up the local bean as shown:
-
-._Java-only: templateBean with lambda supplier_
-[source,java]
-----
-routeTemplate("s3template")
- .templateParameter("region")
- .templateParameter("bucket")
- .templateBean("myClient", S3Client.class, rtc ->
- S3Client.builder().region(rtc.getProperty("region",
Region.class)).build();
- )
- .from("direct:s3-store")
- // must refer to the bean with {{myClient}}
- .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
-----
-
-The template has two parameters to specify the AWS region and the S3 bucket.
To connect to S3
-then a `software.amazon.awssdk.services.s3.S3Client` bean is necessary.
-
-To create this bean, we specify this with the `templateBean` DSL where we
specify the bean id as `myClient`.
-The type of the bean can be specified (`S3Client.class`), however, it is
optional, and
-can be used if you need to let beans be discovered by type and not by name.
-
-This ensures that the code creating the bean is executed later (when Camel is
creating a route from the template),
-then the code must be specified as a _supplier_. Because we want during
creation of the bean access to template parameters,
-we use a Camel `BeanSupplier` which gives access to `RouteTemplateContext`
that is the `_rtc_` variable in the code above.
-
-IMPORTANT: The local bean with id `myClient` *must* be referred to using
Camel's property placeholder syntax, eg `{\{myClient}}`
-in the route template, as shown above with the _to_ endpoint. This is because
the local
-bean must be made unique and Camel will internally re-assign the bean id to
use a unique id instead of `myClient`. And this is done with the help
-of the property placeholder functionality.
-
-If multiple routes are created from this template, then each of the created
routes have their own
-`S3Client` bean created.
-
-=== Binding beans to route templates from template builder
-
-The `TemplatedRouteBuilder` also allows to bind local beans (which allows
specifying those beans) when
-creating routes from existing templates.
-
-Suppose the route template below is defined in XML:
-
-._XML-only: route template without bean binding_
-[source,xml]
-----
- <routeTemplate id="s3template">
- <templateParameter name="region"/>
- <templateParameter name="bucket"/>
- <route>
- <from uri="direct:s3-store"/>
- <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
- </route>
- </routeTemplate>
-----
-
-The template has no bean bindings for `#{\{myClient}}` which would be required
for creating the template.
-
-When creating routes form the template via `TemplatedRouteBuilder` then you
can provide the bean binding
-if you desire the bean to be locally scoped (not shared with others):
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-TemplatedRouteBuilder.builder(context, "s3template")
- .parameter("region", "US-EAST-1")
- .parameter("bucket", "myBucket")
- .bean("myClient", S3Client.class,
- S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build())
- .routeId("mys3route")
- .add();
-----
-+
-As you can see the binding is similar to when using `templateBean` directly in
the route template.
-
-Java DSL::
-+
-[source,java]
-----
-templatedRoute("s3template")
- .parameter("region", "US-EAST-1")
- .parameter("bucket", "myBucket")
- .bean("myClient", S3Client.class,
- rtc -> S3Client.builder() // <1>
- .region(rtc.getProperty("region", Region.class))
- .build())
- .routeId("mys3route");
-----
-<1> Note that the third parameter of the `bean` method is not directly the
bean but rather a factory method that will be used to create the bean, here we
use a lambda expression as factory method.
-
-XML::
-+
-[source,xml]
-----
- <templatedRoute routeTemplateRef="s3template" routeId="mys3route">
- <parameter name="region" value="US-EAST-1"/>
- <parameter name="bucket" value="myBucket"/>
- <bean name="myClient" type="software.amazon.awssdk.services.s3.S3Client"
- scriptLanguage="groovy"> <!--1-->
- <script>
- import software.amazon.awssdk.services.s3.S3Client
- S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build()
- </script>
- </bean>
- </templatedRoute>
-----
-<1> For non-Java DSL, in case of a complex bean factory, you can still rely on
a language like `groovy` to define your bean factory inside a `script` element.
-
-YAML::
-+
-[source,yaml]
-----
-- templatedRoute:
- routeTemplateRef: "s3template"
- routeId: "mys3route"
- parameters:
- - name: "region"
- value: "US-EAST-1"
- - name: "bucket"
- value: "myBucket"
- beans:
- - name: "myClient"
- type: "software.amazon.awssdk.services.s3.S3Client"
- scriptLanguage: "groovy"
- script: | # <1>
- import software.amazon.awssdk.services.s3.S3Client
- S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build()
-----
-<1> For non-Java DSL, in case of a complex bean factory, you can still rely on
a language like `groovy` to define your bean factory as value of the `script`
key.
-====
-
-Instead of binding the beans from the template builder, you could also create
the bean outside the template,
-and bind it by reference.
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-final S3Client myClient = S3Client.builder().region(Region.US_EAST_1).build();
-
-TemplatedRouteBuilder.builder(context, "s3template")
- .parameter("region", Region.US_EAST_1)
- .parameter("bucket", "myBucket")
- .bean("myClient", myClient)
- .routeId("mys3route")
- .add();
-----
-
-Java DSL::
-+
-[source,java]
-----
-final S3Client myClient = S3Client.builder().region(Region.US_EAST_1).build();
-
-templatedRoute("s3template")
- .parameter("region", "US-EAST-1")
- .parameter("bucket", "myBucket")
- .bean("myClient", S3Client.class, rtc -> myClient)
- .routeId("mys3route");
-----
-====
-
-NOTE: You should prefer to create the local beans directly from within the
template (if possible) because this
-ensures the route template has this out of the box. Otherwise, the bean must
be created or provided every time
-a new route is created from the route template. However, the latter gives
freedom to create the bean in any other custom way.
-
-
-=== Binding beans to route templates using bean types
-
-You can create a local bean by referring to a fully qualified class name which
Camel will use to create
-a new local bean instance. When using this, the created bean is created via
default constructor of the class.
-
-The bean instance can be configured with properties via getter/setter style.
-The previous example with creating the AWS S3Client would not support this
kind as this uses _fluent builder_ pattern (not getter/setter).
-
-TIP: In *Camel 4.6* onwards, you can also use constructor arguments for beans
-
-So suppose we have a class as follows:
-
-._Java-only: bean class with getter/setter properties_
-[source,java]
-----
-public class MyBar {
- private String name;
- private String address;
-
- // getter/setter omitted
-
- public String location() {
- return "The bar " + name + " is located at " + address;
- }
-}
-----
-
-Then we can use the `MyBar` class as a local bean in a route template as
follows:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-routeTemplate("barTemplate")
- .templateParameter("bar")
- .templateParameter("street")
- .templateBean("myBar")
- .typeClass("com.foo.MyBar")
- .property("name", "{{bar}}")
- .property("address", "{{street}}")
- .end()
- .from("direct:going-out")
- .to("bean:{{myBar}}");
-----
-+
-With Java DSL, you can also refer to the bean class using type safe way in
`typeClass` by referring to the `.class` as follows:
-+
-[source,java]
-----
-routeTemplate("barTemplate")
- .templateParameter("bar")
- .templateParameter("street")
- .templateBean("myBar")
- .typeClass(MyBar.class)
- .property("name", "{{bar}}")
- .property("address", "{{street}}")
- .end()
- .from("direct:going-out")
- .to("bean:{{myBar}}");
-----
-
-XML::
-+
-In XML, we specify the class FQN name using `#class:` syntax as shown:
-+
-[source,xml]
-----
-<routeTemplate id="myBar">
- <templateParameter name="bar"/>
- <templateParameter name="street"/>
- <templateBean name="myBean" type="#class:com.foo.MyBar">
- <properties>
- <property key="name" value="{{bar}}"/>
- <property key="address" value="{{street}}"/>
- </properties>
- </templateBean>
- <route>
- <from uri="direct:going-out"/>
- <to uri="bean:{{myBar}}"/>
- </route>
-</routeTemplate>
-----
-
-YAML::
-+
-In YAML, we specify the class FQN name using `#class:` syntax as shown:
-+
-[source,yaml]
-----
-- routeTemplate:
- id: "myBar"
- parameters:
- - name: "bar"
- - name: "street"
- beans:
- - name: "myBean"
- type: "#class:com.foo.MyBar"
- properties:
- name: "{{bar}}"
- address: "{{street}}"
- from:
- uri: direct:going-out
- steps:
- - to:
- uri: "bean:{{myBar}}"
-----
-====
-
-
-=== Binding beans to route templates using scripting languages (advanced)
-
-You can use scripting languages like Groovy, Java, to create the bean.
-This allows defining route templates with the scripting language supported by
Camel such as Groovy.
-
-For example, creating the AWS S3 client can be done as shown in Java (with
inlined Groovy code):
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-routeTemplate("s3template")
- .templateParameter("region")
- .templateParameter("bucket")
- .templateBean("myClient", "groovy",
- "software.amazon.awssdk.services.s3.S3Client.S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build()"
- )
- .from("direct:s3-store")
- // must refer to the bean with {{myClient}}
- .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
-----
-
-XML::
-+
-Notice how the Groovy code can be inlined directly in the route template in
XML also.
-+
-[source,xml]
-----
- <routeTemplate id="s3template">
- <templateParameter name="region"/>
- <templateParameter name="bucket"/>
- <templateBean name="myClient" scriptLanguage="groovy">
- <script>
- import software.amazon.awssdk.services.s3.S3Client
- S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build()
- </script>
- </templateBean>
- <route>
- <from uri="direct:s3-store"/>
- <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
- </route>
- </routeTemplate>
-----
-
-YAML::
-+
-Notice how the Groovy code can be inlined directly in the route template in
DSL also.
-+
-[source,yaml]
-----
-- routeTemplate:
- id: "s3template"
- parameters:
- - name: "region"
- - name: "bucket"
- beans:
- - name: "myClient"
- scriptLanguage: "groovy"
- script: |
- import software.amazon.awssdk.services.s3.S3Client
- S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build()
- from:
- uri: direct:s3-store
- steps:
- - to:
- uri: "aws2-s3:{{bucket}}"
- parameters:
- amazonS3Client: "#{{myClient}}"
-----
-====
-
-The groovy code can be externalized into a file on the classpath or file
system, by using `resource:` as prefix, such as:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-routeTemplate("s3template")
- .templateParameter("region")
- .templateParameter("bucket")
- .templateBean("myClient", "groovy", "resource:classpath:s3bean.groovy")
- .from("direct:s3-store")
- // must refer to the bean with {{myClient}}
- .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
-----
-
-XML::
-+
-Notice how we can tell Camel the type of the bean is
`software.amazon.awssdk.services.s3.S3Client` which allows
-Camel to better understand, and also makes the bean able for autowiring and
binding via type. The `type` is optional
-and can be omitted. For example in this example as we inject the bean via its
bean id `myClient`.
-+
-[source,xml]
-----
- <routeTemplate id="s3template">
- <templateParameter name="region"/>
- <templateParameter name="bucket"/>
- <templateBean name="myClient" scriptLanguage="groovy"
- type="software.amazon.awssdk.services.s3.S3Client">
- <script>resource:classpath:s3bean.groovy</script>
- </templateBean>
- <route>
- <from uri="direct:s3-store"/>
- <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
- </route>
- </routeTemplate>
-----
-
-YAML::
-+
-Notice how we can tell Camel the type of the bean is
`software.amazon.awssdk.services.s3.S3Client` which allows
-Camel to better understand, and also makes the bean able for autowiring and
binding via type. The `type` is optional
-and can be omitted. For example in this example as we inject the bean via its
bean id `myClient`.
-+
-[source,yaml]
-----
-- routeTemplate:
- id: "s3template"
- parameters:
- - name: "region"
- - name: "bucket"
- beans:
- - name: "myClient"
- scriptLanguage: "groovy"
- type: "software.amazon.awssdk.services.s3.S3Client"
- script: "resource:classpath:s3bean.groovy"
- from:
- uri: direct:s3-store
- steps:
- - to:
- uri: "aws2-s3:{{bucket}}"
- parameters:
- amazonS3Client: "#{{myClient}}"
-----
-====
-
-Then create the file `s3bean.groovy` in the classpath root:
-
-.s3bean.groovy
-[source,groovy]
-----
-import software.amazon.awssdk.services.s3.S3Client
-
-S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build()
-----
-
-The languages supported you can specify as `scriptLanguage` are:
-
-[width="100%",cols="2s,8",options="header"]
-|===
-| Type | Description
-| bean | Calling a method on a Java class to create the bean.
-| groovy | Using a groovy script to create the bean.
-| java | Java code which is runtime compiled (using jOOR library) to create
the bean.
-| mvel | To use a MVEL template script to create the bean.
-| ognl | To use OGNL template script to create the bean.
-| _name_ | To use a third-party language by the given `_name_` to create the
bean.
-|===
-
-Camel will bind `RouteTemplateContext` as the root object with name `rtc` when
evaluating the script.
-This means you can get access to all the information from
`RouteTemplateContext` and `CamelContext` via `rtc`.
-
-This is what we have done in the scripts in the previous examples where we get
hold of a template parameter with:
-
-[source,groovy]
-----
-rtc.getProperty('region', String.class)
-----
-
-To get access to `CamelContext` you can do:
-
-[source,groovy]
-----
-var cn = rtc.getCamelContext().getName()
-----
-
-The most powerful languages to use are groovy and java. The other languages
are limited in flexibility
-as they are not complete programming languages, but are more suited for
templating needs.
-
-It is recommended to either use groovy or java, if creating the local bean
requires coding,
-and the route templates are not defined using Java code.
-
-The bean language can be used when creating the local bean from an existing
Java method (static or not-static method),
-and the route templates are not defined using Java code.
-
-For example suppose there is a class named `com.foo.MyAwsHelper` that has a
method called `createS3Client`
-then you can call this method from the route template as shown in the
following:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-routeTemplate("s3template")
- .templateParameter("region")
- .templateParameter("bucket")
- .templateBean("myClient", "beam",
"com.foo.MyAwsHelper?method=createS3Client")
- .from("direct:s3-store")
- // must refer to the bean with {{myClient}}
- .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
-----
-
-XML::
-+
-[source,xml]
-----
- <routeTemplate id="s3template">
- <templateParameter name="region"/>
- <templateParameter name="bucket"/>
- <templateBean name="myClient" type="bean">
- <script>com.foo.MyAwsHelper?method=createS3Client</script>
- </templateBean>
- <route>
- <from uri="direct:s3-store"/>
- <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
- </route>
- </routeTemplate>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- routeTemplate:
- id: "s3template"
- parameters:
- - name: "region"
- - name: "bucket"
- beans:
- - name: "myClient"
- scriptLanguage: "bean"
- script: "com.foo.MyAwsHelper?method=createS3Client"
- from:
- uri: direct:s3-store
- steps:
- - to:
- uri: "aws2-s3:{{bucket}}"
- parameters:
- amazonS3Client: "#{{myClient}}"
-----
-====
-
-The method signature of `createS3Client` method **MUST** then have one
parameter for the `RouteTemplateContext` as shown:
-
-._Java-only: bean factory method signature_
-[source,java]
-----
-public static S3Client createS3Client(RouteTemplateContext rtc) {
- return S3Client.builder()
- .region(rtc.getProperty("region", Region.class))
- .build();
-}
-----
-
-If you are using pure Java code (both template and creating local bean),
-then you can create the local bean using Java lambda style as previously
documented.
-
-
-==== Configuring the type of the created bean
-
-The `type` must be set to define what FQN class the created bean.
-
-In the following route template we want to tell Camel that the bean is a
`software.amazon.awssdk.services.s3.S3Client` type.
-
-
-[tabs]
-====
-
-Java::
-+
-In Java DSL you can refer to the type via its class (ie `S3Client.java` which
is a type safe way:
-+
-[source,java]
-----
-routeTemplate("s3template")
- .templateParameter("region")
- .templateParameter("bucket")
- .templateBean("myClient", S3Client.class, "bean",
"com.foo.MyAwsHelper?method=createS3Client")
- .from("direct:s3-store")
- // must refer to the bean with {{myClient}}
- .to("aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}")
-----
-
-XML::
-+
-[source,xml]
-----
- <routeTemplate id="s3template">
- <templateParameter name="region"/>
- <templateParameter name="bucket"/>
- <templateBean name="myClient" scriptLanguage="bean"
- type="software.amazon.awssdk.services.s3.S3Client">
- <script>com.foo.MyAwsHelper?method=createS3Client</script>
- </templateBean>
- <route>
- <from uri="direct:s3-store"/>
- <to uri="aws2-s3:{{bucket}}?amazonS3Client=#{{myClient}}"/>
- </route>
- </routeTemplate>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- routeTemplate:
- id: "s3template"
- parameters:
- - name: "region"
- - name: "bucket"
- beans:
- - name: "myClient"
- scriptLanguage: "bean"
- type: "software.amazon.awssdk.services.s3.S3Client"
- script: "com.foo.MyAwsHelper?method=createS3Client"
- from:
- uri: direct:s3-store
- steps:
- - to:
- uri: "aws2-s3:{{bucket}}"
- parameters:
- amazonS3Client: "#{{myClient}}"
-----
-====
+Route templates support binding locally-scoped beans that are private to each
route created from the template.
+This is an advanced feature.
+See xref:route-template-bean-binding.adoc[Route Template Bean Binding] for
details.
== Configuring route templates when creating route (advanced)
diff --git a/docs/user-manual/modules/ROOT/pages/security.adoc
b/docs/user-manual/modules/ROOT/pages/security.adoc
index da6512831e5c..9ea97369884c 100644
--- a/docs/user-manual/modules/ROOT/pages/security.adoc
+++ b/docs/user-manual/modules/ROOT/pages/security.adoc
@@ -100,62 +100,50 @@ The following _Vaults_ are supported by Camel:
* xref:components::hashicorp-vault-component.adoc[Hashicorp Vault]
* xref:components::ibm-secrets-manager-component.adoc[IBM Secrets Manager]
-==== Using AWS Vault
-
-To use AWS Secrets Manager, you need to provide _accessKey_, _secretKey_ and
the _region_.
-This can be done using environmental variables before starting the application:
-
-[source,bash]
-----
-export $CAMEL_VAULT_AWS_ACCESS_KEY=accessKey
-export $CAMEL_VAULT_AWS_SECRET_KEY=secretKey
-export $CAMEL_VAULT_AWS_REGION=region
-----
-
-You can also configure the credentials in the `application.properties` file
such as:
-
-[source,properties]
-----
-camel.vault.aws.accessKey = accessKey
-camel.vault.aws.secretKey = secretKey
-camel.vault.aws.region = region
-----
-
-If you want instead to use the
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html[AWS
default credentials provider], you'll need to provide the following env
variables:
-
-[source,bash]
-----
-export $CAMEL_VAULT_AWS_USE_DEFAULT_CREDENTIALS_PROVIDER=true
-export $CAMEL_VAULT_AWS_REGION=region
-----
+==== Vault Usage Syntax
-You can also configure the credentials in the `application.properties` file
such as:
+All vault providers use the same property placeholder syntax. The prefix
identifies which vault to use:
-[source,properties]
-----
-camel.vault.aws.defaultCredentialsProvider = true
-camel.vault.aws.region = region
-----
+[width="100%",cols="2,1,3",options="header"]
+|===
+| Provider | Prefix | Required JAR
+| AWS Secrets Manager | `aws:` | `camel-aws-secrets-manager`
+| Google Secret Manager | `gcp:` | `camel-google-secret-manager`
+| Azure Key Vault | `azure:` | `camel-azure-key-vault`
+| Hashicorp Vault | `hashicorp:` | `camel-hashicorp-vault`
+| IBM Secrets Manager | `ibm:` | `camel-ibm-secrets-manager`
+| CyberArk Conjur | `cyberark:` | `camel-cyberark-vault`
+|===
-It is also possible to specify a particular profile name for accessing AWS
Secrets Manager
+The following syntax forms are supported (replace `<prefix>` with the provider
prefix from the table above):
-[source,bash]
+[source,text]
----
-export $CAMEL_VAULT_AWS_USE_PROFILE_CREDENTIALS_PROVIDER=true
-export $CAMEL_VAULT_AWS_PROFILE_NAME=test-account
-export $CAMEL_VAULT_AWS_REGION=region
+{{<prefix>:secretName}} <1>
+{{<prefix>:secretName:defaultValue}} <2>
+{{<prefix>:secretName#fieldName}} <3>
+{{<prefix>:secretName#fieldName:defaultValue}} <4>
----
+<1> Lookup the secret value. Fails if the secret does not exist.
+<2> Lookup the secret value, falling back to `defaultValue` if the secret does
not exist.
+<3> Lookup a specific field from a JSON-structured secret.
+<4> Lookup a specific field, with a fallback default value.
-You can also configure the credentials in the `application.properties` file
such as:
+For example, if you have a JSON secret named `database`:
-[source,properties]
+[source,json]
----
-camel.vault.aws.profileCredentialsProvider = true
-camel.vault.aws.profileName = test-account
-camel.vault.aws.region = region
+{
+ "username": "admin",
+ "password": "password123",
+ "engine": "postgres",
+ "host": "127.0.0.1",
+ "port": "3128",
+ "dbname": "db"
+}
----
-At this point you'll be able to reference a property in the following way by
using `aws:` as prefix in the `{{ }}` syntax:
+You can access individual fields using the `#` syntax:
[tabs]
====
@@ -165,7 +153,8 @@ Java::
[source,java]
----
from("direct:start")
- .to("{{aws:route}}");
+ .log("Username is {{aws:database#username}}")
+ .log("Password is {{aws:database#password:secret}}");
----
XML::
@@ -174,7 +163,8 @@ XML::
----
<route>
<from uri="direct:start"/>
- <to uri="{{aws:route}}"/>
+ <log message="Username is {{aws:database#username}}"/>
+ <log message="Password is {{aws:database#password:secret}}"/>
</route>
----
@@ -186,143 +176,90 @@ YAML::
from:
uri: direct:start
steps:
- - to:
- uri: "{{aws:route}}"
+ - log:
+ message: "Username is {{aws:database#username}}"
+ - log:
+ message: "Password is {{aws:database#password:secret}}"
----
====
-Where `route` will be the name of the secret stored in the AWS Secrets Manager
Service.
-
-You could specify a default value (`aws:key:default-value`) in case the secret
is not present on AWS Secret Manager:
+The examples above use the `aws:` prefix but the same syntax works with any
provider prefix (`gcp:`, `azure:`, `hashicorp:`, `ibm:`, `cyberark:`).
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{aws:route:myDefault}}");
-----
+===== Version Syntax
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{aws:route:myDefault}}"/>
-</route>
-----
+Hashicorp Vault, IBM Secrets Manager, and CyberArk Conjur support retrieving a
specific version of a secret using the `@` suffix:
-YAML::
-+
-[source,yaml]
+[source,text]
----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{aws:route:myDefault}}"
+{{hashicorp:secret:route@2}} <1>
+{{hashicorp:route:defaultValue@2}} <2>
+{{hashicorp:secret:database#username:admin@2}} <3>
+{{ibm:default:route@2}} <4>
+{{cyberark:route@2}} <5>
----
-====
+<1> Hashicorp: get secret `route` at version 2 from the `secret` engine.
+<2> Hashicorp: get secret `route` at version 2, with default fallback.
+<3> Hashicorp: get field `username` from secret `database` at version 2.
+<4> IBM: get secret `route` at version 2 from the `default` secret group.
+<5> CyberArk: get secret `route` at version 2.
-In this case, if the secret doesn't exist, the property will fallback to
"myDefault" as value.
+==== Using AWS Vault
-Also, you are able to get a particular field of the secret, if you have, for
example, a secret named database of this form:
+To use AWS Secrets Manager, you need to provide _accessKey_, _secretKey_ and
the _region_.
+This can be done using environmental variables before starting the application:
-[source,json]
+[source,bash]
----
-{
- "username": "admin",
- "password": "password123",
- "engine": "postgres",
- "host": "127.0.0.1",
- "port": "3128",
- "dbname": "db"
-}
+export $CAMEL_VAULT_AWS_ACCESS_KEY=accessKey
+export $CAMEL_VAULT_AWS_SECRET_KEY=secretKey
+export $CAMEL_VAULT_AWS_REGION=region
----
-You're able to do get single secret value in your route, like for example:
-
-[tabs]
-====
+You can also configure the credentials in the `application.properties` file
such as:
-Java::
-+
-[source,java]
+[source,properties]
----
-from("direct:start")
- .log("Username is {{aws:database#username}}");
+camel.vault.aws.accessKey = accessKey
+camel.vault.aws.secretKey = secretKey
+camel.vault.aws.region = region
----
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{aws:database#username}}"/>
-</route>
-----
+If you want instead to use the
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html[AWS
default credentials provider], you'll need to provide the following env
variables:
-YAML::
-+
-[source,yaml]
+[source,bash]
----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{aws2:database#username}}"
+export $CAMEL_VAULT_AWS_USE_DEFAULT_CREDENTIALS_PROVIDER=true
+export $CAMEL_VAULT_AWS_REGION=region
----
-====
-
-Or re-use the property as part of an endpoint.
-You could specify a default value in case the particular field of secret is
not present on AWS Secret Manager:
-
-[tabs]
-====
+You can also configure the credentials in the `application.properties` file
such as:
-Java::
-+
-[source,java]
+[source,properties]
----
-from("direct:start")
- .log("Username is {{aws:database#username:admin}}");
+camel.vault.aws.defaultCredentialsProvider = true
+camel.vault.aws.region = region
----
+It is also possible to specify a particular profile name for accessing AWS
Secrets Manager:
-XML::
-+
-[source,xml]
+[source,bash]
----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{aws:database#username:admin}}"/>
-</route>
+export $CAMEL_VAULT_AWS_USE_PROFILE_CREDENTIALS_PROVIDER=true
+export $CAMEL_VAULT_AWS_PROFILE_NAME=test-account
+export $CAMEL_VAULT_AWS_REGION=region
----
-YAML::
-+
-[source,yaml]
+You can also configure the credentials in the `application.properties` file
such as:
+
+[source,properties]
----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{aws:database#username:admin}}"
+camel.vault.aws.profileCredentialsProvider = true
+camel.vault.aws.profileName = test-account
+camel.vault.aws.region = region
----
-====
-In this case, if the secret doesn't exist or the secret exists, but the
username field is not part of the secret, the property will fall back to
"admin" as value.
-
-NOTE: For the moment we are not considering the rotation function if any are
applied, but it is in the work to be done.
+At this point you'll be able to reference a property by using `aws:` as prefix
in the `{{ }}` syntax.
+See <<Vault Usage Syntax>> for the full syntax reference.
The only requirement is adding `camel-aws-secrets-manager` JAR to your Camel
application.
@@ -358,1019 +295,131 @@ You can also configure the credentials in the
`application.properties` file such
[source,properties]
----
camel.vault.gcp.useDefaultInstance = true
-camel.vault.aws.projectId = region
+camel.vault.gcp.projectId = projectId
----
-At this point you'll be able to reference a property in the following way by
using `gcp:` as prefix in the `{{ }}` syntax:
+At this point you'll be able to reference a property by using `gcp:` as prefix
in the `{{ }}` syntax.
+See <<Vault Usage Syntax>> for the full syntax reference.
-[tabs]
-====
+There are only two requirements:
+- Adding `camel-google-secret-manager` JAR to your Camel application.
+- Give the service account used permissions to do operation at secret
management level (for example accessing the secret payload, or being admin of
secret manager service)
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{gcp:route}}");
-----
+==== Using Azure Key Vault
-XML::
-+
-[source,xml]
-----
- <route>
- <from uri="direct:start"/>
- <to uri="{{gcp:route}}"/>
- </route>
-----
+To use this function, you'll need to provide credentials to Azure Key Vault
Service as environment variables:
-YAML::
-+
-[source,yaml]
+[source,bash]
----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{gcp:route}}"
+export $CAMEL_VAULT_AZURE_TENANT_ID=tenantId
+export $CAMEL_VAULT_AZURE_CLIENT_ID=clientId
+export $CAMEL_VAULT_AZURE_CLIENT_SECRET=clientSecret
+export $CAMEL_VAULT_AZURE_VAULT_NAME=vaultName
----
-====
-
-Where `route` will be the name of the secret stored in the GCP Secret Manager
Service.
-You could specify a default value (`gcp:key:default-value`) in case the secret
is not present GCP Secret Manager:
-
-[tabs]
-====
+You can also configure the credentials in the `application.properties` file
such as:
-Java::
-+
-[source,java]
+[source,properties]
----
-from("direct:start")
- .to("{{gcp:route:myDefault}}");
+camel.vault.azure.tenantId = accessKey
+camel.vault.azure.clientId = clientId
+camel.vault.azure.clientSecret = clientSecret
+camel.vault.azure.vaultName = vaultName
----
-XML::
-+
-[source,xml]
+Or you can enable the usage of Azure Identity in the following way:
+
+[source,bash]
----
-<route>
- <from uri="direct:start"/>
- <to uri="{{gcp:route:myDefault}}"/>
-</route>
+export $CAMEL_VAULT_AZURE_IDENTITY_ENABLED=true
+export $CAMEL_VAULT_AZURE_VAULT_NAME=vaultName
----
-YAML::
-+
-[source,yaml]
+You can also enable the usage of Azure Identity in the
`application.properties` file such as:
+
+[source,properties]
----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{gcp:route:myDefault}}"
+camel.vault.azure.azureIdentityEnabled = true
+camel.vault.azure.vaultName = vaultName
----
-====
-In this case, if the secret doesn't exist, the property will fallback to
"myDefault" as value.
+At this point you'll be able to reference a property by using `azure:` as
prefix in the `{{ }}` syntax.
+See <<Vault Usage Syntax>> for the full syntax reference.
-Also, you are able to get a particular field of the secret, if you have, for
example, a secret named database of this form:
+The only requirement is adding the `camel-azure-key-vault` JAR to your Camel
application.
-[source,json]
+==== Using Hashicorp Vault
+
+To use this function, you'll need to provide credentials for Hashicorp vault
as environment variables:
+
+[source,bash]
----
-{
- "username": "admin",
- "password": "password123",
- "engine": "postgres",
- "host": "127.0.0.1",
- "port": "3128",
- "dbname": "db"
-}
-----
-
-You're able to do get single secret value in your route, like for example:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{gcp:database#username}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{gcp:database#username}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{gcp:database#username}}"
-----
-====
-
-Or re-use the property as part of an endpoint.
-
-You could specify a default value in case the particular field of secret is
not present on GCP Secret Manager:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{gcp:database#username:admin}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{gcp:database#username:admin}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{gcp:database#username:admin}}"
-----
-====
-
-In this case, if the secret doesn't exist or the secret exists, but the
username field is not part of the secret, the property will fallback to "admin"
as value.
-
-NOTE: For the moment we are not considering the rotation function if any are
applied, but it is in the work to be done.
-
-There are only two requirements:
-- Adding `camel-google-secret-manager` JAR to your Camel application.
-- Give the service account used permissions to do operation at secret
management level (for example accessing the secret payload, or being admin of
secret manager service)
-
-==== Using Azure Key Vault
-
-To use this function, you'll need to provide credentials to Azure Key Vault
Service as environment variables:
-
-[source,bash]
-----
-export $CAMEL_VAULT_AZURE_TENANT_ID=tenantId
-export $CAMEL_VAULT_AZURE_CLIENT_ID=clientId
-export $CAMEL_VAULT_AZURE_CLIENT_SECRET=clientSecret
-export $CAMEL_VAULT_AZURE_VAULT_NAME=vaultName
+export $CAMEL_VAULT_HASHICORP_TOKEN=token
+export $CAMEL_VAULT_HASHICORP_HOST=host
+export $CAMEL_VAULT_HASHICORP_PORT=port
+export $CAMEL_VAULT_HASHICORP_SCHEME=http/https
----
You can also configure the credentials in the `application.properties` file
such as:
[source,properties]
----
-camel.vault.azure.tenantId = accessKey
-camel.vault.azure.clientId = clientId
-camel.vault.azure.clientSecret = clientSecret
-camel.vault.azure.vaultName = vaultName
+camel.vault.hashicorp.token = token
+camel.vault.hashicorp.host = host
+camel.vault.hashicorp.port = port
+camel.vault.hashicorp.scheme = scheme
----
-Or you can enable the usage of Azure Identity in the following way:
+If the running Hashicorp Vault instance is on Hashicorp Cloud, two additional
parameters are required:
[source,bash]
----
-export $CAMEL_VAULT_AZURE_IDENTITY_ENABLED=true
-export $CAMEL_VAULT_AZURE_VAULT_NAME=vaultName
+export CAMEL_HASHICORP_VAULT_CLOUD=true
+export CAMEL_HASHICORP_VAULT_NAMESPACE=namespace
----
-You can also enable the usage of Azure Identity in the
`application.properties` file such as:
+Or in `application.properties`:
[source,properties]
----
-camel.vault.azure.azureIdentityEnabled = true
-camel.vault.azure.vaultName = vaultName
-----
-
-At this point, you'll be able to reference a property in the following way:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{azure:route}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{azure:route}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{azure:route}}"
-----
-====
-
-Where route will be the name of the secret stored in the Azure Key Vault
Service.
-
-You could specify a default value (`azure:key:default-value`) in case the
secret is not present on Azure Key Value Service:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{azure:route:myDefault}}");
+camel.vault.hashicorp.cloud = true
+camel.vault.hashicorp.namespace = namespace
----
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{azure:route:myDefault}}"/>
-</route>
-----
+At this point you'll be able to reference a property by using `hashicorp:` as
prefix in the `{{ }}` syntax.
+Hashicorp Vault also supports <<Version Syntax,version-specific lookups>>
using the `@` suffix.
+See <<Vault Usage Syntax>> for the full syntax reference.
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{azure:route:myDefault}}"
-----
-====
+The only requirement is adding the `camel-hashicorp-vault` JAR to your Camel
application.
-In this case, if the secret doesn't exist, the property will fallback to
"myDefault" as value.
+==== Using IBM Secrets Manager Vault
-Also you are able to get a particular field of the secret if you have, for
example, a secret named database of this form:
+To use this function, you'll need to provide credentials for IBM Secrets
Manager vault as environment variables:
[source,bash]
----
-{
- "username": "admin",
- "password": "password123",
- "engine": "postgres",
- "host": "127.0.0.1",
- "port": "3128",
- "dbname": "db"
-}
-----
-
-You're able to do get single secret value in your route, like for example:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{azure:database#username}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{azure:database#username}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{azure:database#username}}"
-----
-====
-
-Or re-use the property as part of an endpoint.
-
-You could specify a default value in case the particular field of secret is
not present on Azure Key Vault:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{azure:database#username:admin}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{azure:database#username:admin}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{azure:database#username:admin}}"
+export CAMEL_VAULT_IBM_TOKEN=token
+export CAMEL_VAULT_IBM_SERVICE_URL=serviceUrl
----
-====
-
-In this case, if the secret doesn't exist or the secret exists, but the
username field is not part of the secret, the property will fallback to "admin"
as value.
-
-For the moment we are not considering the rotation function if any are
applied, but it is in the work to be done.
-
-The only requirement is adding the camel-azure-key-vault jar to your Camel
application.
-
-==== Using Hashicorp Vault
-To use this function, you'll need to provide credentials for Hashicorp vault
as environment variables:
-
-[source,bash]
-----
-export $CAMEL_VAULT_HASHICORP_TOKEN=token
-export $CAMEL_VAULT_HASHICORP_HOST=host
-export $CAMEL_VAULT_HASHICORP_PORT=port
-export $CAMEL_VAULT_HASHICORP_SCHEME=http/https
-----
-
-You can also configure the credentials in the `application.properties` file
such as:
-
-[source,properties]
-----
-camel.vault.hashicorp.token = token
-camel.vault.hashicorp.host = host
-camel.vault.hashicorp.port = port
-camel.vault.hashicorp.scheme = scheme
-----
-
-In case the running Hashicorp Vault instance you're pointing is running on
Hashicorp Cloud, the configuration will require two additional parameters:
-
-[source,bash]
-----
-export CAMEL_VAULT_HASHICORP_TOKEN=token
-export CAMEL_VAULT_HASHICORP_HOST=host
-export CAMEL_VAULT_HASHICORP_PORT=port
-export CAMEL_VAULT_HASHICORP_SCHEME=http/https
-export CAMEL_HASHICORP_VAULT_CLOUD=true
-export CAMEL_HASHICORP_VAULT_NAMESPACE=namespace
-----
-
-You can also set the same in the `application.properties` file such as:
-
-[source,properties]
-----
-camel.vault.hashicorp.token = token
-camel.vault.hashicorp.host = host
-camel.vault.hashicorp.port = port
-camel.vault.hashicorp.scheme = scheme
-camel.vault.hashicorp.cloud = true
-camel.vault.hashicorp.namespace = namespace
-----
-
-At this point, you'll be able to reference a property in the following way:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{hashicorp:route}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{hashicorp:route}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{hashicorp:route}}"
-----
-====
-
-Where route will be the name of the secret stored in the Hashicorp Vault
instance, in the 'secret' engine.
-
-You could specify a default value in case the secret is not present on
Hashicorp Vault instance:
-
-You could specify a default value (`azure:key:default-value`) in case the
secret is not present on Azure Key Value Service:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{hashicorp:route:myDefault}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{hashicorp:route:myDefault}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{hashicorp:route:myDefault}}"
-----
-====
-
-In this case, if the secret doesn't exist, the property will fallback to
"myDefault" as value.
-
-Also, you are able to get a particular field of the secret, if you have, for
example, a secret named database of this form:
-
-[source,bash]
-----
-{
- "username": "admin",
- "password": "password123",
- "engine": "postgres",
- "host": "127.0.0.1",
- "port": "3128",
- "dbname": "db"
-}
-----
-
-You're able to do get single secret value in your route, in the 'secret'
engine, like, for example:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{hashicorp:database#username}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{hashicorp:database#username}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{hashicorp:database#username}}"
-----
-====
-
-Or re-use the property as part of an endpoint.
-
-You could specify a default value in case the particular field of secret is
not present on Hashicorp Vault instance, in the 'secret' engine:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{hashicorp:database#username:admin}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{hashicorp:database#username:admin}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{hashicorp:database#username:admin}}"
-----
-====
-
-In this case, if the secret doesn't exist or the secret exists (in the
'secret' engine) but the username field is not part of the secret, the property
will fall back to "admin" as value.
-
-There is also the syntax to get a particular version of the secret for both
the approach, with field/default value specified or only with secret:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{hashicorp:secret:route@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{hashicorp:secret:route@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{hashicorp:secret:route@2}}"
-----
-====
-
-This approach will return the RAW route secret with version '2', in the
'secret' engine.
-
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{hashicorp:route:default@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{hashicorp:route:default@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{hashicorp:route:default@2}}"
-----
-====
-
-
-This approach will return the route secret value with version '2' or default
value in case the secret doesn't exist or the version doesn't exist (in the
'secret' engine).
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{hashicorp:secret:database#username:admin@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{hashicorp:secret:database#username:admin@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is
{{hashicorp:secret:database#username:admin@2}}"
-----
-====
-
-This approach will return the username field of the database secret with
version '2' or admin in case the secret doesn't exist or the version doesn't
exist (in the 'secret' engine).
-
-==== Using IBM Secrets Manager Vault
-
-To use this function, you'll need to provide credentials for IBM Secrets
Manager vault as environment variables:
-
-[source,bash]
-----
-export CAMEL_VAULT_IBM_TOKEN=token
-export CAMEL_VAULT_IBM_SERVICE_URL=serviceUrl
-----
-
-You can also configure the credentials in the `application.properties` file
such as:
-
-[source,properties]
-----
-camel.vault.ibm.token = token
-camel.vault.ibm.serviceUrl = serviceUrl
-----
-
-NOTE: if you're running the application on a Kubernetes based cloud platform,
you can initialize the environment variables from a Secret or Configmap to
enhance security. You can also enhance security by
xref:manual::using-propertyplaceholder.adoc#_resolving_property_placeholders_on_cloud[setting
a Secret property placeholder] which will be initialized at application
runtime only.
-
-NOTE: `camel.vault.ibm` configuration only applies to the IBM Secrets Manager
Vault properties function (E.g when resolving properties).
-When using the `operation` option to create, get, list secrets etc., you
should provide the `token` and `serviceUrl` options.
-
-At this point, you'll be able to reference a property in the following way:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{ibm:route}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{ibm:route}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{ibm:route}}"
-----
-====
-
-Where route will be the name of the secret stored in the IBM Secrets Manager
Vault instance, in the 'default' secret group.
-
-You could specify a default value in case the secret is not present on IBM
Secrets Manager Vault instance:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{ibm:default:route:default}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{ibm:default:route:default}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{ibm:default:route:default}}"
-----
-====
-
-In this case, if the secret doesn't exist in the 'default' secret group, the
property will fall back to "default" as value.
-
-Also, you are able to get a particular field of the secret, if you have, for
example, a secret named database of this form:
-
-[source,bash]
-----
-{
- "username": "admin",
- "password": "password123",
- "engine": "postgres",
- "host": "127.0.0.1",
- "port": "3128",
- "dbname": "db"
-}
-----
-
-You're able to do get single secret value in your route, in the 'default'
secret group, like for example:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{ibm:default:database#username}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{ibm:default:database#username}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{ibm:default:database#username}}"
-----
-====
-
-Or re-use the property as part of an endpoint.
-
-You could specify a default value in case the particular field of secret is
not present on IBM Secrets Manager Vault instance, in the 'secret' engine:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{ibm:default:database#username:admin}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{ibm:default:database#username:admin}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{ibm:default:database#username:admin}}"
-----
-====
-
-In this case, if the secret doesn't exist or the secret exists (in the
'default' secret group) but the username field is not part of the secret, the
property will fall back to "admin" as value.
-
-There is also the syntax to get a particular version of the secret for both
the approaches, with field/default value specified or only with secret:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{ibm:default:route@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{ibm:default:route@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{ibm:default:route@2}}"
-----
-====
-
-This approach will return the RAW route secret with version '2', in the
'default' secret group.
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{ibm:default:route:default@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{ibm:default:route:default@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{ibm:default:route:default@2}}"
-----
-====
-
-This approach will return the route secret value with version '2' or default
value in case the secret doesn't exist or the version doesn't exist (in the
'default' secret group).
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{ibm:default:database#username:admin@2}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{ibm:default:database#username:admin@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
+You can also configure the credentials in the `application.properties` file
such as:
+
+[source,properties]
----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{ibm:default:database#username:admin@2}}"
+camel.vault.ibm.token = token
+camel.vault.ibm.serviceUrl = serviceUrl
----
-====
-This approach will return the username field of the database secret with
version '2' or admin in case the secret doesn't exist or the version doesn't
exist (in the 'default' secret group).
+NOTE: If you're running the application on a Kubernetes based cloud platform,
you can initialize the environment variables from a Secret or Configmap to
enhance security. You can also enhance security by
xref:manual::using-propertyplaceholder.adoc#_resolving_property_placeholders_on_cloud[setting
a Secret property placeholder] which will be initialized at application
runtime only.
+
+NOTE: `camel.vault.ibm` configuration only applies to the IBM Secrets Manager
Vault properties function (E.g when resolving properties).
+When using the `operation` option to create, get, list secrets etc., you
should provide the `token` and `serviceUrl` options.
+
+IBM Secrets Manager organizes secrets into _secret groups_. The syntax
includes the group name (e.g. `default`):
+`{{ibm:default:secretName}}`, `{{ibm:default:secretName:fallback}}`,
`{{ibm:default:secretName#field}}`,
+`{{ibm:default:secretName#field:fallback}}`.
+IBM also supports <<Version Syntax,version-specific lookups>> using the `@`
suffix.
+See <<Vault Usage Syntax>> for the full syntax reference.
The only requirement is adding the `camel-ibm-secrets-manager` JAR to your
Camel application.
@@ -1419,286 +468,12 @@ camel.vault.cyberark.password = secretpassword
NOTE: If you're running the application on a Kubernetes based cloud platform,
you can initialize the environment variables from a Secret or ConfigMap to
enhance security.
-At this point, you'll be able to reference a property in the following way:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{cyberark:route}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{cyberark:route}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{cyberark:route}}"
-----
-====
-
-Where `route` will be the name of the secret (variable) stored in the CyberArk
Conjur Vault instance.
-
-You could specify a default value in case the secret is not present on
CyberArk Conjur:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{cyberark:route:default}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{cyberark:route:default}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{cyberark:route:default}}"
-----
-====
-
-In this case, if the secret doesn't exist, the property will fall back to
"default" as value.
-
-Also, you are able to get a particular field of the secret, if you have, for
example, a secret named database of this form:
-
-[source,json]
-----
-{
- "username": "admin",
- "password": "password123",
- "engine": "postgres",
- "host": "127.0.0.1",
- "port": "3128",
- "dbname": "db"
-}
-----
-
-You're able to get single secret value in your route, like for example:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{cyberark:database#username}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{cyberark:database#username}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{cyberark:database#username}}"
-----
-====
-
-Or re-use the property as part of an endpoint.
-
-You could specify a default value in case the particular field of secret is
not present on CyberArk Conjur:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{cyberark:database#username:admin}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{cyberark:database#username:admin}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{cyberark:database#username:admin}}"
-----
-====
-
-In this case, if the secret doesn't exist or the secret exists but the
username field is not part of the secret, the property will fall back to
"admin" as value.
-
-There is also the syntax to get a particular version of the secret for both
the approaches, with field/default value specified or only with secret:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{cyberark:route@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{cyberark:route@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{cyberark:route@2}}"
-----
-====
-
-This approach will return the RAW route secret with version '2'.
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{cyberark:route:default@2}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{cyberark:route:default@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{cyberark:route:default@2}}"
-----
-====
-
-This approach will return the route secret value with version '2' or default
value in case the secret doesn't exist or the version doesn't exist.
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("Username is {{cyberark:database#username:admin@2}}");
-----
-
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <log message="Username is {{cyberark:database#username:admin@2}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "Username is {{cyberark:database#username:admin@2}}"
-----
-====
-
-This approach will return the username field of the database secret with
version '2' or admin in case the secret doesn't exist or the version doesn't
exist.
-
NOTE: CyberArk Conjur requires secrets (variables) to be defined in a policy
file before they can be set.
+At this point you'll be able to reference a property by using `cyberark:` as
prefix in the `{{ }}` syntax.
+CyberArk also supports <<Version Syntax,version-specific lookups>> using the
`@` suffix.
+See <<Vault Usage Syntax>> for the full syntax reference.
+
The only requirement is adding the `camel-cyberark-vault` JAR to your Camel
application.
diff --git a/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
b/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
index 28e6aa917433..d48d76caa862 100644
--- a/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
+++ b/docs/user-manual/modules/ROOT/pages/using-propertyplaceholder.adoc
@@ -712,745 +712,12 @@ the `${}` notation. And in the Camel routes we use the
Camel
placeholder notation with `{\{key}}`.
-== Using property placeholder functions
+== Property Placeholder Functions
-The xref:components::properties-component.adoc[Properties] component includes
the following functions out of the box:
-
-* `env` - A function to lookup the property from OS environment variables
-* `sys` - A function to lookup the property from Java JVM system properties
-* `bean` - A function to lookup the property from the return value of bean's
method (requires `camel-bean` JAR)
-* `boolean` - A function to evaluate if a property key matches a condition and
returns either `true` or `false`
-* `service` - A function to lookup the property from OS environment variables
using the service naming idiom
-* `service.name` - A function to lookup the property from OS environment
variables using the service naming idiom returning the hostname part only
-* `service.port` - A function to lookup the property from OS environment
variables using the service naming idiom returning the port part only
-
-These functions are intended to make it easy to lookup values from the
environment, as shown in the example below:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{env:SOMENAME}}")
- .to("{{sys:MyJvmPropertyName}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{env:SOMENAME}}"/>
- <to uri="{{sys:MyJvmPropertyName}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{env:SOMENAME}}"
- - to:
- uri: "{{sys:MyJvmPropertyName}}"
-----
-====
-
-You can use default values as well, so if the property does not exist, you can
define a default value as shown below, where the default value is a `log:foo`
and `log:bar` value.
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{env:SOMENAME:log:foo}}")
- .to("{{sys:MyJvmPropertyName:log:bar}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{env:SOMENAME:log:foo}}"/>
- <to uri="{{sys:MyJvmPropertyName:log:bar}}"/>
-</route>
-----
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{env:SOMENAME:log:foo}}"
- - to:
- uri: "{{sys:MyJvmPropertyName:log:bar}}"
-----
-====
-
-The boolean function is intended for more flexibility when enabling or
disabling EIP options.
-
-For example given we have a property with key `region` that has the value
`EMEA`:
-
-[source,properties]
-----
-region = EMEA
-----
-
-We can then configure EIPs whether they are disabled based on this condition
as follows:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .choice().disabled("{{boolean:region == 'EMEA'}}")
- .when(simple("${header.RetryAttempts} == null"))
- .setProperty("HttpMessageMethod", constant("SET"))
- .process("SetOriginalMessageProcessor")
- .end();
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <choice disabled="{{boolean:region == 'EMEA'}}">
- <when>
- <simple>${header.RetryAttempts} == null</simple>
- <setProperty name="HttpMessageMethod">
- <constant>SET</constant>
- </setProperty>
- <process ref="SetOriginalMessageProcessor"/>
- </when>
- </choice>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - choice:
- disabled: "{{boolean:region == 'EMEA'}}"
- when:
- - expression:
- simple:
- expression: "${header.RetryAttempts} == null"
- steps:
- - setProperty:
- name: "HttpMessageMethod"
- expression:
- constant: "SET"
- - process:
- ref: "SetOriginalMessageProcessor"
-----
-====
-
-[NOTE]
-====
-Property placeholders can also be used in `application.properties` files, also
with the functions such as ENV as shown:
-
-[source,properties]
-----
-# server name read from ENV and fallback to use localhost as default value
-myserver = {{env:MY_SERVER_NAME:localhost}}
-----
-====
-
-TIP: The boolean function uses the
xref:components:languages:simple-language.adoc[Simple] language which has many
functions and operators to build the condition.
-
-The service function is for looking up a service which is defined using OS
environment variables using the service naming idiom, to refer to a service
location using `hostname : port`
-
-* __NAME__**_SERVICE_HOST**
-* __NAME__**_SERVICE_PORT**
-
-in other words the service uses `_SERVICE_HOST` and `_SERVICE_PORT` as prefix.
-So if the service is named FOO, then the OS environment variables should be
set as
-
-[source,bash]
-----
-export $FOO_SERVICE_HOST=myserver
-export $FOO_SERVICE_PORT=8888
-----
-
-For example if the FOO service a remote HTTP service, then we can refer to the
service in the Camel endpoint uri, and use the HTTP component to make the HTTP
call:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("http://{{service:FOO}}/myapp");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="http://{{service:FOO}}/myapp"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "http://{{service:FOO}}/myapp"
-----
-====
-
-And we can use default values if the service has not been defined, for example
to call a service on localhost, maybe for unit testing.
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("http://{{service:FOO:localhost:8080}}/myapp");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="http://{{service:FOO:localhost:8080}}/myapp"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "http://{{service:FOO:localhost:8080}}/myapp"
-----
-====
-
-The bean function (you need to have `camel-bean` JAR on classpath) is for
looking up the property from the return value of bean's method.
-
-Assuming we have registered a bean named 'foo' that has a method called 'bar'
that returns a directory name, then we can refer to the bean's method in the
camel endpoint url, and use the file component to poll a directory:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("file:{{bean:foo.bar}}")
- .to("direct:result");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="file:{{bean:foo.bar}}"/>
- <to uri="direct:result"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: file:{{bean:foo.bar}}
- steps:
- - to:
- uri: "direct:result"
-----
-====
-
-IMPORTANT: The method must be a public no-arg method (i.e. no parameters) and
return a value such as a String, boolean, int.
-
-=== Using Kubernetes property placeholder functions
-
-The `camel-kubernetes` component include the following functions:
-
-* `configmap` - A function to lookup the string property from Kubernetes
ConfigMaps.
-* `configmap-binary` - A function to lookup the binary property from
Kubernetes ConfigMaps.
-* `secret` - A function to lookup the string property from Kubernetes Secrets.
-* `secret-binary` - A function to lookup the binary property from Kubernetes
Secrets.
-
-The syntax for both functions are:
-
-[source,text]
-----
-configmap:name/key[:defaultValue]
-----
-
-Where the default value is optional, for example the following will lookup
`myKey`,
-and fail if there is no such configmap.
-
-[source,text]
-----
-configmap:mymap/mykey
-----
-
-In this example then it would not fail as a default value is provided:
-
-[source,text]
-----
-configmap:mymap/mykey:123
-----
-
-If the value stored in the configmap is in binary format, so it is stored as
`Binary Data`, it will be downloaded in a file, and it returns the absolute
path of the file
-
-[source,text]
-----
-configmap-binary:mymap/mybinkey
-----
-
-it returns a path like `/tmp/camel11787545916150467474/mybinkey`
-
-Before the Kubernetes property placeholder functions can be used they need to
be configured with either (or both)
-
-- path - A _mount path_ that must be mounted to the running pod, to load the
configmaps or secrets from local disk.
-- kubernetes client - *Autowired* An
`io.fabric8.kubernetes.client.KubernetesClient` instance to use for connecting
to the Kubernetes API server.
-
-Camel will first use _mount paths_ (if configured) to lookup, and then
fallback to use the `KubernetesClient`.
-
-==== Configuring mount paths for ConfigMaps and Secrets
-
-The configuration of the _mount path_ are used by the given order:
-
-1. Reading configuration property with keys
`camel.kubernetes-config.mount-path-configmaps` and
`camel.kubernetes-config.mount-path-secrets`.
-2. Use JVM system property with key `camel.k.mount-path.configmaps` and
`camel.k.mount-path.secrets` (Camel K compatible).
-3. Use OS ENV variable with key `CAMEL_K_MOUNT_PATH_CONFIGMAPS` and
`CAMEL_K_MOUNT_PATH_SECRETS` (Camel K compatible).
-
-For example to use `/etc/camel/resources/` as mount path, you can configure
this in the `application.properties`:
-
-[source,properties]
-----
-camel.kubernetes-config.mount-path-configmaps = /etc/camel/myconfig/
-camel.kubernetes-config.mount-path-secrets = /etc/camel/mysecrets/
-----
-
-==== Configuring Kubernetes Client
-
-Camel will autowire the `KubernetesClient` if a single instance of the client
exists in the running application (lookup via the xref:registry.adoc[Registry]).
-Otherwise, a new `KubernetesClient` is created. The client can be configured
from either
-
-- Using `camel.kubernetes-config.client.` properties (see below for example)
-- Attempt to auto-configure itself by a combination of OS Environment
variables, reading from `~./kube/config` configuration,
-and service account token file. For more details see the
https://github.com/fabric8io/kubernetes-client documentation.
-
-You most likely only need to explicit configure the `KubernetesClient` when
you want to connect
-from a local computer to a remote Kubernetes cluster, where you can specify
various options,
-such as the masterUrl and oauthToken as shown:
-
-[source,properties]
-----
-camel.kubernetes-config.client.masterUrl = https://127.0.0.1:50179/
-camel.kubernetes-config.client.oauthToken = eyJhbGciOiJSUzI1NiIsImtpZCI...
-----
-
-TIP: The `KubernetesClient` has many options, see the
https://github.com/fabric8io/kubernetes-client[Kubernetes Client] documentation
for more information for these options.
-
-If you only use _mount paths_, then it is good practice to disable
`KubernetesClient` which can be done by setting enabled to false as show:
-
-[source,properties]
-----
-camel.kubernetes-config.client-enabled = false
-----
-
-When running your Camel applications inside an existing Kubernetes cluster,
then you often
-would not need to explicit configure the `KubernetesClient` and can rely on
default settings.
-
-TIP: If you use Camel Quarkus, then it is recommended to use their
https://quarkus.io/guides/kubernetes-config
-which automatic pre-configure the `KubernetesClient` which Camel then will
reuse.
-
-==== Using configmap with Kubernetes
-
-Given a configmap named `myconfig` in Kubernetes that has two entries:
-
-[source,properties]
-----
-drink = beer
-first = Carlsberg
-----
-
-Then these values can be used in your Camel routes such as:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("What {{configmap:myconfig/drink}} do you want?")
- .log("I want {{configmap:myconfig/first}}");
-----
-
-XML::
-+
-[source,xml]
-----
- <route>
- <from uri="direct:start"/>
- <log message="What {{configmap:myconfig/drink}} do you want?"/>
- <log message="I want {{configmap:myconfig/first}}"/>
- </route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "What {{configmap:myconfig/drink}} do you want?"
- - log:
- message: "I want {{configmap:myconfig/first}}"
-----
-====
-
-You can also provide a default value in case a key does not exist, such as
`Heiniken` being the default value:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .log("What {{configmap:myconfig/drink}} do you want?")
- .log("I want {{configmap:myconfig/second:Heineken}}");
-----
-
-XML::
-+
-[source,xml]
-----
- <route>
- <from uri="direct:start"/>
- <log message="What {{configmap:myconfig/drink}} do you want?"/>
- <log message="I want {{configmap:myconfig/second:Heineken}}"/>
- </route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - log:
- message: "What {{configmap:myconfig/drink}} do you want?"
- - log:
- message: "I want {{configmap:myconfig/second:Heineken}}"
-----
-====
-
-==== Using secrets with Kubernetes
-
-Camel reads ConfigMaps from the Kubernetes API Server. And when RBAC is
enabled on the cluster,
-the ServiceAccount that is used to run the application needs to have the
proper permissions for such access.
-
-A secret named `mydb` could contain username and passwords to connect to a
database such as:
-
-[source,properties]
-----
-myhost = killroy
-myport = 5555
-myuser = scott
-mypass = tiger
-----
-
-This can be used in Camel with for example the Postgres Sink Kamelet:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-String sink =
-"""
- kamelet:postgresql-sink?serverName={{secret:mydb/myhost}}?
- &serverPort={{secret:mydb/myport}}
- &username={{secret:mydb/myuser}}
- &password={{secret:mydb/mypass}}
- &databaseName=cities
- &query=INSERT INTO accounts (username,city) VALUES (:#username,:#city)
-""";
-
-from("direct:rome")
- .setBody(constant("{ \"username\":\"oscerd\", \"city\":\"Rome\"}"))
- .to(sink);
-----
-
-XML::
-+
-[source,xml]
-----
- <route>
- <from uri="direct:rome"/>
- <setBody>
- <constant>{ "username":"oscerd", "city":"Rome"}</constant>
- </setBody>
- <to uri="kamelet:postgresql-sink?serverName={{secret:mydb/myhost}}
- &serverPort={{secret:mydb/myport}}
- &username={{secret:mydb/myuser}}
- &password={{secret:mydb/mypass}}
- &databaseName=cities
- &query=INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"/>
- </route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct
- parameters:
- name: rome
- steps:
- - setBody:
- expression:
- constant:
- expression: "{ \"username\":\"oscerd\", \"city\":\"Rome\"}"
- - to:
- uri: kamelet
- parameters:
- templateId: postgresql-sink
- serverName: "{{secret:mydb/myhost}}"
- serverPort: "{{secret:mydb/myport}}"
- username: "{{secret:mydb/myuser}}"
- password: "{{secret:mydb/mypass}}"
- databaseName: 'cities'
- query: "INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"
-----
-====
-
-The postgres-sink Kamelet can also be configured in `application.properties`
which reduces the configuration
-in the route above:
-
-[source,properties]
-----
-camel.component.kamelet.postgresql-sink.databaseName={{secret:mydb/myhost}}
-camel.component.kamelet.postgresql-sink.serverPort={{secret:mydb/myport}}
-camel.component.kamelet.postgresql-sink.username={{secret:mydb/myuser}}
-camel.component.kamelet.postgresql-sink.password={{secret:mydb/mypass}}
-----
-
-Which reduces the route to:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:rome")
- .setBody(constant("{ \"username\":\"oscerd\", \"city\":\"Rome\"}"))
- .to("kamelet:postgresql-sink?databaseName=cities&query=INSERT INTO accounts
(username,city) VALUES (:#username,:#city)");
-----
-
-XML::
-+
-[source,xml]
-----
- <route>
- <from uri="direct:rome"/>
- <setBody>
- <constant>{ "username":"oscerd", "city":"Rome"}</constant>
- </setBody>
- <to uri="kamelet:postgresql-sink?databaseName=cities
- &query=INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"/>
- </route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:rome
- steps:
- - setBody:
- expression:
- constant:
- expression: "{ \"username\":\"oscerd\", \"city\":\"Rome\"}"
- - to:
- uri: kamelet
- parameters:
- templateId: postgresql-sink
- databaseName: cities
- query: "INSERT INTO accounts (username,city) VALUES
(:#username,:#city)"
-----
-====
-
-==== Using configmap or secrets in local-mode
-
-During development, you may want to run in _local mode_ where you do not need
acces to a Kubernetes cluster, to lookup the configmap.
-In the local mode, then Camel will lookup the configmap _keys_ from local
properties, eg:
-
-For example the example above with the Postgres kamelet, that was configured
using a secret:
-
-[source,properties]
-----
-camel.component.kamelet.postgresql-sink.databaseName={{secret:mydb/myhost}}
-camel.component.kamelet.postgresql-sink.serverPort={{secret:mydb/myport}}
-camel.component.kamelet.postgresql-sink.username={{secret:mydb/myuser}}
-camel.component.kamelet.postgresql-sink.password={{secret:mydb/mypass}}
-----
-
-Now suppose we have a local Postgres database we want to use, then we can turn
on _local mode_
-and specify the credentials in the same properties file:
-
-[source,properties]
-----
-camel.kubernetes-config.local-mode = true
-mydb/myhost=localhost
-mydb/myport=1234
-mydb/myuser=scott
-mydb/mypass=tiger
-----
-
-NOTE: Notice how the key is prefixed with the name of the secret and a slash,
eg `name/key`. This makes it easy to copy/paste
-from the actual use of the configmap/secret and into the
`application.properties` file.
-
-
-=== Using custom property placeholder functions
-
-The xref:components::properties-component.adoc[Properties] component allow to
plugin 3rd party functions which can be used during parsing of the property
placeholders.
-These functions are then able to do custom logic to resolve the placeholders,
such as looking up in databases, do custom computations, or whatnot.
-The name of the function becomes the prefix used in the placeholder.
-
-This is best illustrated in the example route below, where we use `beer` as
the prefix:
-
-[tabs]
-====
-
-Java::
-+
-[source,java]
-----
-from("direct:start")
- .to("{{beer:FOO}}")
- .to("{{beer:BAR}}");
-----
-
-XML::
-+
-[source,xml]
-----
-<route>
- <from uri="direct:start"/>
- <to uri="{{beer:FOO}}"/>
- <to uri="{{beer:BAR}}"/>
-</route>
-----
-
-YAML::
-+
-[source,yaml]
-----
-- route:
- from:
- uri: direct:start
- steps:
- - to:
- uri: "{{beer:FOO}}"
- - to:
- uri: "{{beer:BAR}}"
-----
-====
-
-The implementation of the function is only two methods as shown below:
-
-[source,java]
-----
[email protected]("beer")
-public class MyBeerFunction implements PropertiesFunction {
-
- @Override
- public String getName() {
- return "beer";
- }
-
- @Override
- public String apply(String remainder) {
- return "mock:" + remainder.toLowerCase();
- }
-}
-----
-
-The function must implement the `org.apache.camel.spi.PropertiesFunction`
interface.
-The method `getName` is the name of the function (beer).
-And the `apply` method is where we implement the custom logic to do.
-As the sample code is from a unit test, it just returns a value to refer to a
mock endpoint.
-
-You also need to have `camel-component-maven-plugin` Maven plugin as part of
building the component will
-then ensure that this custom properties function has necessary source code
generated that makes Camel
-able to automatically discover the function.
-
-NOTE: If the custom properties function need logic to startup and shutdown,
then the function can extend `ServiceSupport`
-and have this logic in `doStart` and `doStop` methods.
-
-TIP: For an example see the `camel-base64` component.
+Camel supports built-in functions for looking up properties from environment
variables, system properties,
+Kubernetes, and custom sources.
+See xref:property-placeholder-functions.adoc[Property Placeholder Functions]
for details.
== Using third party property sources