The property placeholders feature can be used to substitute strings into various contexts (such as endpoint URIs and attributes in XML DSL elements), where the placeholder settings are stored in Java properties files. This feature can be useful, if you want to share settings between different Fuse Mediation Router applications or if you want to centralize certain configuration settings.
For example, the following route sends requests to a Web server, whose host and port are
substituted by the placehoders, {{remote.host}}
and
{{remote.port}}
:
from("direct:start").to("http://{{remote.host}}:{{remote.port}}");
The placeholder values are defined in a Java properties file, as follows:
# Java properties file remote.host=myserver.com remote.port=8080
Property settings are stored in one or more Java properties files and must conform to
the standard Java properties file format. Each property setting appears on its own line, in
the format
.
Lines with Key
=Value
#
or !
as the first non-blank character are treated as
comments.
For example, a property file could have content as shown in Example 2.2.
Example 2.2. Sample Property File
# Property placeholder settings # (in Java properties file format) cool.end=mock:result cool.result=result cool.concat=mock:{{cool.result}} cool.start=direct:cool cool.showid=true cheese.end=mock:cheese cheese.quote=Camel rocks cheese.type=Gouda bean.foo=foo bean.bar=bar
The properties component must be configured with the locations of one or more property files before you can start using it in route definitions. You must provide the property values using one of the following resolvers:
classpath:
PathName
,PathName
,...(Default) Specifies locations on the classpath, where
PathName
is a file pathname delimited using forward slashes.file:
PathName
,PathName
,...Specifies locations on the file system, where
PathName
is a file pathname delimited using forward slashes.ref:
BeanID
Specifies the ID of a
java.util.Properties
object in the registry.blueprint:
BeanID
Specifies the ID of a
cm:property-placeholder
bean, which is used in the context of an OSGi blueprint file to access properties defined in the OSGi Configuration Admin service. For details, see Integration with OSGi blueprint property placeholders.
For example, to specify the com/fusesource/cheese.properties
property file
and the com/fusesource/bar.properties
property file, both located on the
classpath, you would use the following location string:
com/fusesource/cheese.properties,com/fusesource/bar.properties
Note | |
---|---|
You can omit the |
You can embed Java system properties and O/S environment variables in a location
PathName
.
Java system properties can be embedded in a location resolver using the syntax,
${
. For example, if the root
directory of Fuse ESB is stored in the Java system property, PropertyName
}karaf.home
, you could
embed that directory value in a file location, as follows:
file:${karaf.home}/etc/foo.properties
O/S environment variables can be embedded in a location resolver using the syntax,
${env:
. For example, if the root
directory of Fuse ESB is stored in the environment variable, VarName
}SMX_HOME
, you could
embed that directory value in a file location, as follows:
file:${env:SMX_HOME}/etc/foo.properties
Before you can start using property placeholders, you must configure the properties component, specifying the locations of one or more property files.
In the Java DSL, you can configure the properties component with the property file locations, as follows:
// Java import org.apache.camel.component.properties.PropertiesComponent; ... PropertiesComponent pc = new PropertiesComponent(); pc.setLocation("com/fusesource/cheese.properties,com/fusesource/bar.properties"); context.addComponent("properties", pc);
As shown in the addComponent()
call, the name of the properties component
must be set to properties
.
In the XML DSL, you can configure the properties component using the dedicated
propertyPlacholder
element, as follows:
<camelContext ...> <propertyPlaceholder id="properties" location="com/fusesource/cheese.properties,com/fusesource/bar.properties" /> </camelContext>
After it is configured, the property component automatically substitutes placeholders (in the appropriate contexts). The syntax of a placeholder depends on the context, as follows:
In endpoint URIs and in Spring XML files—the placeholder is specified as
{{
.Key
}}When setting XML DSL attributes—
xs:string
attributes are set using the following syntax:AttributeName
="{{Key
}}"Other attribute types (for example,
xs:int
orxs:boolean
) must be set using the following syntax:prop:
AttributeName
="Key
"Where
prop
is associated with thehttp://camel.apache.org/schema/placeholder
namespace.When setting Java DSL EIP options—to set an option on an Enterprise Integration Pattern (EIP) command in the Java DSL, add a
placeholder()
clause like the following to the fluent DSL:.placeholder("
OptionName
", "Key
")In Simple language expressions—the placeholder is specified as
${properties:
.Key
}
Wherever an endpoint URI string appears in a route, the first step in parsing the
endpoint URI is to apply the property placeholder parser. The placeholder parser
automatically substitutes any property names appearing between double braces,
{{
. For example, given the property
settings shown in Example 2.2, you could define
a route as follows:Key
}}
from("{{cool.start}}") .to("log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}") .to("mock:{{cool.result}}");
By default, the placeholder parser looks up the properties
bean ID in the
registry to find the property component. If you prefer, you can explicitly specify the
scheme in the endpoint URIs. For example, by prefixing properties:
to each of
the endpoint URIs, you can define the following equivalent route:
from("properties:{{cool.start}}") .to("properties:log:{{cool.start}}?showBodyType=false&showExchangeId={{cool.showid}}") .to("properties:mock:{{cool.result}}");
When specifying the scheme explicitly, you also have the option of specifying options to
the properties component. For example, to override the property file location, you could set
the location
option as follows:
from("direct:start").to("properties:{{bar.end}}?location=com/mycompany/bar.properties");
You can also use property placeholders in the XML DSL, for setting various attributes of
the DSL elements. In this context, the placholder syntax also uses double braces,
{{
. For example, you could define a
Key
}}jmxAgent
element using property placeholders, as follows:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <propertyPlaceholder id="properties" location="org/apache/camel/spring/jmx.properties"/> <!-- we can use property placeholders when we define the JMX agent --> <jmxAgent id="agent" registryPort="{{myjmx.port}}" usePlatformMBeanServer="{{myjmx.usePlatform}}" createConnector="true" statisticsLevel="RoutesOnly" /> <route> <from uri="seda:start"/> <to uri="mock:result"/> </route> </camelContext>
You can use the regular placeholder syntax for specifying attribute values of
xs:string
type—for example, <jmxAgent
registryPort="{{myjmx.port}}" ...>
. But for attributes of any other type (for
example, xs:int
or xs:boolean
), you must use the special syntax,
prop:
.AttributeName
="Key
"
For example, given that a property file defines the stop.flag
property to
have the value, true
, you can use this property to set the
stopOnException
boolean attribute, as follows:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:prop="http://camel.apache.org/schema/placeholder" ... > <bean id="illegal" class="java.lang.IllegalArgumentException"> <constructor-arg index="0" value="Good grief!"/> </bean> <camelContext xmlns="http://camel.apache.org/schema/spring"> <propertyPlaceholder id="properties" location="classpath:org/apache/camel/component/properties/myprop.properties" xmlns="http://camel.apache.org/schema/spring"/> <route> <from uri="direct:start"/> <multicast prop:stopOnException="stop.flag"> <to uri="mock:a"/> <throwException ref="damn"/> <to uri="mock:b"/> </multicast> </route> </camelContext> </beans>
Important | |
---|---|
The |
When invoking an EIP command in the Java DSL, you can set any EIP option using the value
of a property placeholder, by adding a sub-clause of the form,
placeholder("
.OptionName
",
"Key
")
For example, given that a property file defines the stop.flag
property to
have the value, true
, you can use this property to set the
stopOnException
option of the multicast EIP, as follows:
from("direct:start") .multicast().placeholder("stopOnException", "stop.flag") .to("mock:a").throwException(new IllegalAccessException("Damn")).to("mock:b");
You can also substitute property placeholders in Simple language expressions, but in
this case the syntax of the placeholder is
${properties:
. For example, you can substitute
the Key
}cheese.quote
placehoder inside a Simple expression, as follows:
from("direct:start") .transform().simple("Hi ${body} do you think ${properties:cheese.quote}?");
It is also possible to override the location of the property file using the syntax,
${properties:
.
For example, to substitute the Location
:Key
}bar.quote
placeholder using the settings from
the com/mycompany/bar.properties
property file, you can define a Simple
expression as follows:
from("direct:start") .transform().simple("Hi ${body}. ${properties:com/mycompany/bar.properties:bar.quote}.");
If you deploy your Fuse Mediation Router application into the Fuse ESB OSGi container, you can integrate the Fuse Mediation Router property placeholder mechanism with Fuse ESB's blueprint property placeholder mechanism (in fact, the integration is enabled by default). There are two basic approaches to setting up the integration, as follows:
If you define a camelContext
element inside an OSGi blueprint file, the
Fuse Mediation Router property placeholder mechanism automatically integrates with the blueprint property
placeholder mechanism. That is, placeholders obeying the Fuse Mediation Router syntax (for example,
{{cool.end}}
) that appear within the scope of camelContext
are
implicitly resolved by looking up the blueprint property placeholder
mechanism.
For example, consider the following route defined in an OSGi blueprint file, where the
last endpoint in the route is defined by the property placeholder,
{{result}}
:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <!-- OSGI blueprint property placeholder --> <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint"> <!-- list some properties for this test --> <cm:default-properties> <cm:property name="result" value="mock:result"/> </cm:default-properties> </cm:property-placeholder> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <!-- in the route we can use {{ }} placeholders which will look up in blueprint, as Camel will auto detect the OSGi blueprint property placeholder and use it --> <route> <from uri="direct:start"/> <to uri="mock:foo"/> <to uri="{{result}}"/> </route> </camelContext> </blueprint>
The blueprint property placeholder mechanism is initialized by creating a
cm:property-placeholder
bean. In the preceding example, the
cm:property-placeholder
bean is associated with the
camel.blueprint
persistent ID, where a persistent ID is the standard way of
referencing a group of related properties from the OSGi Configuration
Adminn service. In other words, the cm:property-placeholder
bean
provides access to all of the properties defined under the camel.blueprint
persistent ID. It is also possible to specify default values for some of the properties
(using the nested cm:property
elements).
In the context of blueprint, the Fuse Mediation Router placeholder mechanism searches for an instance
of cm:property-placeholder
in the bean registry. If it finds such an instance,
it automatically integrates the Fuse Mediation Router placeholder mechanism, so that placeholders like,
{{result}}
, are resolved by looking up the key in the blueprint property
placeholder mechanism (in this example, through the myblueprint.placeholder
bean).
Note | |
---|---|
The default blueprint placeholder syntax (accessing the blueprint properties directly)
is |
If you want to have more control over where the Fuse Mediation Router property placeholder mechanism
finds its properties, you can define a propertyPlaceholder
element and specify
the resolver locations explicitly.
For example, consider the following blueprint configuration, which differs from the
previous example in that it creates an explicit propertyPlaceholder
instance:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xsi:schemaLocation=" http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> <!-- OSGI blueprint property placeholder --> <cm:property-placeholder id="myblueprint.placeholder" persistent-id="camel.blueprint"> <!-- list some properties for this test --> <cm:default-properties> <cm:property name="result" value="mock:result"/> </cm:default-properties> </cm:property-placeholder> <camelContext xmlns="http://camel.apache.org/schema/blueprint"> <!-- using Camel properties component and refer to the blueprint property placeholder by its id --> <propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder"/> <!-- in the route we can use {{ }} placeholders which will lookup in blueprint --> <route> <from uri="direct:start"/> <to uri="mock:foo"/> <to uri="{{result}}"/> </route> </camelContext> </blueprint>
In the preceding example, the propertyPlaceholder
element specifies
explicitly which cm:property-placeholder
bean to use by setting the location to
blueprint:myblueprint.placeholder
. That is, the blueprint:
resolver explicitly references the ID, myblueprint.placeholder
, of the
cm:property-placeholder
bean.
This style of configuration is useful, if there is more than one
cm:property-placeholder
bean defined in the blueprint file and you need to
specify which one to use. It also makes it possible to source properties from multiple
locations, by specifying a comma-separated list of locations. For example, if you wanted to
look up properties both from the cm:property-placeholder
bean and from the
properties file, myproperties.properties
, on the classpath, you could define
the propertyPlaceholder
element as follows:
<propertyPlaceholder id="properties" location="blueprint:myblueprint.placeholder,classpath:myproperties.properties"/>