Simple - Built-in Operators
Built-in Operators
The simple language has limited support for operators that are used in predicates to evaluate whether a condition is either true or false.
Camel operators require the left value must be enclosed in ${ }. The syntax is:
${leftValue} OP rightValue Where the rightValue can be a string literal enclosed in ' ', null, a constant value or another expression enclosed in ${ }.
| There must be spaces around the operator. |
Camel will automatically type convert the rightValue type to the leftValue type, so it is able to e.g., convert a string into a numeric, so you can use > comparison for numeric values.
Comparison Operators
The following comparison operators are supported:
| Operator | Description |
|---|---|
| equals |
| equals ignore case (will ignore case when comparing String values) |
| greater than |
| greater than or equals |
| less than |
| less than or equals |
| not equals |
| not equals ignore case (will ignore case when comparing String values) |
| For testing if contains by ignoring case sensitivity in a string-based value |
| For testing if it does not contain by ignoring case sensitivity in a string-based value |
| For testing if contains in a string-based value |
| For testing if it does not contain in a string-based value |
| For testing if the left-hand side string ends with the right-hand string. |
| For testing if the left-hand side string does not end with the right-hand string. |
| For matching if in a set of values, each element must be separated by comma. If you want to include an empty value, then it must be defined using double comma, e.g. |
| For matching if not in a set of values, each element must be separated by comma. If you want to include an empty value, then it must be defined using double comma, e.g. |
| For matching if the left-hand side type is an instance of the value. |
| For matching if the left-hand side type is not an instance of the value. |
| For matching if the left-hand side is within a range of values defined as numbers: |
| For matching if the left-hand side is not within a range of values defined as numbers: |
| 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 testing if the left-hand side string starts with the right-hand string. |
| For testing if the left-hand side string does not start with the right-hand string. |
Numeric Operators
The following numeric operators can be used:
| Operator | Description |
|---|---|
| To increment a number by one. The left-hand side must be a function, otherwise parsed as literal. |
| To decrement a number by one. The left-hand side must be a function, otherwise parsed as literal. |
These operators are unary and requires to be attached directly next to a function:
${function}OP For example to increment the result of the function:
simple("${header.myNumber}++ > 10"); And the same for decrement:
simple("${header.myNumber}-- < 10"); Other Operators
The following other operators can be used:
| Operator | Description |
|---|---|
| The ternary operator evaluates a condition and returns a value based on the result. If the condition is true, the first value (after |
| The elvis operator returns the left-hand side if it has an effective Boolean value of true, otherwise it returns the right-hand side. This is useful for providing fallback values when an expression may evaluate to a value with an effective Boolean value of false (such as |
| The chain operator is used in the situations where multiple nested functions need to be applied to a value, while making it easy to read. The value on the left-hand-side is evaluated, and set as the new message body before evaluating the right-hand-side function. This concept is similar to the Pipeline EIP. |
| The null-safe chain operator, where the chain will not continue when a function returned |
Ternary Operator
The syntax for the ternary operator is:
${leftValue} OP rightValue ? trueValue : falseValue For example the following ternary operator will return positive if header foo is greater than 0, otherwise negative:
simple("${header.foo > 0 ? 'positive' : 'negative'}"); Ternary operators can also be nested to handle multiple conditions:
simple("${header.score >= 90 ? 'A' : ${header.score >= 80 ? 'B' : 'C'}}"); Elvis Operator
For example the following elvis operator will return the username header unless its null or empty, which then the default value of Guest is returned.
simple("${header.username} ?: 'Guest'"); Chain Operator
The syntax for the chain operator is:
${leftValue} ~> ${rightValue} And there can be as many chains:
${leftValue} ~> ${midValue} ~> ${midValue} ~> ${rightValue} For example if the message body contains Hello World then the follow would return WORLD:
simple("${substringAfter('Hello')} ~> ${trim()} ~> ${uppercase()}"); The null safe variant (?~>) can be used to avoid NullPointerException if it’s accepted to not continue the chain when any function returned null:
However, many of the simple functions have NPE protection built-in, so this variant is only needed in special situations.
Using $param as input parameter value
The chain operator will by default pass results via the message body. This usually works well with most functions. However, when you need to be in full control then use $param as the magic parameter which represents the passed value from the previous function in the chain. |
Suppose the message body contains " Hello World from the Camel " then the following chain works out of the box:
simple("${trim()} ~> ${replace('Hello','Hi')} ~> ${split(' ')} ~> ${size()}"); And here is the same example where we explicit use $param in the parameters where we need the input to be:
simple("${trim()} ~> ${replace('Hello','Hi',$param)} ~> ${split($param,' ')} ~> ${size($param)}"); Boolean Operators
And the following boolean operators can be used to group expressions:
| Operator | Description |
|---|---|
| The |
| The |
The syntax for AND is:
${leftValue} OP rightValue && ${leftValue} OP rightValue And the syntax for OR is:
${leftValue} OP rightValue || ${leftValue} OP rightValue Some examples:
// exact equals match
simple("${header.foo} == 'foo'")
// ignore case when comparing, so if the header has value FOO, this will match
simple("${header.foo} =~ 'foo'")
// here Camel will type convert '100' into the type of header.bar and if it is an Integer '100' will also be converter to an Integer
simple("${header.bar} == '100'")
simple("${header.bar} == 100")
// 100 will be converter to the type of header.bar, so we can do > comparison
simple("${header.bar} > 100")
// if the value of header.bar was 100, value returned will be 101. header.bar itself will not be changed.
simple("${header.bar}++") Using Operators with different Java Object types
When you compare with different types such as String and int, then you have to take a bit of care. Camel will use the type from the left-hand side as first 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 < ${header.bar}") which then ensures the int type is used as first priority.
This may change in the future if the Camel team improves the binary comparison operations to prefer numeric types to String-based. It’s most often the String type which causes problems when comparing with numbers.
// testing for null
simple("${header.baz} == null")
// testing for not null
simple("${header.baz} != null") And a bit more advanced example where the right value is another expression
simple("${header.date} == ${date:now:yyyyMMdd}")
simple("${header.type} == ${bean:orderService?method=getOrderType}") And an example with contains, testing if the title contains the word Camel
simple("${header.title} contains 'Camel'") And an example with regex, testing if the number header is a 4-digit value:
simple("${header.number} regex '\\d{4}'") 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("${header.type} in 'gold,silver'") And for all the last 3, we also support the negate test using not:
simple("${header.type} !in 'gold,silver'") And you can test if the type is a certain instance, e.g., for instance a String
simple("${header.type} is 'java.lang.String'") We have added a shorthand for all java.lang types, so you can write it as:
simple("${header.type} is 'String'") Ranges are also supported. The range interval requires numbers and both from and end are inclusive. For instance, to test whether a value is between 100 and 199:
simple("${header.number} range 100..199") Notice we use .. in the range without spaces. It is based on the same syntax as Groovy.
simple("${header.number} range '100..199'") As the XML DSL does not have all the power as the Java DSL with all its various builder methods, you have to resort to using 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 it if the header is a widget order:
<from uri="seda:orders">
<filter>
<simple>${header.type} == 'widget'</simple>
<to uri="bean:orderService?method=handleWidget"/>
</filter>
</from> Combining multiple expression using AND / OR Operator
If you have two expressions you can combine them with the && (and) or || (or) operator.
For instance:
simple("${header.title} contains 'Camel' && ${header.type} == 'gold'") And of course the || is also supported. The sample would be:
simple("${header.title} contains 'Camel' || ${header.type} == 'gold'")