Using external properties in Camel routes
One of the many nice features in Spring is the ability to use property placeholders such as ${database.url}
to externalize information outside the application in a properties file. This allows your application's deployable artifacts to be built once and move through environments such as development, system test, UAT, and production, each time changing their behavior based on those external values. Camel provides a corresponding mechanism that you can use to externalize values used within routes.
This recipe will show you an approach for externalizing values, such as host name and port number, such that those values can be changed independent of the routing code.
Getting ready
Define a propertyPlaceholder
tag inside the camelContext
element:
<camelContext xmlns="http://camel.apache.org/schema/spring"> <propertyPlaceholder id="properties" location="classpath:placeholder.properties"/> <!-- other code here --> </camelContext>
Properties contained in the file placeholder.properties
can then be used directly inside your Camel route using placeholders.
Note
The id
value "properties
" is mandatory.
The Java code for this recipe is located in the org.camelcookbook.structuringroutes.propertyplaceholder
package. Spring XML files are located under src/main/resources/META-INF/spring
and prefixed with propertyPlaceholder
.
How to do it...
The placeholder syntax is different from the usual Spring ${..}
format, in that properties are delimited by {{
to start and }}
to end.
<route> <from uri="{{start.endpoint}}"/> <transform> <simple>{{transform.message}}: ${body}</simple> </transform> <to uri="{{end.endpoint}}"/> </route>
Consider the following properties file content:
start.endpoint=direct:in transform.message=I hear you end.endpoint=mock:out
Configured with these, the preceding route will consume a message from an in-memory endpoint, prefix the body with I hear you
and send the result to a mock endpoint for testing.
How it works...
This bridging functionality is necessary since Spring has some limitations in terms of allowing third-party libraries to use its property placeholder mechanism.
The location URI scheme can take the following forms:
|
Uses a named |
|
Refers to a fixed path on the filesystem |
|
Refers to a file within the current application |
Location URIs can themselves contain placeholders for JVM system properties and environment variables:
file:${karaf.home}/etc/application.properties file:${env:CATALINA_HOME}/etc/application.properties
Instead of using a property-placeholder
tag, you can also define a PropertiesComponent
object in the Spring context with id
as "properties
", and it will be integrated as expected:
<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent"> <property name="location" value="classpath:placeholder.properties"/> </bean>
This also works when using Camel directly from a Java application without Spring:
PropertiesComponent properties = new PropertiesComponent(); properties.setLocation("classpath:placeholder.properties"); camelContext.addComponent(properties);
The placeholder mechanism just shown also works when defining routes in Java. The following route works as expected inside a Camel context that has a properties placeholder configured:
from("{{start.endpoint}}") .transform().simple("{{transform.message}}: ${body}") .log("Set message to ${body}") .to("{{end.endpoint}}");
There's more...
Camel provides a drop-in replacement for a Spring PropertyPlaceholderConfigurer
, that enables Spring beans to be initialized with ${…}
configuration while allowing Camel logic to make use of {{…}}
placeholders, with the one piece of configuration.
<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> <property name="location" value="classpath:placeholder.properties"/> </bean>
See also
- Using Property Placeholder: http://camel.apache.org/using-propertyplaceholder.html