The simple language is a language that was developed in Apache Camel specifically for the purpose of accessing and manipulating the various parts of an exchange object. The language is not quite as simple as when it was originally created and it now features a comprehensive set of logical operators and conjunctions.
Table of Contents
In the Java DSL, there are two styles for using the simple() command
in a route. You can either pass the simple() command as an argument to
a processor, as follows:
from("seda:order")
.filter(simple("${in.header.foo}"))
.to("mock:fooOrders");Or you can call the simple() command as a sub-clause on the
processor, for example:
from("seda:order")
.filter()
.simple("${in.header.foo}")
.to("mock:fooOrders");If you are embedding a simple expression inside a plain text string, you must use
the placeholder syntax, ${Expression}. For
example, to embed the in.header.name expression in a string:
simple("Hello ${in.header.name}, how are you?")From Java, you can customize the start and end tokens ({ and
}, by default) by calling the changeFunctionStartToken
static method and the changeFunctionEndToken static method on the
SimpleLanguage object.
For example, you can change the start and end tokens to [ and
] in Java, as follows:
// Java
import org.apache.camel.language.simple.SimpleLanguage;
...
SimpleLanguage.changeFunctionStartToken("[");
SimpleLanguage.changeFunctionEndToken("]");![]() | Note |
|---|---|
Customizing the start and end tokens affects all Apache Camel applications that
share the same |
In the XML DSL, you can use a simple expression by putting the expression inside a
simple element. For example, to define a route that performs
filtering based on the contents of the foo header:
<route id="simpleExample">
<from uri="seda:orders"/>
<filter>
<simple>${in.header.foo}</simple>
<to uri="mock:fooOrders"/>
</filter>
</route>Sometimes — for example, if you have enabled Spring property placeholders or
OSGi blueprint property placeholders — you might find that the
${Expression} syntax clashes with
another property placeholder syntax. In this case, you can disambiguate the
placeholder using the alternative syntax,
$simple{Expression}, for the simple
expression. For example:
<simple>Hello $simple{in.header.name}, how are you?</simple>From XML configuration, you can customize the start and end tokens ({
and }, by default) by overriding the SimpleLanguage
instance. For example, to change the start and end tokens to [ and
], define a new SimpleLanguage bean in your XML
configuration file, as follows:
<bean id="simple" class="org.apache.camel.language.simple.SimpleLanguage"> <constructor-arg name="functionStartToken" value="["/> <constructor-arg name="functionEndToken" value="]"/> </bean>
![]() | Note |
|---|---|
Customizing the start and end tokens affects all Apache Camel applications that
share the same |
By default, whitespace preceding and following a simple expression is automatically trimmed in XML DSL. So this expression with surrounding whitespace:
<transform>
<simple>
data=${body}
</simple>
</transform>is automatically trimmed, so that it is equivalent to this expression (no surrounding whitespace):
<transform>
<simple>data=${body}</simple>
</transform>If you want to include newlines before or after the expression, you can either explicitly add a newline character, as follows:
<transform>
<simple>data=${body}\n</simple>
</transform>or you can switch off auto-trimming, by setting the trim attribute to
false, as follows:
<transform trim="false">
<simple>data=${body}
</simple>
</transform>It is possible to execute Simple scripts that are stored in an external resource, as described here.
Use the following syntax to access a Simple script that is stored as an external resource:
resource:Scheme:Location
Where the Scheme: can be either
classpath:, file:, or http:.
For example, to read the mysimple.txt script from the classpath,
simple("resource:classpath:mysimple.txt")The simple language provides various elementary expressions that return different
parts of a message exchange. For example, the expression,
simple("${header.timeOfDay}"), would return the contents of a
header called timeOfDay from the incoming message.
![]() | Note |
|---|---|
Since Apache Camel 2.9, you must always use the placeholder
syntax, |
You can use the simple language to define string expressions, based on the
variables provided. For example, you can use a variable of the form,
in.header.HeaderName, to obtain the
value of the HeaderName header, as follows:
simple("${in.header.foo}")You can embed simple variables in a string expression — for example:
simple("Received a message from ${in.header.user} on ${date:in.header.date:yyyyMMdd}.")As well as providing variables that access all of the different parts of an
exchange (see Table 15, “Variables for the Simple Language”), the simple language also
provides special variables for formatting dates,
date:command:pattern,
and for calling bean methods, bean:beanRef.
For example, you can use the date and the bean variables as follows:
simple("Todays date is ${date:now:yyyyMMdd}")
simple("The order type is ${bean:orderService?method=getOrderType}")You can specify the result type of an expression explicitly. This is mainly useful for converting the result type to a boolean or numerical type.
In the Java DSL, specify the result type as an extra argument to
simple(). For example, to return an integer result, you could
evaluate a simple expression as follows:
...
.setHeader("five", simple("5", Integer.class))In the XML DSL, specify the result type using the resultType
attribute. For example:
<setHeader headerName="five">
<!-- use resultType to indicate that the type should be a java.lang.Integer -->
<simple resultType="java.lang.Integer">5</simple>
</setHeader>From Camel 2.17, the setHeaderand setExchange properties allows to use a dynamic header key using the Simple language, if the name of the key is a Simple language expression.
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<setHeader headerName="$simple{type:org.apache.camel.spring.processor.SpringSetPropertyNameDynamicTest$TestConstans.EXCHANGE_PROP_TX_FAILED}">
<simple>${type:java.lang.Boolean.TRUE}</simple>
</setHeader>
<to uri="mock:end"/>
</route>
</camelContext>Simple expressions can be nested — for example:
simple("${header.${bean:headerChooser?method=whichHeader}}")You can access a bean’s constant or enum fields using the following syntax:
type:ClassName.Field
For example, consider the following Java enum type:
package org.apache.camel.processor;
...
public enum Customer {
GOLD, SILVER, BRONZE
}You can access the Customer enum fields, as follows:
from("direct:start")
.choice()
.when().simple("${header.customer} ==
${type:org.apache.camel.processor.Customer.GOLD}")
.to("mock:gold")
.when().simple("${header.customer} ==
${type:org.apache.camel.processor.Customer.SILVER}")
.to("mock:silver")
.otherwise()
.to("mock:other");The Object Graph Navigation
Language (OGNL) is a notation for invoking bean methods in a chain-like
fashion. If a message body contains a Java bean, you can easily access its bean
properties using OGNL notation. For example, if the message body is a Java object
with a getAddress() accessor, you can access the Address
object and the Address object’s properties as follows:
simple("${body.address}")
simple("${body.address.street}")
simple("${body.address.zip}")
simple("${body.address.city}")Where the notation, ${body.address.street}, is shorthand for
${body.getAddress.getStreet}.
You can use the null-safe operator, ?., to avoid encountering
null-pointer exceptions, in case the body does not have an
address. For example:
simple("${body?.address?.street}")If the body is a java.util.Map type, you can look up a value in the
map with the key, foo, using the following notation:
simple("${body[foo]?.name}")You can also use square brackets notation, [k], to access the
elements of a list. For example:
simple("${body.address.lines[0]}")
simple("${body.address.lines[1]}")
simple("${body.address.lines[2]}")The last keyword returns the index of the last element of a list. For
example, you can access the second last element of a list, as
follows:
simple("${body.address.lines[last-1]}")You can use the size method to query the size of a list, as
follows:
simple("${body.address.lines.size}")You can construct predicates by testing expressions for equality. For example, the
predicate, simple("${header.timeOfDay} == '14:30'"), tests
whether the timeOfDay header in the incoming message is equal to
14:30.
In addition, whenever the resultType is specified as a Boolean the
expression is evaluated as a predicate instead of an expression. This allows
the predicate syntax to be used for these expressions.
You can also test various parts of an exchange (headers, message body, and so on) using simple predicates. Simple predicates have the following general syntax:
${LHSVariable} Op RHSValueWhere the variable on the left hand side, LHSVariable, is one of the variables shown in Table 15, “Variables for the Simple Language” and the value on the right hand side, RHSValue, is one of the following:
${RHSVariable}.' '.' '.null.The simple language always attempts to convert the RHS value to the type of the LHS value.
![]() | Note |
|---|---|
While the simple language will attempt to convert the RHS, depending on the operator the LHS may need to be cast into the appropriate Type before the comparison is made. |
For example, you can perform simple string comparisons and numerical comparisons as follows:
simple("${in.header.user} == 'john'")
simple("${in.header.number} > '100'") // String literal can be converted to integerYou can test whether the left hand side is a member of a comma-separated list, as follows:
simple("${in.header.type} in 'gold,silver'")You can test whether the left hand side matches a regular expression, as follows:
simple("${in.header.number} regex '\d{4}'")You can test the type of the left hand side using the is operator, as
follows:
simple("${in.header.type} is 'java.lang.String'")
simple("${in.header.type} is 'String'") // You can abbreviate java.lang. typesYou can test whether the left hand side lies in a specified numerical range (where the range is inclusive), as follows:
simple("${in.header.number} range '100..199'")You can also combine predicates using the logical conjunctions,
&& and ||.
For example, here is an expression using the && conjunction
(logical and):
simple("${in.header.title} contains 'Camel' && ${in.header.type} == 'gold'")And here is an expression using the || conjunction (logical inclusive
or):
simple("${in.header.title} contains 'Camel' || ${in.header.type} == 'gold'")Table 15, “Variables for the Simple Language” shows all of the variables supported by the simple language.
Table 15. Variables for the Simple Language
| Variable | Type | Description |
|---|---|---|
|
| The Camel context. Supports OGNL expressions. |
|
| The Camel context’s ID value. |
|
| The exchange’s ID value. |
|
| The In message ID value. |
|
| The In message body. Supports OGNL expressions. |
|
| The In message body. Supports OGNL expressions. |
|
| The Out message body. |
| Type | The In message body, converted to the
specified type. All types, Type, must be
specified using their fully-qualified Java name, except for the
types: |
| Type | The In message body, converted to the
specified type. All types, Type, must be
specified using their fully-qualified Java name, except for the
types: |
|
| The In message’s HeaderName header. Supports OGNL expressions. |
|
| The In message’s HeaderName header (alternative syntax). |
|
| The In message’s HeaderName header. |
|
| The In message’s HeaderName header (alternative syntax). |
|
| The In message’s HeaderName header. Supports OGNL expressions. |
|
| The In message’s HeaderName header (alternative syntax). |
|
| The In message’s HeaderName header. Supports OGNL expressions. |
|
| The In message’s HeaderName header (alternative syntax). |
|
| The Out message’s HeaderName header. |
|
| The Out message’s HeaderName header (alternative syntax). |
|
| The Out message’s HeaderName header. |
|
| The Out message’s HeaderName header (alternative syntax). |
| Type | The Key header, converted to the
specified type. All types, Type, must be
specified using their fully-qualified Java name, except for the
types: |
|
| All of the In headers (as a
|
|
| All of the In headers (as a
|
|
| The PropertyName property on the exchange. |
|
| The PropertyName property on the exchange (alternative syntax). |
|
| The SysPropertyName Java system property. |
|
| The SysEnvVar system environment variable. |
|
| Either the exception object from
|
|
| If an exception is set on the exchange, returns the value of
|
|
| If an exception is set on the exchange, returns the value of
|
|
| A date formatted using a java.text.SimpleDateFormat pattern. The following
commands are supported: |
|
| Invokes a method on the referenced bean and returns the
result of the method invocation. To specify a method
name, you can either use the
|
|
| Looks up the bean with the ID, beanID, in the registry and returns a reference to the bean itself. For example, if you are using the splitter EIP, you could use this variable to reference the bean that implements the splitting algorithm. |
|
| The value of the Key property placeholder . |
|
| The value of the Key property placeholder, where the location of the properties file is given by Location . |
|
| The name of the current thread. |
|
| Returns the ID of the current route through which the
|
|
| References a type or field by its Fully-Qualified-Name (FQN). To
refer to a field, append
|
|
| From Camel 2.17, the collate function iterates the message body and groups the data into the sub lists of specific size. You can use with the Splitter EIP to split a message body and group or batch the submessages into a group of N sublists. |
The binary operators for simple language predicates are shown in Table 16, “Binary Operators for the Simple Language”.
Table 16. Binary Operators for the Simple Language
| Operator | Description |
|---|---|
| Equals. |
| Equals ignore case. Ignore the case when comparing string values. |
| Greater than. |
| Greater than or equals. |
| Less than. |
| Less than or equals. |
| Not equal to. |
| Test if LHS string contains RHS string. |
| Test if LHS string does not contain RHS string. |
| Test if LHS string matches RHS regular expression. |
| Test if LHS string does not match RHS regular expression. |
| Test if LHS string appears in the RHS comma-separated list. |
| Test if LHS string does not appear in the RHS comma-separated list. |
| Test if LHS is an instance of RHS Java type (using Java
|
| Test if LHS is not an instance of RHS Java
type (using Java |
| Test if LHS number lies in the RHS range (where range has the
format,
|
| Test if LHS number does not lie in the RHS
range (where range has the format,
|
| New in Camel 2.18. Test if the LHS string starts with the RHS string. |
| New in Camel 2.18. Test if the LHS string ends with the RHS string. |
The binary operators for simple language predicates are shown in Table 17, “Unary Operators for the Simple Language”.
Table 17. Unary Operators for the Simple Language
| Operator | Description |
|---|---|
| Increment a number by 1. |
| Decrement a number by 1. |
| The newline character. |
| The carriage return character. |
| The tab character. |
| (Obsolete) Since Camel version 2.11, the backslash escape character is not supported. |
The conjunctions shown in Table 18, “Conjunctions for Simple Language Predicates” can be used to combine two or more simple language predicates.
Table 18. Conjunctions for Simple Language Predicates
| Operator | Description |
|---|---|
| Combine two predicates with logical and. |
| Combine two predicates with logical inclusive or. |
| Deprecated. Use |
| Deprecated. Use |