A Simple, the expression language
Camel offers a powerful expression language, which back in the earlier days wasn’t as powerful and was labeled Simple. It has evolved to become much more since then, but don’t worry: it’s still simple to use.
The Simple language is provided out of the box in the camel-core JAR file, which means you don’t have to add any JARs on the classpath to use it.
highlight, annotate, and bookmark
You can automatically highlight by performing the text selection while keeping the alt/ key pressed.

A.1 Introducing Simple
In a nutshell, the Simple expression language evaluates an expression on the current instance of Exchange that is under processing. The Simple language can be used for both expressions and predicates, which makes it a perfect match to be used in your Camel routes.
For example, the Content-Based Router EIP can leverage the Simple language to define predicates in the when clauses, as shown here:
The equivalent Spring XML example would be as follows:
As you can see from the preceding examples, the Simple expression is understandable and similar to other scripting languages. In these examples, Camel will evaluate the expression as a Predicate, which means the result is a boolean, which is either true or false. In the example, you use operators to determine whether the message body contains the word Camel or whether the message header amount is larger than 1000.
That gives you a taste of the Simple language. Let’s look at its syntax.
discuss

A.2 Syntax
The Simple language uses ${ } placeholders for dynamic expressions, such as those in the previous examples. You can use multiple ${ } placeholders in the same expression, or even nest placeholders.
For example, these are valid Simple expressions:
An alternative syntax is available to accommodate a clash with Spring’s property placeholder feature. You can now also use $simple{ } placeholders with Simple, such as shown in this example:
These examples use variables such as body and header. The next section covers this.
settings

A.3 Built-in variables
The Simple language provides a number of variables that bind to information in the current Exchange. You’ve already seen the body and header. Table A.1 lists all the variables available.
Table A.1 Variables in the Simple language
Variable |
Type |
Description |
|
|
Contains the input message body |
|
|
Contains the output message body |
|
|
Contains the input message header XXX |
|
|
Contains the output message header |
|
|
Contains the exchange property XXX |
|
|
The input message headers |
|
|
The input message headers |
|
|
Contains the unique ID of the |
|
|
Contains the system environment |
|
|
Contains the exception on the |
|
|
Contains the exception |
|
|
Contains the exception message on the |
|
|
Contains the name of the current thread; can be used for logging purposes |
|
|
The CamelContext name. |
|
|
The current Exchange object. |
|
|
The ID of the route where this Exchange is currently being routed. |
|
|
Represents null. |
|
|
The message history of the current exchange. This shows how the message has been routed. |
|
|
The message history of the current exchange but without showing an of the Exchange content. Helpful if you don't want sensitive details showing up in the logs. |
|
|
Use a newline character. |
|
|
Use a tab character. |
|
|
Use a carriage return character. |
|
|
Use the '}' character, which is special for a simple expression of course. |
The variables can easily be used in a Simple expression, as you’ve already seen. Logging the message body can be done using ${body} as shown in the following route snippet:
The Simple language also has a set of built-in functions.
highlight, annotate, and bookmark
You can automatically highlight by performing the text selection while keeping the alt/ key pressed.

A.4 Built-in functions
The Simple language has four functions at your disposal, as listed in table A.2.
Table A.2 Functions provided in the Simple language
Function |
Type |
Description |
|
|
Converts the body to the given type. For example,
|
|
|
Converts the body to the given type and then invokes a method on the resulting object using OGNL notation. May return |
|
|
Converts the body to the given type. Will throw a |
|
|
Converts the body to the given type and then invokes a method on the resulting object using OGNL notation. Will throw a |
|
|
Converts the header with the given key to the given type. Will return |
|
|
Invokes a method on a bean. Camel will look up the bean with the given ID from the |
|
|
Formats a date. The command must be either The pattern is based on the |
|
|
Invoke a method on the CamelContent using Object Graph Navigation Language (OGNL) notation. You can see more about OGNL later in this appendix. |
|
|
Split a message body into sub lists of size sub_list_size. Actual result is an Iterator which points to the sub Lists. |
|
|
Invoke a method on the Exchange using OGNL notation. You can see more about OGNL later in this appendix. |
|
|
Get the exchange property XXX and then invoke a method on the resulting object using OGNL notation. |
|
|
Lookup and return bean with ID XXX. |
|
|
Resolves a property with the given key using the Camel Properties component. |
|
|
Resolves a property with the given key using the Camel Properties component. If the key doesn't exits or has no value, a specified default can be used. |
|
|
Returns a random number between 0 (included) and the specified max (excluded). |
|
|
Returns a random number between the specified min (included) and the specified max (excluded). |
|
|
Skip the specified number of items in the current message body and return the remainder.. |
|
|
Refers to a type or a field by its FQN. For example, ${type:org.apache.camel.Exchange.FILE_NAME} would refer to the constant Exchange.FILE_NAME field which would resolve to “CamelFileName”. |
For example, to log a formatted date from the message header, you could do as follows:
In this example, the input message is expected to contain a header with the key myDate, which should be of type java.util.Date.
Suppose you need to organize received messages into a directory structure containing the current day’s date as a parent folder. The file producer has direct support for specifying the target filename using the Simple language as shown in bold:
Now suppose the file must use a filename generated from a bean. You can use the bean function to achieve this:
In this example, Camel will look up the bean with the ID uuidBean from the Registry and invoke the generate method. The output of this method invocation is returned and used as the filename.
The Camel Properties component is used for property placeholders. For example, you could store a property in a file containing a configuration for a big-spender threshold.
Then you could refer to the big properties key from the Simple language:
The Simple language also has built-in variables when working with the Camel File and FTP components.
discuss

