Languages Supported Appendix. Apache Camel
Below you will find brief information for Camel. This guide introduces Apache Camel, a powerful open-source integration framework. Learn about Enterprise Integration Patterns, Bean Integration, and how to create routing and mediation rules using Java, Scala, or XML.
Advertisement
Advertisement
Languages Supported Appendix
To support flexible and powerful Enterprise Integration Patterns Camel supports various
Languages to create an Expression or Predicate within either the Routing Domain Specific
Language or the Xml Configuration. The following languages are supported
BEAN LANGUAGE
The purpose of the Bean Language is to be able to implement an Expression or Predicate using a simple method on a bean.
So the idea is you specify a bean name which will then be resolved in the Registry such as the Spring ApplicationContext then a method is invoked to evaluate the Expression or
Predicate.
If no method name is provided then one is attempted to be chosen using the rules for Bean
Binding; using the type of the message body and using any annotations on the bean methods.
The Bean Binding rules are used to bind the Message Exchange to the method parameters; so you can annotate the bean to extract headers or other expressions such as XPath or
XQuery from the message.
Using Bean Expressions from the Java DSL
from( "activemq:topic:OrdersTopic" ).
filter().method( "myBean" , "isGoldCustomer" ).
to( "activemq:BigSpendersQueue" );
Using Bean Expressions from XML
<route>
<from uri= "activemq:topic:OrdersTopic" />
<filter>
<method bean= "myBean" method= "isGoldCustomer" />
<to uri= "activemq:BigSpendersQueue" />
</filter>
</route>
193 LANGUAGES SUPPORTED APPENDIX
Writing the expression bean
The bean in the above examples is just any old Java Bean with a method called isGoldCustomer() that returns some object that is easily converted to a
boolean value in this
case, as its used as a predicate.
So we could implement it like this...
public class MyBean { public boolean isGoldCustomer(Exchange exchange) {
...
}
}
We can also use the Bean Integration annotations. For example you could do...
or public boolean isGoldCustomer( String body) {...} public boolean isGoldCustomer(@Header(name = "foo" ) Integer fooHeader) {...}
So you can bind parameters of the method to the Exchange, the Message or individual headers, properties, the body or other expressions.
Non registry beans
As of Camel 1.5 the Bean Language also supports invoking beans that isn't registered in the
Registry. This is usable for quickly to invoke a bean from Java DSL where you don't need to register the bean in the Registry such as the Spring ApplicationContext.
Camel can instantiate the bean and invoke the method if given a class or invoke an already existing instance. This is illustrated from the example below:
NOTE This bean DSL is supported since Camel 2.0-M2
from( "activemq:topic:OrdersTopic" ).
filter().expression(BeanLanguage(MyBean.class, "isGoldCustomer" )).
to( "activemq:BigSpendersQueue" );
The 2nd parameter isGoldCustomer is an optional parameter to explicit set the method name to invoke. If not provided Camel will try to invoke the best suited method. If case of ambiguity Camel will thrown an Exception. In these situations the 2nd parameter can solve this problem. Also the code is more readable if the method name is provided. The 1st parameter can also be an existing instance of a Bean such as:
LANGUAGES SUPPORTED APPENDIX 194
private MyBean my; from( "activemq:topic:OrdersTopic" ).
filter().expression(BeanLanguage.bean(my, "isGoldCustomer" )).
to( "activemq:BigSpendersQueue" );
In Camel 2.2 onwards you can avoid the BeanLanguage and have it just as: private MyBean my; from( "activemq:topic:OrdersTopic" ).
filter().expression(bean(my, "isGoldCustomer" )).
to( "activemq:BigSpendersQueue" );
Which also can be done in a bit shorter and nice way: private MyBean my; from( "activemq:topic:OrdersTopic" ).
filter().method(my, "isGoldCustomer" ).
to( "activemq:BigSpendersQueue" );
Other examples
We have some test cases you can look at if it'll help
• MethodFilterTest is a JUnit test case showing the Java DSL use of the bean expression being used in a filter
• aggregator.xml is a Spring XML test case for the Aggregator which uses a bean method call to test for the completion of the aggregation.
Dependencies
The Bean language is part of
camel-core.
CONSTANT EXPRESSION LANGUAGE
The Constant Expression Language is really just a way to specify constant strings as a type of expression.
Available as of Camel 1.5
Example usage
The setHeader element of the Spring DSL can utilize a constant expression like:
195 LANGUAGES SUPPORTED APPENDIX
<route>
<from uri= "seda:a" />
<setHeader headerName= "theHeader" >
<constant>the value</constant>
</setHeader>
<to uri= "mock:b" />
</route> in this case, the Message coming from the seda:a Endpoint will have 'theHeader' header set to the constant value 'the value'.
And the same example using Java DSL: from( "seda:a" ).setHeader( "theHeader" , constant( "the value" )).to( "mock:b" );
Dependencies
The Constant language is part of
camel-core.
EL
Camel supports the unified JSP and JSF Expression Language via the JUEL to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
For example you could use EL inside a Message Filter in XML
<route>
<from uri= "seda:foo" />
<filter>
<el> ${in.headers.foo == 'bar'} </el>
<to uri= "seda:bar" />
</filter>
</route>
You could also use slightly different syntax, e.g. if the header name is not a valid identifier:
<route>
<from uri= "seda:foo" />
<filter>
<el> ${in.headers['My Header'] == 'bar'} </el>
<to uri= "seda:bar" />
</filter>
</route>
You could use EL to create an Predicate in a Message Filter or as an Expression for a Recipient
List
LANGUAGES SUPPORTED APPENDIX 196
Variables
Variable Type Description
exchange Exchange the Exchange object in out
Message
Message the exchange.in message the exchange.out message
Samples
You can use EL dot notation to invoke operations. If you for instance have a body that contains a POJO that has a getFamiliyName method then you can construct the syntax as follows:
"$in.body.familyName"
Dependencies
To use EL in your camel routes you need to add the a dependency on
camel-juel which
implements the EL language.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-juel</artifactId>
<version>1.6.1</version>
</dependency>
Otherwise you'll also need to include JUEL.
HEADER EXPRESSION LANGUAGE
The Header Expression Language allows you to extract values of named headers.
Available as of Camel 1.5
Example usage
The recipientList element of the Spring DSL can utilize a header expression like:
<route>
<from uri= "direct:a" />
<!-- use comma as a delimiter for String based values -->
197 LANGUAGES SUPPORTED APPENDIX
<recipientList delimiter= "," >
<header> myHeader </header>
</recipientList>
</route>
In this case, the list of recipients are contained in the header 'myHeader'.
And the same example in Java DSL: from( "direct:a" ).recipientList(header( "myHeader" ));
And with a slightly different syntax where you use the builder to the fullest (i.e. avoid using parameters but using stacked operations, notice that header is not a parameter but a stacked method call) from( "direct:a" ).recipientList().header( "myHeader" );
Dependencies
The Header language is part of
camel-core.
JXPATH
Camel supports JXPath to allow XPath expressions to be used on beans in an Expression or
Predicate to be used in the DSL or Xml Configuration. For example you could use JXPath to create an Predicate in a Message Filter or as an Expression for a Recipient List.
From 1.3 of Camel onwards you can use XPath expressions directly using smart completion in your IDE as follows from( "queue:foo" ).filter().
jxpath( "/in/body/foo" ).
to( "queue:bar" )
Variables
Variable Type this
Exchange
Description
the Exchange object in out
Message
Message the exchange.in message the exchange.out message
LANGUAGES SUPPORTED APPENDIX 198
Using XML configuration
If you prefer to configure your routes in your Spring XML file then you can use JXPath expressions as follows
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/ schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/ camel-spring.xsd">
<camelContext id= "camel" xmlns= "http://activemq.apache.org/camel/schema/spring" >
<route>
<from uri= "activemq:MyQueue" />
<filter>
<jxpath> in/body/name = 'James' </xpath>
<to uri= "mqseries:SomeOtherQueue" />
</filter>
</route>
</camelContext>
</beans>
Examples
Here is a simple example using a JXPath expression as a predicate in a Message Filter from( "direct:start" ).
filter().jxpath( "in/body/name='James'" ).
to( "mock:result" );
JXPATH INJECTION
You can use Bean Integration to invoke a method on a bean and use various languages such as
JXPath to extract a value from the message and bind it to a method parameter.
For example public class Foo {
@MessageDriven(uri = "activemq:my.queue" ) public void doSomething(@JXPath( "in/body/foo" ) String correlationID, @Body String body) {
// process the inbound message here
}
}
199 LANGUAGES SUPPORTED APPENDIX
Variables
Variable this
exchange exception exchangeId fault request response
Dependencies
To use JXpath in your camel routes you need to add the a dependency on
camel-jxpath
which implements the JXpath language.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jxpath</artifactId>
<version>1.4.0</version>
</dependency>
Otherwise, you'll also need Commons JXPath.
MVEL
Avialable in Camel 2.0
Camel allows Mvel to be used as an Expression or Predicate the DSL or Xml Configuration.
You could use Mvel to create an Predicate in a Message Filter or as an Expression for a
Recipient List
You can use Mvel dot notation to invoke operations. If you for instance have a body that contains a POJO that has a getFamiliyName method then you can construct the syntax as follows:
"request.body.familyName"
// or
"getRequest().getBody().getFamilyName()"
Type Description
Exchange the Exchange is the root object
Exchange the Exchange object
Throwable the Exchange exception (if any)
String
Message
Message
Message the exchange id the Fault message (if any) the exchange.in message the exchange.out message (if any)
LANGUAGES SUPPORTED APPENDIX 200
properties property(name)
Map
Object property(name, type) Type the exchange properties the property by the given name the property by the given name as the given type
Samples
For example you could use Mvel inside a Message Filter in XML
<route>
<from uri= "seda:foo" />
<filter>
<mvel>request.headers.foo == 'bar'</mvel>
<to uri= "seda:bar" />
</filter>
</route>
And the sample using Java DSL: from( "seda:foo" ).filter().mvel( "request.headers.foo == 'bar'" ).to( "seda:bar" );
Dependencies
To use Mvel in your camel routes you need to add the a dependency on
camel-mvel which
implements the Mvel language.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mvel</artifactId>
<version>2.0.0</version>
</dependency>
Otherwise, you'll also need MVEL
OGNL
Camel allows OGNL to be used as an Expression or Predicate the DSL or Xml Configuration.
You could use OGNL to create an Predicate in a Message Filter or as an Expression for a
Recipient List
201 LANGUAGES SUPPORTED APPENDIX
You can use OGNL dot notation to invoke operations. If you for instance have a body that contains a POJO that has a getFamiliyName method then you can construct the syntax as follows:
"request.body.familyName"
// or
"getRequest().getBody().getFamilyName()"
Variables
Variable this
exchange exception exchangeId fault request response properties property(name)
Map
Object property(name, type) Type
Type Description
Exchange the Exchange is the root object
Exchange the Exchange object
Throwable the Exchange exception (if any)
String
Message
Message
Message the exchange id the Fault message (if any) the exchange.in message the exchange.out message (if any) the exchange properties the property by the given name the property by the given name as the given type
Samples
For example you could use OGNL inside a Message Filter in XML
<route>
<from uri= "seda:foo" />
<filter>
<ognl>request.headers.foo = 'bar'</ognl>
<to uri= "seda:bar" />
</filter>
</route>
And the sample using Java DSL: from( "seda:foo" ).filter().ognl( "request.headers.foo = 'bar'" ).to( "seda:bar" );
LANGUAGES SUPPORTED APPENDIX 202
Dependencies
To use OGNL in your camel routes you need to add the a dependency on
camel-ognl which
implements the OGNL language.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ognl</artifactId>
<version>1.4.0</version>
</dependency>
Otherwise, you'll also need OGNL
PROPERTY EXPRESSION LANGUAGE
The Property Expression Language allows you to extract values of named exchange properties.
Available as of Camel 2.0
Example usage
The recipientList element of the Spring DSL can utilize a property expression like:
<route>
<from uri= "direct:a" />
<recipientList>
<property> myProperty </property>
</recipientList>
</route>
In this case, the list of recipients are contained in the property 'myProperty'.
And the same example in Java DSL: from( "direct:a" ).recipientList(property( "myProperty" ));
And with a slightly different syntax where you use the builder to the fullest (i.e. avoid using parameters but using stacked operations, notice that property is not a parameter but a stacked method call) from( "direct:a" ).recipientList().property( "myProperty" );
203 LANGUAGES SUPPORTED APPENDIX
Dependencies
The Property language is part of
camel-core.
SCRIPTING LANGUAGES
Camel supports a number of scripting languages which can be used to create an Expression or
Predicate via the standard JSR 223 which is a standard part of Java 6.
The following scripting languages are integrated into the DSL:
Language DSL keyword
EL el
Groovy groovy
JavaScript
JoSQL
JXPath
MVEL
OGNL
PHP javaScript sql jxpath mvel ognl php
Python
Ruby python ruby
XPath xpath
XQuery xquery
However any JSR 223 scripting language can be used using the generic DSL methods.
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
context org.apache.camel.CamelContext
The Camel Context exchange request response org.apache.camel.Exchange
org.apache.camel.Message
org.apache.camel.Message
The current Exchange
The IN message
The OUT message
LANGUAGES SUPPORTED APPENDIX 204
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
BeanShell BeanShell 2.0b5
beanshell or bsh
205 LANGUAGES SUPPORTED APPENDIX
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
SEE ALSO
• Languages
• DSL
• Xml Configuration
BEANSHELL
Camel supports BeanShell among other Scripting Languages to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
To use a BeanShell expression use the following Java code:
...choice()
.when(script( "beanshell" , "request.getHeaders().get(\" foo\ ").equals(\" bar\ ")" ))
.to( "..." )
Or the something like this in your Spring XML:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ) == null </language>
...
You could follow the examples above to create an Predicate in a Message Filter or as an
Expression for a Recipient List
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
LANGUAGES SUPPORTED APPENDIX 206
BeanShell Issues
You must use BeanShell 2.0b5 or greater. Note that as of 2.0b5 BeanShell cannot compile scripts, which causes Camel releases before 2.6 to fail when configured with BeanShell expressions.
context exchange request response org.apache.camel.CamelContext
The Camel Context org.apache.camel.Exchange
The current Exchange org.apache.camel.Message
org.apache.camel.Message
The IN message
The OUT message
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
207 LANGUAGES SUPPORTED APPENDIX
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
BeanShell BeanShell 2.0b5
beanshell or bsh
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
JAVASCRIPT
Camel supports JavaScript/ECMAScript among other Scripting Languages to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
To use a JavaScript expression use the following Java code
... javaScript( "someJavaScriptExpression" ) ...
For example you could use the
javaScript function to create an Predicate in a Message Filter
or as an Expression for a Recipient List
Example
In the sample below we use JavaScript to create a Predicate use in the route path, to route exchanges from admin users to a special queue.
LANGUAGES SUPPORTED APPENDIX 208
from( "direct:start" )
.choice()
.when().javaScript( "request.headers.get('user') ==
'admin'" ).to( "seda:adminQueue" )
.otherwise()
.to( "seda:regularQueue" );
And a Spring DSL sample as well:
<route>
<from uri= "direct:start" />
<choice>
<when>
<javaScript> request.headers.get('user') == 'admin' </javaScript>
<to uri= "seda:adminQueue" />
</when>
<otherwise>
<to uri= "seda:regularQueue" />
</otherwise>
</choice>
</route>
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
context exchange request response org.apache.camel.CamelContext
org.apache.camel.Exchange
org.apache.camel.Message
org.apache.camel.Message
The Camel Context
The current Exchange
The IN message
The OUT message
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
209 LANGUAGES SUPPORTED APPENDIX
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
BeanShell BeanShell 2.0b5
beanshell or bsh
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
LANGUAGES SUPPORTED APPENDIX 210
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
GROOVY
Camel supports Groovy among other Scripting Languages to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
To use a Groovy expression use the following Java code
... groovy( "someGroovyExpression" ) ...
For example you could use the
groovy function to create an Predicate in a Message Filter or
as an Expression for a Recipient List
Example
// lets route if a line item is over $100 from( "queue:foo" ).filter(groovy( "request.lineItems.any { i -> i.value > 100
}" )).to( "queue:bar" )
And the Spring DSL:
<route>
<from uri= "queue:foo" />
<filter>
<groovy> request.lineItems.any { i -> i.value > 100 } </groovy>
<to uri= "queue:bar" />
</filter>
</route>
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
context org.apache.camel.CamelContext
The Camel Context exchange request org.apache.camel.Exchange
org.apache.camel.Message
The current Exchange
The IN message
211 LANGUAGES SUPPORTED APPENDIX
response org.apache.camel.Message
The OUT message
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
LANGUAGES SUPPORTED APPENDIX 212
BeanShell BeanShell 2.0b5
beanshell or bsh
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
PYTHON
Camel supports Python among other Scripting Languages to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
To use a Python expression use the following Java code
... python( "somePythonExpression" ) ...
For example you could use the
python function to create an Predicate in a Message Filter or
as an Expression for a Recipient List
Example
In the sample below we use Python to create a Predicate use in the route path, to route exchanges from admin users to a special queue.
from( "direct:start" )
.choice()
.when().python( "request.headers['user'] == 'admin'" ).to( "seda:adminQueue" )
.otherwise()
.to( "seda:regularQueue" );
And a Spring DSL sample as well:
<route>
<from uri= "direct:start" />
<choice>
213 LANGUAGES SUPPORTED APPENDIX
<when>
<python> request.headers['user'] == 'admin' </python>
<to uri= "seda:adminQueue" />
</when>
<otherwise>
<to uri= "seda:regularQueue" />
</otherwise>
</choice>
</route>
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
context exchange request response org.apache.camel.CamelContext
org.apache.camel.Exchange
org.apache.camel.Message
org.apache.camel.Message
The Camel Context
The current Exchange
The IN message
The OUT message
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
LANGUAGES SUPPORTED APPENDIX 214
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
BeanShell BeanShell 2.0b5
beanshell or bsh
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
PHP
Camel supports PHP among other Scripting Languages to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
To use a PHP expression use the following Java code
215 LANGUAGES SUPPORTED APPENDIX
... php( "somePHPExpression" ) ...
For example you could use the
php function to create an Predicate in a Message Filter or as an
Expression for a Recipient List
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
context exchange org.apache.camel.CamelContext
org.apache.camel.Exchange
The Camel Context
The current Exchange request org.apache.camel.Message
The IN message response org.apache.camel.Message
The OUT message
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
LANGUAGES SUPPORTED APPENDIX 216
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
BeanShell BeanShell 2.0b5
beanshell or bsh
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
RUBY
Camel supports Ruby among other Scripting Languages to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
To use a Ruby expression use the following Java code
... ruby( "someRubyExpression" ) ...
217 LANGUAGES SUPPORTED APPENDIX
For example you could use the
ruby function to create an Predicate in a Message Filter or as
an Expression for a Recipient List
Example
In the sample below we use Ruby to create a Predicate use in the route path, to route exchanges from admin users to a special queue.
from( "direct:start" )
.choice()
.when().ruby( "$request.headers['user'] == 'admin'" ).to( "seda:adminQueue" )
.otherwise()
.to( "seda:regularQueue" );
And a Spring DSL sample as well:
<route>
<from uri= "direct:start" />
<choice>
<when>
<ruby> $request.headers['user'] == 'admin' </ruby>
<to uri= "seda:adminQueue" />
</when>
<otherwise>
<to uri= "seda:regularQueue" />
</otherwise>
</choice>
</route>
ScriptContext
The JSR-223 scripting languages ScriptContext is pre configured with the following attributes all set at ENGINE_SCOPE:
Attribute Type Value
context exchange request response org.apache.camel.CamelContext
org.apache.camel.Exchange
org.apache.camel.Message
org.apache.camel.Message
The Camel Context
The current Exchange
The IN message
The OUT message
Attributes
You can add your own attributes with the attribute(name, value) DSL method, such as:
LANGUAGES SUPPORTED APPENDIX 218
In the sample below we add an attribute user that is an object we already have instantiated as myUser. This object has a getFirstName() method that we want to set as header on the message. We use the groovy language to concat the first and last name into a single string that is returned.
from( "direct:in" ).setHeader( "name" ).groovy( "'$user.firstName
$user.lastName'" ).attribute( "user" , myUser).to( "seda:users" );
Any scripting language
Camel can run any JSR-223 scripting languages using the script DSL method such as: from( "direct:in" ).setHeader( "firstName" ).script( "jaskel" ,
"user.firstName" ).attribute( "user" , myUser).to( "seda:users" );
This is a bit different using the Spring DSL where you use the
expression element that
doesn't support setting attributes (yet):
<from uri= "direct:in" />
<setHeader headerName= "firstName" >
<expression language= "jaskel" > user.firstName
</expression>
</setHeader>
<to uri= "seda:users" />
You can also use predicates e.g. in a Filter:
<filter>
<language language= "beanshell" > request.getHeaders().get( "Foo" ).equals( "Bar" ) </language>
<to uri= "direct:next" />
</filter>
See Scripting Languages for the list of languages with explicit DSL support.
Some languages without specific DSL support but known to work with these generic methods include:
Language Implementation language="..." value
BeanShell BeanShell 2.0b5
beanshell or bsh
Dependencies
To use scripting languages in your camel routes you need to add the a dependency on
camel-
script which integrates the JSR-223 scripting engine.
219 LANGUAGES SUPPORTED APPENDIX
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-script</artifactId>
<version>1.4.0</version>
</dependency>
SIMPLE EXPRESSION LANGUAGE
The Simple Expression Language was a really simple language you can use, but has since grown more powerful. Its primarily intended for being a really small and simple language for evaluating
Expression and Predicate without requiring any new dependencies or knowledge of XPath; so its ideal for testing in camel-core. Its ideal to cover 95% of the common use cases when you need a little bit of expression based script in your Camel routes.
However for much more complex use cases you are generally recommended to choose a more expressive and powerful language such as:
• JavaScript
• EL
• OGNL
• Mvel
• Groovy
• one of the supported Scripting Languages
The simple language uses ${body} placeholders for complex expressions where the expression contains constant literals. The ${ } placeholders can be omitted if the expression is only the token itself.
To get the body of the in message: "body", or "in.body" or "${body}".
A complex expression must use ${ } placeholders, such as: "Hello
${in.header.name} how are you?".
You can have multiple tokens in the same expression: "Hello ${in.header.name} this is ${in.header.me} speaking".
However you can
not nest tokens (i.e. having another ${ } placeholder in an existing, is not
allowed).
Variables
Variable
exchangeId id
Type Description
String
Camel 2.3: the exchange id
String the input message id
LANGUAGES SUPPORTED APPENDIX 220
Alternative syntax
From Camel 2.5 onwards you can also use the alternative syntax which uses
$simple{ } as placeholders.
This can be used in situations to avoid clashes when using for example Spring property placeholder together with Camel.
File language is now merged with Simple language
From Camel 2.2 onwards, the File Language is now merged with Simple language which means you can use all the file syntax directly within the simple language.
body in.body
body.
OGNL
in.body.
OGNL
bodyAs(type) mandatoryBodyAs(type)
Object the input body
Object the input body
Object
Object
Type
Type
Camel 2.3: the input body invoked using a Camel
OGNL expression.
Camel 2.3: the input body invoked using a Camel
OGNL expression.
Camel 2.3: Converts the body to the given type
determined by its classname. The converted body can be null.
Camel 2.5: Converts the body to the given type
determined by its classname, and expects the body to be not null.
out.body
header.foo
headers.foo
in.header.foo
in.headers.foo
header.foo[bar] in.header.foo[bar]
Object
Object
Object
Object the output body refer to the input foo header refer to the input foo header refer to the input foo header
Object refer to the input foo header
Object
Camel 2.3: regard input foo header as a map and
perform lookup on the map with bar as key
Object
Camel 2.3: regard input foo header as a map and
perform lookup on the map with bar as key
221 LANGUAGES SUPPORTED APPENDIX
in.headers.foo[bar] header.foo.
OGNL
in.header.foo.
OGNL
in.headers.foo.
out.header.foo
OGNL
out.headers.foo
headerAs(key,type)
Object
Object
Object
Object
Camel 2.3: regard input foo header as a map and
perform lookup on the map with bar as key
Camel 2.3: refer to the input foo header and invoke
its value using a Camel OGNL expression.
Camel 2.3: refer to the input foo header and invoke
its value using a Camel OGNL expression.
Camel 2.3: refer to the input foo header and invoke
its value using a Camel OGNL expression.
Object refer to the out header foo
Object refer to the out header foo
Type
Camel 2.5: Converts the header to the given type
determined by its classname property.foo
sys.foo
sysenv.foo
exception exception.
OGNL
exception.message
exception.stacktrace
Object refer to the foo property on the exchange
String refer to the system property
String
Camel 2.3: refer to the system environment
Object
Object
Camel 2.4: Refer to the exception object on the
exchange, is
null if no exception set on exchange. Will
fallback and grab caught exceptions
(Exchange.EXCEPTION_CAUGHT) if the Exchange has any.
Camel 2.4: Refer to the exchange exception invoked
using a Camel OGNLE expression object
String
String
Camel 2.0. Refer to the exception.message on the
exchange, is
null if no exception set on exchange. Will
fallback and grab caught exceptions
(Exchange.EXCEPTION_CAUGHT) if the Exchange has any.
Camel 2.6. Refer to the exception.stracktrace on the
exchange, is
null if no exception set on exchange. Will
fallback and grab caught exceptions
(Exchange.EXCEPTION_CAUGHT) if the Exchange has any.
LANGUAGES SUPPORTED APPENDIX 222
date:command:pattern bean:bean expression properties:locations:key threadName
String
Object
String
String
Camel 1.5. Date formatting using the
java.text.SimpleDataFormat patterns.
Supported commands are:
now for current timestamp,
in.header.xxx or header.xxx to use the Date
object in the IN header with the key xxx.
out.header.xxx to use the Date object in the OUT
header with the key xxx.
Camel 1.5. Invoking a bean expression using the Bean
language. Specifying a method name you must use dot as separator. In Camel 2.0 we also support the
?method=methodname syntax that is used by the Bean component.
Camel 2.3: Lookup a property with the given key. The
locations option is optional. See more at Using
PropertyPlaceholder.
Camel 2.3: Returns the name of the current thread.
Can be used for logging purpose.
OGNL support
Available as of Camel 2.3
The Simple and Bean language now supports a Camel OGNL notation for invoking beans in a chain like fashion.
Suppose the Message IN body contains a POJO which has a getAddress() method.
Then you can use Camel OGNL notation to access the address object: simple( "${body.address}" ) simple( "${body.address.street}" ) simple( "${body.address.zip}" )
Camel understands the shorthand names for getters, but you can invoke any method or use the real name such as: simple( "${body.address}" ) simple( "${body.getAddress.getStreet}" ) simple( "${body.address.getZip}" ) simple( "${body.doSomething}" )
You can also use the null safe operator (?.) to avoid NPE if for example the body does NOT have an address
223 LANGUAGES SUPPORTED APPENDIX
simple( "${body?.address?.street}" )
Its also possible to index in Map or List types, so you can do: simple( "${body[foo].name}" )
To assume the body is Map based and lookup the value with foo as key, and invoke the getName method on that value.
Suppose there was no value with the key foo then you can use the null safe operator to avoid the NPE as shown: simple( "${body[foo]?.name}" )
You can also access List types, for example to get lines from the address you can do: simple( "${body.address.lines[0]}" ) simple( "${body.address.lines[1]}" ) simple( "${body.address.lines[2]}" )
There is a special last keyword which can be used to get the last value from a list.
simple( "${body.address.lines[last]}" )
And to get the 2nd last you can subtract a number, so we can use last-1 to indicate this: simple( "${body.address.lines[last-1]}" )
And the 3rd last is of course: simple( "${body.address.lines[last-2]}" )
And yes you can combine this with the operator support as shown below: simple( "${body.address.zip} > 1000" )
Operator support
Available as of Camel 2.0
We added a basic set of operators supported in the simple language in Camel 2.0. The parser is limited to only support a single operator.
To enable it the left value must be enclosed in ${ }. The syntax is:
LANGUAGES SUPPORTED APPENDIX 224
${leftValue} OP rightValue
>=
<
<=
!=
Where the rightValue can be a String literal enclosed in ' ', null, a constant value or another expression enclosed in ${ }.
Camel will automatically type convert the rightValue type to the leftValue type, so its able to eg.
convert a string into a numeric so you can use > comparison for numeric values.
The following operators is supported:
Operator Description
==
> equals greater than contains not contains greater than or equals less than less than or equals not equals
For testing if contains in a string based value
For testing if not contains in a string based value regex not regex in not in is not is range
For matching against a given regular expression pattern defined as a String value
For not matching against a given regular expression pattern defined as a String value
For matching if in a set of values, each element must be separated by comma.
For matching if not in a set of values, each element must be separated by comma.
For matching if the left hand side type is an instanceof the value.
For matching if the left hand side type is not an instanceof the value.
For matching if the left hand side is within a range of values defined as numbers: from..to
not range
For matching if the left hand side is not within a range of values defined as numbers: from..to
And the following operators can be used to group expressions:
Operator Description
and and is used to group two expressions
225 LANGUAGES SUPPORTED APPENDIX
or or is used to group two expressions
The syntax for AND is:
${leftValue} OP rightValue and ${leftValue} OP rightValue
And the syntax for OR is:
${leftValue} OP rightValue or ${leftValue} OP rightValue
Some examples: simple( "${in.header.foo} == 'foo'" )
// ' ' can be omitted simple( "${in.header.foo} == foo" )
// here Camel will type convert '100' into the type of in.header.bar and if its an
Integer '100' will also be converter to an Integer simple( "${in.header.bar} == '100'" ) simple( "${in.header.bar} == 100" )
// 100 will be converter to the type of in.header.bar so we can do > comparison simple( "${in.header.bar} > 100" )
// testing for null simple( "${in.header.baz} == null " )
// testing for not null simple( "${in.header.baz} != null " )
And a bit more advanced example where the right value is another expression simple( "${in.header.date} == ${date:now:yyyyMMdd}" ) simple( "${in.header.type} == ${bean:orderService?method=getOrderType}" )
And an example with contains, testing if the title contains the word Camel simple( "${in.header.title} contains 'Camel'" )
And an example with regex, testing if the number header is a 4 digit value: simple( "${in.header.number} regex '\d{4}'" )
LANGUAGES SUPPORTED APPENDIX 226
Using and,or operators
In
Camel 2.4 or older the and or or can only be used once in a simple
language expression. From
Camel 2.5 onwards you can use these operators
multiple times.
Comparing with different types
When you compare with different types such as String and int, then you have to take a bit care. Camel will use the type from the left hand side as 1st priority. And fallback to the right hand side type if both values couldn't be compared based on that type.
This means you can flip the values to enforce a specific type. Suppose the bar value above is a String. Then you can flip the equation: simple( "100 < ${in.header.bar}" ) which then ensures the int type is used as 1st priority.
This may change in the future if the Camel team improves and let the binary comparision operations be smarter and prefer numeric types over String based. It's most often the String type which causes problem when comparing with numbers.
And finally an example if the header equals any of the values in the list. Each element must be separated by comma, and no space around.
This also works for numbers etc, as Camel will convert each element into the type of the left hand side.
simple( "${in.header.type} in 'gold,silver'" )
And for all the last 3 we also support the negate test using not: simple( "${in.header.type} not in 'gold,silver'" )
And you can test for if the type is a certain instance, eg for instance a String simple( "${in.header.type} is 'java.lang.
String '" )
We have added a shorthand for all java.lang types so you can write it as:
227 LANGUAGES SUPPORTED APPENDIX
simple( "${in.header.type} is String " )
Ranges is also supported. The range interval requires numbers and both from and end is inclusive. For instance to test whether a value is between 100 and 199: simple( "${in.header.number} range 100..199" )
Notice we use .. in the range without spaces. Its based on the same syntax as Groovy.
Using and / or
If you have two expressions you can combine them with the and or or operator.
For instance: simple( "${in.header.title} contains 'Camel' and ${in.header.type'} == 'gold'" )
And of course the or is also supported. The sample example would be: simple( "${in.header.title} contains 'Camel' or ${in.header.type'} == 'gold'" )
Notice: Currently and or or can only be used once in a simple language expression. This
might change in the future.
So you
cannot do:
simple( "${in.header.title} contains 'Camel' and ${in.header.type'} == 'gold' and
${in.header.number} range 100..200" )
Samples
In the Spring XML sample below we filter based on a header value:
<from uri= "seda:orders" >
<filter>
<simple> in.header.foo
</simple>
<to uri= "mock:fooOrders" />
</filter>
</from>
The Simple language can be used for the predicate test above in the Message Filter pattern, where we test if the in message has a foo header (a header with the key foo exists). If the
LANGUAGES SUPPORTED APPENDIX 228
Can be used in Spring XML
As the Spring XML does not have all the power as the Java DSL with all its various builder methods, you had to resort to use some other languages for testing with simple operators. Now you can do this with the simple language. In the sample below we want to test if the header is a widget order:
<from uri= "seda:orders" >
<filter>
<simple> ${in.header.type} == 'widget' </simple>
<to uri= "bean:orderService?method=handleWidget" />
</filter>
</from> expression evaluates to
true then the message is routed to the mock:foo endpoint,
otherwise its lost in the deep blue sea .
The same example in Java DSL: from( "seda:orders" )
.filter().simple( "in.header.foo" ).to( "seda:fooOrders" );
You can also use the simple language for simple text concatenations such as: from( "direct:hello" ).transform().simple( "Hello ${in.header.user} how are you?" ).to( "mock:reply" );
Notice that we must use ${ } placeholders in the expression now to let Camel be able to parse it correctly.
And this sample uses the date command to output current date.
from( "direct:hello" ).transform().simple( "The today is ${date:now:yyyyMMdd} and its a great day." ).to( "mock:reply" );
And in the sample below we invoke the bean language to invoke a method on a bean to be included in the returned string: from( "direct:order" ).transform().simple( "OrderId:
${bean:orderIdGenerator}" ).to( "mock:reply" );
Where orderIdGenerator is the id of the bean registered in the Registry. If using Spring then its the Spring bean id.
229 LANGUAGES SUPPORTED APPENDIX
If we want to declare which method to invoke on the order id generator bean we must prepend .method name such as below where we invoke the generateId method.
from( "direct:order" ).transform().simple( "OrderId:
${bean:orderIdGenerator.generateId}" ).to( "mock:reply" );
And in Camel 2.0 we can use the ?method=methodname option that we are familiar with the Bean component itself: from( "direct:order" ).transform().simple( "OrderId:
${bean:orderIdGenerator?method=generateId}" ).to( "mock:reply" );
And from Camel 2.3 onwards you can also convert the body to a given type, for example to ensure its a String you can do:
<transform>
<simple> Hello ${bodyAs(String)} how are you?
</simple>
</transform>
There is a few types which have a shorthand notation, hence why we can use String instead of java.lang.String. These are: byte[], String, Integer, Long. All other types must use their FQN name, e.g. org.w3c.dom.Document.
Its also possible to lookup a value from a header Map in Camel 2.3 onwards:
<transform>
<simple> The gold value is ${header.type[gold]} </simple>
</transform>
In the code above we lookup the header with name type and regard it as a java.util.Map
and we then lookup with the key gold and return the value.
If the header is not convertible to Map an exception is thrown. If the header with name type does not exists null is returned.
Dependencies
The Simple language is part of
camel-core.
FILE EXPRESSION LANGUAGE
Available as of Camel 1.5
The File Expression Language is an extension to the Simple language, adding file related capabilities. These capabilities is related to common use cases working with file path and names.
LANGUAGES SUPPORTED APPENDIX 230
File language is now merged with Simple language
From Camel 2.2 onwards, the file language is now merged with Simple language which means you can use all the file syntax directly within the simple language.
The goal is to allow expression to be used with the File and FTP components for setting dynamic file patterns for both consumer and producer.
Syntax
This language is an
extension to the Simple language so the Simple syntax applies also. So the
table below only lists the additional.
As opposed to Simple language File Language also supports Constant expressions so you can enter a fixed filename.
All the file tokens uses the same expression name as the method on the java.io.File
object, for instance file:absolute refers to the java.io.File.getAbsolute() method. Notice that not all expressions is supported by the current Exchange. For instance the
FTP component supports some of the options, where as the File component support all of them.
Expression Type
File
Consumer
File
Producer
FTP
Consumer
FTP
Producer
Description
file:name file:name.ext
file:name.noext
file:onlyname file:onlyname.noext
file:ext file:parent file:path file:absolute file:absolute.path
file:length file:size file:modified
String
String
String
String
String
String
String
String
Boolean
String
Long
Long
Date yes yes yes yes yes yes yes yes yes yes yes yes yes no no no no no no no no no no no no no yes yes yes yes yes yes yes yes no no yes yes yes no no no no no no no no no no no no no refers to the file name (is relative to the starting directory, see note below)
Camel 2.3: refers to the file extension only refers to the file name with no extension
(is relative to the starting directory, see note below)
Camel 2.0: refers to the file name only with no leading paths.
Camel 2.0: refers to the file name only with no extension and with no leading paths.
Camel 1.6.1/Camel 2.0: refers to the file extension only refers to the file parent refers to the file path
Camel 2.0: refers to whether the file is regarded as absolute or relative refers to the absolute file path refers to the file length returned as a Long type
Camel 2.5: refers to the file length returned as a Long type
Camel 2.0: refers to the file last modified returned as a Date type
231 LANGUAGES SUPPORTED APPENDIX
date:command:pattern String yes yes yes yes for date formatting using the java.text.SimepleDataFormat
patterns. Is an extension to the Simple language. Additional command is:
file
(consumers only) for the last modified timestamp of the file. Notice: all the commands from the Simple language can also be used.
File token example
Relative paths
We have a java.io.File handle for the file hello.txt in the following relative directory: .\filelanguage\test. And we configure out endpoint to use this starting directory .\filelanguage. The the file tokens will return as:
Expression Returns
file:name file:name.ext
test\hello.txt
txt file:name.noext
file:onlyname test\hello hello.txt
file:onlyname.noext
hello file:ext txt file:parent file:path file:absolute file:absolute.path
filelanguage\test filelanguage\test\hello.txt
false
\workspace\camel\camel-core\target\filelanguage\test\hello.txt
Absolute paths
We have a java.io.File handle for the file hello.txt in the following absolute directory: \workspace\camel\camel-core\target\filelanguage\test. And we configure out endpoint to use the absolute starting directory
\workspace\camel\camel-core\target\filelanguage. The the file tokens will return as:
Expression Returns
file:name test\hello.txt
LANGUAGES SUPPORTED APPENDIX 232
file:name.ext
file:name.noext
txt test\hello file:onlyname hello.txt
file:onlyname.noext
hello file:ext file:parent file:path file:absolute file:absolute.path
txt
\workspace\camel\camel-core\target\filelanguage\test
\workspace\camel\camel-core\target\filelanguage\test\hello.txt
true
\workspace\camel\camel-core\target\filelanguage\test\hello.txt
Samples
You can enter a fixed Constant expression such as myfile.txt: fileName= "myfile.txt"
Lets assume we use the file consumer to read files and want to move the read files to backup folder with the current date as a sub folder. This can be archived using an expression like: fileName= "backup/${date:now:yyyyMMdd}/${file:name.noext}.bak" relative folder names is also supported so suppose the backup folder should be a sibling folder then you can append .. as: fileName= "../backup/${date:now:yyyyMMdd}/${file:name.noext}.bak"
As this is an extension to the Simple language we have access to all the goodies from this language also, so in this use case we want to use the in.header.type as a parameter in the dynamic expression: fileName= "../backup/${date:now:yyyyMMdd}/type-${in.header.type}/ backup-of-${file:name.noext}.bak"
If you have a custom Date you want to use in the expression then Camel supports retrieving dates from the message header.
fileName= "orders/ order-${in.header.customerId}-${date:in.header.orderDate:yyyyMMdd}.xml"
233 LANGUAGES SUPPORTED APPENDIX
And finally we can also use a bean expression to invoke a POJO class that generates some
String output (or convertible to String) to be used: fileName= "uniquefile-${bean:myguidgenerator.generateid}.txt"
And of course all this can be combined in one expression where you can use the File Language,
Simple and the Bean language in one combined expression. This is pretty powerful for those common file path patterns.
Using Spring PropertyPlaceholderConfigurer together with the File component
In Camel you can use the File Language directly from the Simple language which makes a
Content Based Router more easy to do in Spring XML, where we can route based on file extensions as shown below:
<from uri= "file://input/orders" />
<choice>
<when>
<simple> ${file:ext} == 'txt' </simple>
<to uri= "bean:orderService?method=handleTextFiles" />
</when>
<when>
<simple> ${file:ext} == 'xml' </simple>
<to uri= "bean:orderService?method=handleXmlFiles" />
</when>
<otherwise>
<to uri= "bean:orderService?method=handleOtherFiles" />
</otherwise>
</choice>
If you use the fileName option on the File endpoint to set a dynamic filename using the File
Language then make sure you use the alternative syntax (available from Camel 2.5 onwards) to avoid clash with Springs
PropertyPlaceholderConfigurer.
<bean id= "propertyPlaceholder" class= "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name= "location" value= "classpath:bundle-context.cfg" />
</bean>
<bean id= "sampleRoute" class= "SampleRoute" >
<property name= "fromEndpoint" value= "${fromEndpoint}" />
<property name= "toEndpoint" value= "${toEndpoint}" />
</bean>
LANGUAGES SUPPORTED APPENDIX 234
fromEndpoint=activemq:queue:test toEndpoint=file: //fileRoute/out?fileName=test-$simple{date:now:yyyyMMdd}.txt
Notice how we use the $simple{ } syntax in the toEndpoint above.
If you don't do this, there is a class and Spring will thrown an exception like org.springframework.beans.factory.BeanDefinitionStoreException:
Invalid bean definition with name 'sampleRoute' defined in class path resource
[bundle-context.xml]:
Could not resolve placeholder 'date:now:yyyyMMdd'
Dependencies
The File language is part of
camel-core.
SQL
The SQL support is added by JoSQL and is primarily used for performing SQL queries on inmemory objects. If you prefer to perform actual database queries then check out the JPA component.
To use SQL in your camel routes you need to add the a dependency on
camel-josql
which implements the SQL language.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId> org.apache.camel
</groupId>
<artifactId> camel-josql </artifactId>
<version> 2.5.0
</version>
</dependency>
Camel supports SQL to allow an Expression or Predicate to be used in the DSL or Xml
Configuration. For example you could use SQL to create an Predicate in a Message Filter or as an Expression for a Recipient List.
from( "queue:foo" ).setBody().sql( "select * from MyType" ).to( "queue:bar" )
And the spring DSL:
<from uri= "queue:foo" />
<setBody>
<sql> select * from MyType </sql>
235 LANGUAGES SUPPORTED APPENDIX
</setBody>
<to uri= "queue:bar" />
Variables
Variable
exchange in out
Type
the property key
Object the header key Object
Description
Exchange the Exchange object
Message the exchange.in message
Message the exchange.out message the Exchange properties the variable key Object the exchange.in headers if any additional variables is added using setVariables method
XPATH
Camel supports XPath to allow an Expression or Predicate to be used in the DSL or Xml
Configuration. For example you could use XPath to create an Predicate in a Message Filter or as an Expression for a Recipient List.
from( "queue:foo" ).
filter().xpath( " //foo" )).
to( "queue:bar" ) from( "queue:foo" ).
choice().xpath( " //foo" )).to("queue:bar").
otherwise().to( "queue:others" );
Namespaces
In 1.3 onwards you can easily use namespaces with XPath expressions using the Namespaces helper class.
Namespaces ns = new Namespaces( "c" , "http: //acme.com/cheese" ); from( "direct:start" ).filter().
LANGUAGES SUPPORTED APPENDIX 236
xpath( "/c:person[@name='James']" , ns).
to( "mock:result" );
Variables
Variables in XPath is defined in different namespaces. The default namespace is http://camel.apache.org/schema/spring.
Namespace URI
Local part
Type Description
http://camel.apache.org/xml/in/ http://camel.apache.org/xml/out/ in out
Message
Message the exchange.in
message the exchange.out
message http://camel.apache.org/xml/functions/ functions Object
Object
Camel 2.5: Additional
functions
OS environment variables http://camel.apache.org/xml/variables/ environment-variables http://camel.apache.org/xml/variables/ system-properties env system http://camel.apache.org/xml/variables/ exchange-property
Camel will resolve variables according to either:
▪ namespace given
▪ no namespace given
Object
Object
Java System properties the exchange property
Namespace given
If the namespace is given then Camel is instructed exactly what to return. However when resolving either
in or out Camel will try to resolve a header with the given local part first, and
return it. If the local part has the value
body then the body is returned instead.
No namespace given
If there is no namespace given then Camel resolves only based on the local part. Camel will try to resolve a variable in the following steps:
▪ from variables that has been set using the variable(name, value) fluent builder
237 LANGUAGES SUPPORTED APPENDIX
▪ from message.in.header if there is a header with the given key
▪ from exchange.properties if there is a property with the given key
Functions
Camel adds the following XPath functions that can be used to access the exchange:
Function Argument Type Description
in:body Object Will return the
in message body.
in:header out:body none the header name none
Object
Object
Will return the
Will return the
in message header.
out message body.
out:header the header name
Object Will return the
out message header.
function:properties key for property
String
Camel 2.5: To lookup a property using the
Properties component (property placeholders).
function:simple simple expression
Object
Camel 2.5: To evaluate a Simple
expression.
Here's an example showing some of these functions in use.
from( "direct:start" ).choice()
.when().xpath( "in:header('foo') = 'bar'" ).to( "mock:x" )
.when().xpath( "in:body() = '<two/>'" ).to( "mock:y" )
.otherwise().to( "mock:z" );
And the new functions introduced in Camel 2.5:
// setup properties component
PropertiesComponent properties = new PropertiesComponent(); properties.setLocation( "classpath:org/apache/camel/builder/xml/myprop.properties" ); context.addComponent( "properties" , properties);
// myprop.properties contains the following properties
// foo=Camel
// bar=Kong from( "direct:in" ).choice()
// $type is a variable for the header with key type
// here we use the properties function to lookup foo from the properties files
// which at runtime will be evaluted to 'Camel'
.when().xpath( "$type = function:properties('foo')" )
.to( "mock:camel" )
// here we use the simple language to evaluate the expression
LANGUAGES SUPPORTED APPENDIX 238
// which at runtime will be evaluated to 'Donkey Kong'
.when().xpath( " //name = function:simple('Donkey ${properties:bar}')" )
.to( "mock:donkey" )
.otherwise()
.to( "mock:other" )
.end();
Using XML configuration
If you prefer to configure your routes in your Spring XML file then you can use XPath expressions as follows
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/ schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/ camel-spring.xsd">
<camelContext id= "camel" xmlns= "http://activemq.apache.org/camel/schema/spring"
xmlns:foo= "http://example.com/person" >
<route>
<from uri= "activemq:MyQueue" />
<filter>
<xpath> /foo:person[@name='James'] </xpath>
<to uri= "mqseries:SomeOtherQueue" />
</filter>
</route>
</camelContext>
</beans>
Notice how we can reuse the namespace prefixes,
foo in this case, in the XPath expression for
easier namespace based XPath expressions!
See also this discussion on the mailinglist about using your own namespaces with xpath
Setting result type
The XPath expression will return a result type using native XML objects such as org.w3c.dom.NodeList. But many times you want a result type to be a String. To do this you have to instruct the XPath which result type to use.
In Java DSL: xpath( "/foo:person/@id" , String .class)
In Spring DSL you use the
resultType attribute to provide a fully qualified classname:
239 LANGUAGES SUPPORTED APPENDIX
<xpath resultType= "java.lang.String" > /foo:person/@id </xpath>
In @XPath:
Available as of Camel 2.1
@XPath(value = "concat('foo-', //order/name/)" , resultType = String .class) String name)
Where we use the xpath function concat to prefix the order name with foo-. In this case we have to specify that we want a String as result type so the concat function works.
Examples
Here is a simple example using an XPath expression as a predicate in a Message Filter from( "direct:start" ).
filter().xpath( "/person[@name='James']" ).
to( "mock:result" );
If you have a standard set of namespaces you wish to work with and wish to share them across many different XPath expressions you can use the NamespaceBuilder as shown in this example
// lets define the namespaces we'll need in our filters
Namespaces ns = new Namespaces( "c" , "http: //acme.com/cheese" )
.add( "xsd" , "http: //www.w3.org/2001/XMLSchema" );
// now lets create an xpath based Message Filter from( "direct:start" ).
filter(ns.xpath( "/c:person[@name='James']" )).
to( "mock:result" );
In this sample we have a choice construct. The first choice evaulates if the message has a header key
type that has the value Camel.
The 2nd choice evaluates if the message body has a name tag
<name> which values is Kong.
If neither is true the message is routed in the otherwise block: from( "direct:in" ).choice()
// using $headerName is special notation in Camel to get the header key
.when().xpath( "$type = 'Camel'" )
.to( "mock:camel" )
// here we test for the body name tag
.when().xpath( " //name = 'Kong'" )
.to( "mock:donkey" )
.otherwise()
.to( "mock:other" )
.end();
LANGUAGES SUPPORTED APPENDIX 240
And the spring XML equivalent of the route:
<camelContext xmlns= "http://camel.apache.org/schema/spring" >
<route>
<from uri= "direct:in" />
<choice>
<when>
<xpath> $type = 'Camel' </xpath>
<to uri= "mock:camel" />
</when>
<when>
<xpath> //name = 'Kong' </xpath>
<to uri= "mock:donkey" />
</when>
<otherwise>
<to uri= "mock:other" />
</otherwise>
</choice>
</route>
</camelContext>
XPATH INJECTION
You can use Bean Integration to invoke a method on a bean and use various languages such as
XPath to extract a value from the message and bind it to a method parameter.
The default XPath annotation has SOAP and XML namespaces available. If you want to use your own namespace URIs in an XPath expression you can use your own copy of the XPath annotation to create whatever namespace prefixes you want to use.
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.w3c.dom.NodeList; import org.apache.camel.component.bean.XPathAnnotationExpressionFactory; import org.apache.camel.language.LanguageAnnotation; import org.apache.camel.language.NamespacePrefix;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@LanguageAnnotation(language = "xpath" , factory =
XPathAnnotationExpressionFactory.class) public @ interface MyXPath {
String value();
// You can add the namespaces as the default value of the annotation
NamespacePrefix[] namespaces() default {
241 LANGUAGES SUPPORTED APPENDIX
}
@NamespacePrefix(prefix = "n1" , uri = "http: //example.org/ns1" ),
@NamespacePrefix(prefix = "n2" , uri = "http: //example.org/ns2" )};
Class <?> resultType() default NodeList.class; i.e. cut and paste upper code to your own project in a different package and/or annotation name then add whatever namespace prefix/uris you want in scope when you use your annotation on a method parameter. Then when you use your annotation on a method parameter all the namespaces you want will be available for use in your XPath expression.
NOTE this feature is supported from Camel 1.6.1.
For example public class Foo {
@MessageDriven(uri = "activemq:my.queue" ) public void doSomething(@Path( "/ns1:foo/ns2:bar/text()" ) String correlationID,
@Body String body) {
// process the inbound message here
}
}
Using XPathBuilder without an Exchange
Available as of Camel 2.3
You can now use the org.apache.camel.builder.XPathBuilder without the need for an Exchange. This comes handy if you want to use it as a helper to do custom xpath evaluations.
It requires that you pass in a CamelContext since a lot of the moving parts inside the
XPathBuilder requires access to the Camel Type Converter and hence why CamelContext is needed.
For example you can do something like this: boolean matches = XPathBuilder.xpath( "/foo/bar/@xyz" ).matches(context, "<foo><bar xyz='cheese'/></foo>" ));
This will match the given predicate.
You can also evaluate for example as shown in the following three examples:
String name = XPathBuilder.xpath( "foo/bar" ).evaluate(context,
"<foo><bar>cheese</bar></foo>" , String .class);
Integer number = XPathBuilder.xpath( "foo/bar" ).evaluate(context,
"<foo><bar>123</bar></foo>" , Integer .class);
LANGUAGES SUPPORTED APPENDIX 242
Boolean bool = XPathBuilder.xpath( "foo/bar" ).evaluate(context,
"<foo><bar> true </bar></foo>" , Boolean .class);
Evaluating with a String result is a common requirement and thus you can do it a bit simpler:
String name = XPathBuilder.xpath( "foo/bar" ).evaluate(context,
"<foo><bar>cheese</bar></foo>" );
Using Saxon with XPathBuilder
Available as of Camel 2.3
You need to add
camel-saxon as dependency to your project.
Its now easier to use Saxon with the XPathBuilder which can be done in several ways as shown below.
Where as the latter ones are the easiest ones.
Using a factory
// create a Saxon factory
XPathFactory fac = new net.sf.saxon.xpath.XPathFactoryImpl();
// create a builder to evaluate the xpath using the saxon factory
XPathBuilder builder = XPathBuilder.xpath( "tokenize(/foo/bar, '_')[2]" ).factory(fac);
// evaluate as a String result
String result = builder.evaluate(context, "<foo><bar>abc_def_ghi</bar></foo>" ); assertEquals( "def" , result);
Using ObjectModel
// create a builder to evaluate the xpath using saxon based on its object model uri
XPathBuilder builder = XPathBuilder.xpath( "tokenize(/foo/bar,
'_')[2]" ).objectModel( "http: //saxon.sf.net/jaxp/xpath/om" );
// evaluate as a String result
String result = builder.evaluate(context, "<foo><bar>abc_def_ghi</bar></foo>" ); assertEquals( "def" , result);
The easy one
// create a builder to evaluate the xpath using saxon
XPathBuilder builder = XPathBuilder.xpath( "tokenize(/foo/bar, '_')[2]" ).saxon();
// evaluate as a String result
String result = builder.evaluate(context, "<foo><bar>abc_def_ghi</bar></foo>" ); assertEquals( "def" , result);
243 LANGUAGES SUPPORTED APPENDIX
Setting a custom XPathFactory using System Property
Available as of Camel 2.3
Camel now supports reading the JVM system property javax.xml.xpath.XPathFactory that can be used to set a custom XPathFactory to use.
This unit test shows how this can be done to use Saxon instead:
// set system property with the XPath factory to use which is Saxon
System .setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":" + "http: //saxon.sf.net/ jaxp/xpath/om" , "net.sf.saxon.xpath.XPathFactoryImpl");
// create a builder to evaluate the xpath using saxon
XPathBuilder builder = XPathBuilder.xpath( "tokenize(/foo/bar, '_')[2]" );
// evaluate as a String result
String result = builder.evaluate(context, "<foo><bar>abc_def_ghi</bar></foo>" ); assertEquals( "def" , result);
Camel will log at INFO level if it uses a non default XPathFactory such as:
XPathBuilder INFO Using system property javax.xml.xpath.XPathFactory:http: //saxon.sf.net/jaxp/xpath/om with value: net.sf.saxon.xpath.XPathFactoryImpl when creating XPathFactory
Dependencies
The XPath language is part of camel-core.
XQUERY
Camel supports XQuery to allow an Expression or Predicate to be used in the DSL or Xml
Configuration. For example you could use XQuery to create an Predicate in a Message Filter or as an Expression for a Recipient List.
from( "queue:foo" ).filter().
xquery( " //foo" ).
to( "queue:bar" )
You can also use functions inside your query, in which case you need an explicit type conversion (or you will get a org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR) by passing the Class as a second argument to the
xquery() method.
LANGUAGES SUPPORTED APPENDIX 244
from( "direct:start" ).
recipientList().xquery( "concat('mock:foo.', /person/@city)" , String .class);
Variables
The IN message body will be set as the contextItem. Besides this these Variables is also added as parameters:
Variable Type Description
Support version
exchange in.body
out.body
Exchange
Object
Object
The current Exchange
The In message's body >= 1.6.1
>= 1.6.1
in.headers.* Object
The OUT message's body (if any)
You can access the value of exchange.in.headers
with key
foo by using the variable which name is
in.headers.foo
>=1.6.1
out.headers.*
key name
Object
Object
You can access the value of exchange.out.headers
with key
foo by using the variable which name is
out.headers.foo variable
Any exchange.properties and exchange.in.headers
(exchange.in.headers support was removed since camel 1.6.1) and any additional parameters set using setParameters(Map). These parameters is added with they own key name, for instance if there is an IN header with the key name
foo then
its added as
foo.
>=1.6.1
Using XML configuration
If you prefer to configure your routes in your Spring XML file then you can use XPath expressions as follows
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo= "http://example.com/person" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/ schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/ camel-spring.xsd">
245 LANGUAGES SUPPORTED APPENDIX
<camelContext id= "camel" xmlns= "http://activemq.apache.org/camel/schema/spring" >
<route>
<from uri= "activemq:MyQueue" />
<filter>
<xquery> /foo:person[@name='James'] </xquery>
<to uri= "mqseries:SomeOtherQueue" />
</filter>
</route>
</camelContext>
</beans>
Notice how we can reuse the namespace prefixes,
foo in this case, in the XPath expression for
easier namespace based XQuery expressions!
When you use functions in your XQuery expression you need an explicit type conversion which is done in the xml configuration via the
@type attribute:
<xquery type= "java.lang.String" > concat('mock:foo.', /person/@city) </xquery>
Using XQuery as an endpoint
Sometimes an XQuery expression can be quite large; it can essentally be used for Templating.
So you may want to use an XQuery Endpoint so you can route using XQuery templates.
The following example shows how to take a message of an ActiveMQ queue (MyQueue) and transform it using XQuery and send it to MQSeries.
<camelContext id= "camel" xmlns= "http: //camel.apache.org/schema/spring" >
<route>
<from uri= "activemq:MyQueue" />
<to uri= "xquery:com/acme/someTransform.xquery" />
<to uri= "mqseries:SomeOtherQueue" />
</route>
</camelContext>
Examples
Here is a simple example using an XQuery expression as a predicate in a Message Filter from( "direct:start" ).filter().xquery( "/person[@name='James']" ).to( "mock:result" );
This example uses XQuery with namespaces as a predicate in a Message Filter
LANGUAGES SUPPORTED APPENDIX 246
Namespaces ns = new Namespaces( "c" , "http: //acme.com/cheese" ); from( "direct:start" ).
filter().xquery( "/c:person[@name='James']" , ns).
to( "mock:result" );
Learning XQuery
XQuery is a very powerful language for querying, searching, sorting and returning XML. For help learning XQuery try these tutorials
• Mike Kay's XQuery Primer
• the W3Schools XQuery Tutorial
You might also find the XQuery function reference useful
Dependencies
To use XQuery in your camel routes you need to add the a dependency on
camel-saxon
which implements the XQuery language.
If you use maven you could just add the following to your pom.xml, substituting the version number for the latest & greatest release (see the download page for the latest versions).
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-saxon</artifactId>
<version>1.4.0</version>
</dependency>
247 LANGUAGES SUPPORTED APPENDIX
Download
Advertisement
Key features
Enterprise Integration Patterns implementation
Bean Integration
Java DSL
Spring XML Configuration
Scala DSL
URI-based endpoint configuration
Frequently asked questions
Apache Camel is an open-source integration framework based on Enterprise Integration Patterns with Bean Integration.
You can use a Java based Domain Specific Language (DSL), Spring based Xml Configuration files or via the Scala DSL.
HTTP, ActiveMQ, JMS, JBI, SCA, MINA or CXF Bus API together with working with pluggable Data Format options.