A.5 Built-in file variables
Files consumed using the File or FTP components have file-related variables available to the Simple language. Table A.3 lists those variables.
Table A.3 File-related variables available when consuming files
Variable |
Type |
Description |
|
|
Contains the filename (relative to the starting directory) |
|
|
Contains the file extension |
|
|
Contains the file extension whereby only the extension after the last dot is returned. So a “tar.gz” file would have an extension of “gz” |
|
|
Contains the filename without extension (relative to the starting directory) |
|
|
Contains the filename without extension (relative to the starting directory) whereby only the extension after the last dot is stripped. So a file named “my-dir/backup.tar.gz” would mean “my-dir/backup.tar” is returned. |
|
|
Contains the filename without any leading paths |
|
|
Contains the filename without extension and leading paths |
|
|
Contains the filename without extension and leading paths whereby only the extension after the last dot is stripped. So a file named “backup.tar.gz” would mean “backup.tar” is returned. |
|
|
Contains the file parent (the paths leading to the file) |
|
|
Contains the file path (including leading paths) |
|
|
Whether or not the filename is an absolute or relative file path |
|
|
Contains the absolute file path. |
|
|
Contains the file length |
|
|
Contains the modification date of the file as a |
Among other things, the file variables can be used to log which file has been consumed:
The File and FTP endpoints have options that accept Simple language expressions. For example, the File consumer can be configured to move processed files into a folder you specify. Suppose you must move files into a directory structure organized by dates. This can be done by specifying the expression in the move option, as follows:
Tip
The FTP endpoint supports the same move option as shown here.
Another example where the file variables come in handy is if you have to process files differently based on the file extension. For example, suppose you have CSV and XML files:
Note
You can read more about the file variables at the Camel website: http://camel.apache.org/file-language.html.
In this appendix, we’ve used the Simple language for predicates. In fact, the previous example determines whether the file is a text file or not. Doing this requires operators.
settings

Take our tour and find out more about liveBook's features:
- Search - full text search of all our books
- Discussions - ask questions and interact with other readers in the discussion forum.
- Highlight, annotate, or bookmark.
A.6 Built-in operators
The first example in this appendix implemented the Content-Based Router EIP with the Simple expression language. It used predicates to determine where to route a message, and these predicates use operators. Table A.4 lists all the operators supported in Simple.
Table A.4 Operators provided in the Simple language
Operator |
Description |
|
Tests whether the left side is equal to the right side |
|
Tests whether the left side is equal to the right side ignoring case |
|
Tests whether the left side is greater than the right side |
|
Tests whether the left side is greater than or equal to the right side |
|
Tests whether the left side is less than the right side |
|
Tests whether the left side is less than or equal to the right side |
|
Tests whether the left side is not equal to the right side |
|
Tests whether the left side contains the |
|
Tests whether the left side doesn’t contain the |
|
Tests whether the left side starts with the |
|
Tests whether the left side ends with the |
|
Tests whether the left side is in a set of values specified on the right side; the values must be separated by commas |
|
Tests whether the left side is not in a set of values specified on the right side; the values must be separated by commas |
|
Tests whether the left side is within a range of values defined with the following syntax: 'from..to' |
|
Tests whether the left side is not within a range of values defined with the following syntax: 'from..to' |
|
Tests whether the left side matches a regular expression pattern defined as a |
|
Tests whether the left side doesn’t match a regular expression pattern defined as a |
|
Tests whether the left side type is an instance of the value on the right side |
|
Tests whether the left side type is not an instance of the value on the right side |
|
Unary operator which increments a left hand side function and returns that value. So if we had a counter header with value = 1, the expression ${header.counter}++ would return 2. |
|
Unary operator which decrements a left hand side function and returns that value. So if we had a counter header with value = 2, the expression ${header.counter}-- would return 1. |
The operators require the following syntax:
The value on the left side must be enclosed in a ${ } placeholder. The operator must be separated with a single space on the left and right. The right value can either be a fixed value or another dynamic value enclosed using ${ }.
Let’s look at some examples.
Here you test whether the foo header is equal to the String value "Camel". If you want to test for "Camel rocks", you must enclose the String in quotes (because the value contains a space):
Camel will automatically type coerce, so you can compare apples to oranges. Camel will regard both as fruit:
Suppose the bar header is a String with the value "100". Camel will convert this value to the same type as the value on the right side, which is numeric. It will therefore compute 100 < 200, which renders true.
You can use the range operator to test whether a value is in a numeric range.
Both the from and to range values are inclusive. You must define the range exactly as shown.
A regular expression can be used to test a variety of things, such as whether a value is a four-digit value:
You can also use the built-in functions with the operators. For example, to test whether a given header has today’s date, you can leverage the date function:
Tip
You can see more examples in the Camel Simple online documentation: http://camel.apache.org/simple.html.
The Simple language also allows you to combine two expressions together.
A.6.1 Combining expressions
The Simple language can combine expressions using the && (and) or || (or) operators.
The syntax for combining two expressions is as follows:
Here’s an example using and to group two expressions:
The Simple language also supports an OGNL feature.
highlight, annotate, and bookmark
You can automatically highlight by performing the text selection while keeping the alt/ key pressed.

A.7 The OGNL feature
Both the Simple language and Bean component support an Object Graph Navigation Language (OGNL) feature when specifying the method name to invoke. OGNL allows you to specify a chain of methods in the expression.
Suppose the message body contains a Customer object that has a getAddress() method. To get the ZIP code of the address, you would simply type the following:
You can use a shorter notation, omitting the get prefix and the parentheses.
In this example, the ZIP code will be returned. But if the getAddress method returns null, the example would cause a NoSuchMethodException to be thrown by Camel. If you want to avoid this, you can use the null-safe operator ?. as follows:
The methods in the OGNL expression can be any method name. For example, to invoke a sayHello method, you would do this:
Camel uses the bean parameter binding, which we covered in chapter 4. This means that the method signature of sayHello can have parameters that are bound to the current Exchange being routed:
The OGNL feature has specialized support for accessing Map and List types. For example, suppose the getAddress method has a getLines method that returns a List. You could access the lines by their index values, as follows:
If you try to index an element that is out of bounds, an IndexOutOfBoundsException exception is thrown. You can use the null-safe operator to suppress this exception:
If you want to access the last element, you can use last as the index value, as shown here:
The access support for Maps is similar, but you use a key instead of a numeric value as the index. Suppose the message body contains a getType method that returns a Map instance. You could access the gold entry as follows:
You could even invoke a method on the gold entry like this:
This concludes our tour of the various features supported by the Camel Simple language. We’ll now take a quick look at how to use the Simple language from custom Java code.
discuss

A.8 Using Simple from custom Java code
The Simple language is most often used directly in your Camel routes, in either the Java DSL or a Spring XML file. But it’s also possible to use it from custom Java code.
Here’s an example that uses the Simple language from a Camel Processor.
Listing A.1 Using the Simple language from custom Java code
As you can see in listing A.1, all it takes is creating an instance of SimpleBuilder, which is capable of evaluating either a predicate or an expression. In the listing, you use the Simple language as a predicate.
To use an expression to say “Hello,” you could do the following:
Notice how you specify that you want the response back as a String by passing in String.class to the evaluate method.
Listing A.1 uses the Simple language from within a Camel Processor, but you’re free to use it anywhere, such as from a custom bean. Just keep in mind that the Exchange must be passed into the matches method on the SimpleBuilder.
settings

A.9 Summary
This appendix covered the Simple language, which is an expression language provided with Camel.
You saw how well it blends with Camel routes, which makes it easy to define predicates in routes, such as those needed when using the Content-Based Router.
We also looked at how easy it was with the Simple language to access information from the Exchange message by using the built-in variables. You saw that Simple provides functions, such as a date function that formats dates and a bean function that invokes methods on beans.
Finally, we covered OGNL notation, which makes it even easier to access data from nested beans.
All together, the Simple language is a great expression language that should help you with 95 percent of your use cases.