Routing Expression and Predicate Languages


Red Hat JBoss Fuse

Writing evaluative statements

Red Hat

Version 6.0
13 Oct 2017

Abstract

This guide describes the basic syntax used by the evaluative languages supported by Apache Camel.

Chapter 1. Introduction

Abstract

This chapter provides an overview of all the expression languages supported by Apache Camel.

1.1. Overview of the Languages

Table of expression and predicate languages

Table 1.1, “Expression and Predicate Languages” gives an overview of the different syntaxes for invoking expression and predicate languages.
Expand
Table 1.1. Expression and Predicate Languages
LanguageStatic MethodFluent DSL MethodXML ElementAnnotationArtifact
section "Bean Integration" in "Implementing Enterprise Integration Patterns"bean()EIP().method()method@BeanCamel core
Constantconstant()EIP().constant()constant@ConstantCamel core
ELel()EIP().el()el@ELcamel-juel
Groovygroovy()EIP().groovy()groovy@Groovycamel-groovy
Headerheader()EIP().header()header@HeaderCamel core
JavaScriptjavaScript()EIP().javaScript()javaScript@JavaScriptcamel-script
JoSQLsql()EIP().sql()sql@SQLcamel-josql
JXPathNoneEIP().jxpath()jxpath@JXPathcamel-jxpath
MVELmvel()EIP().mvel()mvel@MVELcamel-mvel
OGNLognl()EIP().ognl()ognl@OGNLcamel-ognl
PHPphp()EIP().php()php@PHPcamel-script
Propertyproperty()EIP().property()property@PropertyCamel core
Pythonpython()EIP().python()python@Pythoncamel-script
Refref()EIP().ref()refN/ACamel core
Rubyruby()EIP().ruby()ruby@Rubycamel-script
Simple/Filesimple()EIP().simple()simple@SimpleCamel core
SpELspel()EIP().spel()spel@SpELcamel-spring
XPathxpath()EIP().xpath()xpath@XPathCamel core
XQueryxquery()EIP().xquery()xquery@XQuerycamel-saxon

1.2. How to Invoke an Expression Language

Prerequisites

Before you can use a particular expression language, you must ensure that the required JAR files are available on the classpath. If the language you want to use is not included in the Apache Camel core, you must add the relevant JARs to your classpath.
If you are using the Maven build system, you can modify the build-time classpath simply by adding the relevant dependency to your POM file. For example, if you want to use the Ruby language, add the following dependency to your POM file:
<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-script</artifactId>
  <!-- Use the same version as your Camel core version -->
  <version>${camel.version}</version>
</dependency>
Copy to Clipboard Toggle word wrap
If you are going to deploy your application in a Red Hat JBoss Fuse OSGi container, you also need to ensure that the relevant language features are installed (features are named after the corresponding Maven artifact). For example, to use the Groovy language in the OSGi container, you must first install the camel-groovy feature by entering the following OSGi console command:
karaf@root> features:install camel-groovy
Copy to Clipboard Toggle word wrap

Approaches to invoking

As shown in Table 1.1, “Expression and Predicate Languages”, there are several different syntaxes for invoking an expression language, depending on the context in which it is used. You can invoke an expression language:

As a static method

Most of the languages define a static method that can be used in any context where an org.apache.camel.Expression type or an org.apache.camel.Predicate type is expected. The static method takes a string expression (or predicate) as its argument and returns an Expression object (which is usually also a Predicate object).
For example, to implement a content-based router that processes messages in XML format, you could route messages based on the value of the /order/address/countryCode element, as follows:
from("SourceURL")
  .choice
    .when(xpath("/order/address/countryCode = 'us'"))
      .to("file://countries/us/")
    .when(xpath("/order/address/countryCode = 'uk'"))
      .to("file://countries/uk/")
    .otherwise()
      .to("file://countries/other/")
  .to("TargetURL");
Copy to Clipboard Toggle word wrap

As a fluent DSL method

The Java fluent DSL supports another style of invoking expression languages. Instead of providing the expression as an argument to an Enterprise Integration Pattern (EIP), you can provide the expression as a sub-clause of the DSL command. For example, instead of invoking an XPath expression as filter(xpath("Expression")), you can invoke the expression as, filter().xpath("Expression").
For example, the preceding content-based router can be re-implemented in this style of invocation, as follows:
from("SourceURL")
  .choice
    .when().xpath("/order/address/countryCode = 'us'")
      .to("file://countries/us/")
    .when().xpath("/order/address/countryCode = 'uk'")
      .to("file://countries/uk/")
    .otherwise()
      .to("file://countries/other/")
  .to("TargetURL");
Copy to Clipboard Toggle word wrap

As an XML element

You can also invoke an expression language in XML, by putting the expression string inside the relevant XML element.
For example, the XML element for invoking XPath in XML is xpath (which belongs to the standard Apache Camel namespace). You can use XPath expressions in a XML DSL content-based router, as follows:
<from uri="file://input/orders"/>
<choice>
  <when>
 <xpath>/order/address/countryCode = 'us'</xpath>
    <to uri="file://countries/us/"/>
  </when>
  <when>
 <xpath>/order/address/countryCode = 'uk'</xpath>
    <to uri="file://countries/uk/"/>
  </when>
  <otherwise>
    <to uri="file://countries/other/"/>
  </otherwise>
</choice>
Copy to Clipboard Toggle word wrap
Alternatively, you can specify a language expression using the language element, where you specify the name of the language in the language attribute. For example, you can define an XPath expression using the language element as follows:
<language language="xpath">/order/address/countryCode = 'us'</language>
Copy to Clipboard Toggle word wrap

As an annotation

Language annotations are used in the context of bean integration (see section "Bean Integration" in "Implementing Enterprise Integration Patterns"). The annotations provide a convenient way of extracting information from a message or header and then injecting the extracted data into a bean's method parameters.
For example, consider the bean, myBeanProc, which is invoked as a predicate of the filter() EIP. If the bean's checkCredentials method returns true, the message is allowed to proceed; but if the method returns false, the message is blocked by the filter. The filter pattern is implemented as follows:
// Java
MyBeanProcessor myBeanProc = new MyBeanProcessor();

from("SourceURL")
  .filter().method(myBeanProc, "checkCredentials")
  .to("TargetURL");
Copy to Clipboard Toggle word wrap
The implementation of the MyBeanProcessor class exploits the @XPath annotation to extract the username and password from the underlying XML message, as follows:
// Java
import org.apache.camel.language.XPath;

public class MyBeanProcessor {
    boolean void checkCredentials(
        @XPath("/credentials/username/text()") String user,
        @XPath("/credentials/password/text()") String pass
    ) {
        // Check the user/pass credentials...
        ...
    }
}
Copy to Clipboard Toggle word wrap
The @XPath annotation is placed just before the parameter into which it gets injected. Notice how the XPath expression explicitly selects the text node, by appending /text() to the path, which ensures that just the content of the element is selected, not the enclosing tags.

Chapter 2. Constant

Overview

The constant language is a trivial built-in language that is used to specify a plain text string. This makes it possible to provide a plain text string in any context where an expression type is expected.

XML example

In XML, you can set the username header to the value, Jane Doe as follows:
<camelContext>
  <route>
    <from uri="SourceURL"/>
    <setHeader headerName="username">
      <constant>Jane Doe</constant>
    </setHeader>
    <to uri="TargetURL"/>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Java example

In Java, you can set the username header to the value, Jane Doe as follows:
from("SourceURL")
  .setHeader("username", constant("Jane Doe"))
  .to("TargetURL");
Copy to Clipboard Toggle word wrap

Chapter 3. EL

Overview

The Unified Expression Language (EL) was originally specified as part of the JSP 2.1 standard (JSR-245), but it is now available as a standalone language. Apache Camel integrates with JUEL (http://juel.sourceforge.net/), which is an open source implementation of the EL language.

Adding JUEL package

To use EL in your routes you need to add a dependency on camel-juel to your project as shown in Example 3.1, “Adding the camel-juel dependency”.

Example 3.1. Adding the camel-juel dependency

<!-- Maven POM File -->
<properties>
  <camel-version>2.10.0.redhat-60024</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-juel</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the el() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.language.juel.JuelExpression.el;
Copy to Clipboard Toggle word wrap

Variables

Table 3.1, “EL variables” lists the variables that are accessible when using EL.
Expand
Table 3.1. EL variables
VariableTypeValue
exchange org.apache.camel.Exchange The current Exchange
in org.apache.camel.Message The IN message
out org.apache.camel.Message The OUT message

Example

Example 3.2, “Routes using EL” shows two routes that use EL.

Example 3.2. Routes using EL

<camelContext>
  <route>
    <from uri="seda:foo"/>
    <filter>
      <language language="el">${in.headers.foo == 'bar'}</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
  <route>
    <from uri="seda:foo2"/>
    <filter>
      <language language="el">${in.headers['My Header'] == 'bar'}</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Chapter 4. The File Language

Abstract

The file language is an extension to the simple language, not an independent language in its own right. But the file language extension can only be used in conjunction with File or FTP endpoints.

4.1. When to Use the File Language

Overview

The file language is an extension to the simple language which is not always available. You can use it under the following circumstances:
Note
The escape character, \, is not available in the file language.

In a File or FTP consumer endpoint

There are several URI options that you can set on a File or FTP consumer endpoint, which take a file language expression as their value. For example, in a File consumer endpoint URI you can set the fileName, move, preMove, moveFailed, and sortBy options using a file expression.
In a File consumer endpoint, the fileName option acts as a filter, determining which file will actually be read from the starting directory. If a plain text string is specified (for example, fileName=report.txt), the File consumer reads the same file each time it is updated. You can make this option more dynamic, however, by specifying a simple expression. For example, you could use a counter bean to select a different file each time the File consumer polls the starting directory, as follows:
file://target/filelanguage/bean/?fileName=${bean:counter.next}.txt&delete=true
Copy to Clipboard Toggle word wrap
Where the ${bean:counter.next} expression invokes the next() method on the bean registered under the ID, counter.
The move option is used to move files to a backup location after then have been read by a File consumer endpoint. For example, the following endpoint moves files to a backup directory, after they have been processed:
file://target/filelanguage/?move=backup/${date:now:yyyyMMdd}/${file:name.noext}.bak&recursive=false
Copy to Clipboard Toggle word wrap
Where the ${file:name.noext}.bak expression modifies the original file name, replacing the file extension with .bak.
You can use the sortBy option to specify the order in which file should be processed. For example, to process files according to the alphabetical order of their file name, you could use the following File consumer endpoint:
file://target/filelanguage/?sortBy=file:name
Copy to Clipboard Toggle word wrap
To process file according to the order in which they were last modified, you could use the following File consumer endpoint:
file://target/filelanguage/?sortBy=file:modified
Copy to Clipboard Toggle word wrap
You can reverse the order by adding the reverse: prefix—for example:
file://target/filelanguage/?sortBy=reverse:file:modified
Copy to Clipboard Toggle word wrap

On exchanges created by a File or FTP consumer

When an exchange originates from a File or FTP consumer endpoint, it is possible to apply file language expressions to the exchange throughout the route (as long as the original message headers are not erased). For example, you could define a content-based router, which routes messages according to their file extension, as follows:
<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>
Copy to Clipboard Toggle word wrap

4.2. File Variables

Overview

File variables can be used whenever a route starts with a File or FTP consumer endpoint, which implies that the underlying message body is of java.io.File type. The file variables enable you to access various parts of the file pathname, almost as if you were invoking the methods of the java.io.File class (in fact, the file language extracts the information it needs from message headers that have been set by the File or FTP endpoint).

Starting directory

Some of file variables return paths that are defined relative to a starting directory, which is just the directory that is specified in the File or FTP endpoint. For example, the following File consumer endpoint has the starting directory, ./filetransfer (a relative path):
file:filetransfer
Copy to Clipboard Toggle word wrap
The following FTP consumer endpoint has the starting directory, ./ftptransfer (a relative path):
ftp://myhost:2100/ftptransfer
Copy to Clipboard Toggle word wrap

Naming convention of file variables

In general, the file variables are named after corresponding methods on the java.io.File class. For example, the file:absolute variable gives the value that would be returned by the java.io.File.getAbsolute() method.
Note
This naming convention is not strictly followed, however. For example, there is no such method as java.io.File.getSize().

Table of variables

Table 4.1, “Variables for the File Language” shows all of the variable supported by the file language.
Expand
Table 4.1. Variables for the File Language
VariableTypeDescription
file:nameStringThe pathname relative to the starting directory.
file:name.extStringThe file extension (characters following the last . character in the pathname).
file:name.noextStringThe pathname relative to the starting directory, omitting the file extension.
file:onlynameStringThe final segment of the pathname. That is, the file name without the parent directory path.
file:onlyname.noextStringThe final segment of the pathname, omitting the file extension.
file:extStringThe file extension (same as file:name.ext).
file:parentStringThe pathname of the parent directory, including the starting directory in the path.
file:pathStringThe file pathname, including the starting directory in the path.
file:absoluteBooleantrue, if the starting directory was specified as an absolute path; false, otherwise.
file:absolute.pathStringThe absolute pathname of the file.
file:lengthLongThe size of the referenced file.
file:sizeLongSame as file:length.
file:modifiedjava.util.DateDate last modified.

4.3. Examples

Relative pathname

Consider a File consumer endpoint, where the starting directory is specified as a relative pathname. For example, the following File endpoint has the starting directory, ./filelanguage:
file://filelanguage
Copy to Clipboard Toggle word wrap
Now, while scanning the filelanguage directory, suppose that the endpoint has just consumed the following file:
./filelanguage/test/hello.txt
Copy to Clipboard Toggle word wrap
And, finally, assume that the filelanguage directory itself has the following absolute location:
/workspace/camel/camel-core/target/filelanguage
Copy to Clipboard Toggle word wrap
Given the preceding scenario, the file language variables return the following values, when applied to the current exchange:
Expand
ExpressionResult
file:nametest/hello.txt
file:name.exttxt
file:name.noexttest/hello
file:onlynamehello.txt
file:onlyname.noexthello
file:exttxt
file:parentfilelanguage/test
file:pathfilelanguage/test/hello.txt
file:absolutefalse
file:absolute.path/workspace/camel/camel-core/target/filelanguage/test/hello.txt

Absolute pathname

Consider a File consumer endpoint, where the starting directory is specified as an absolute pathname. For example, the following File endpoint has the starting directory, /workspace/camel/camel-core/target/filelanguage:
file:///workspace/camel/camel-core/target/filelanguage
Copy to Clipboard Toggle word wrap
Now, while scanning the filelanguage directory, suppose that the endpoint has just consumed the following file:
./filelanguage/test/hello.txt
Copy to Clipboard Toggle word wrap
Given the preceding scenario, the file language variables return the following values, when applied to the current exchange:
Expand
ExpressionResult
file:nametest/hello.txt
file:name.exttxt
file:name.noexttest/hello
file:onlynamehello.txt
file:onlyname.noexthello
file:exttxt
file:parent/workspace/camel/camel-core/target/filelanguage/test
file:path/workspace/camel/camel-core/target/filelanguage/test/hello.txt
file:absolutetrue
file:absolute.path/workspace/camel/camel-core/target/filelanguage/test/hello.txt

Chapter 5. Groovy

Overview

Groovy is a Java-based scripting language that allows quick parsing of object. The Groovy support is part of the camel-script module.

Adding the script module

To use Groovy in your routes you need to add a dependency on camel-script to your project as shown in Example 5.1, “Adding the camel-script dependency”.

Example 5.1. Adding the camel-script dependency

<!-- Maven POM File -->
<properties>
  <camel-version>2.10.0.redhat-60024</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the groovy() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.camel.script.ScriptBuilder.*;
Copy to Clipboard Toggle word wrap

Built-in attributes

Table 5.1, “Groovy attributes” lists the built-in attributes that are accessible when using Groovy.
Expand
Table 5.1. Groovy attributes
AttributeTypeValue
contextorg.apache.camel.CamelContextThe Camel Context
exchangeorg.apache.camel.ExchangeThe current Exchange
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesorg.apache.camel.builder.script.PropertiesFunctionFunction with a resolve method to make it easier to use the properties component inside scripts.
The attributes all set at ENGINE_SCOPE.

Example

Example 5.2, “Routes using Groovy” shows two routes that use Groovy scripts.

Example 5.2. Routes using Groovy

<camelContext>
  <route>
    <from uri=""mock:mock0" />
    <filter>
      <language language="groovy">request.lineItems.any { i -> i.value > 100 }</language>
      <to uri="mock:mock1" />
    </filter>
  </route>
  <route>
    <from uri="direct:in"/>
    <setHeader headerName="firstName">
      <language language="groovy">$user.firstName $user.lastName</language>
    </setHeader>
    <to uri="seda:users"/>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Using the properties component

To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:
.setHeader("myHeader").groovy("properties.resolve(PropKey)")
Copy to Clipboard Toggle word wrap
Where PropKey is the key of the property you want to resolve, where the key value is of String type.
For more details about the properties component, see chapter "Properties" in "EIP Component Reference".

Chapter 7. JavaScript

Overview

JavaScript, also known as ECMAScript is a Java-based scripting language that allows quick parsing of object. The JavaScript support is part of the camel-script module.

Adding the script module

To use JavaScript in your routes you need to add a dependency on camel-script to your project as shown in Example 7.1, “Adding the camel-script dependency”.

Example 7.1. Adding the camel-script dependency

<!-- Maven POM File -->
<properties>
  <camel-version>2.10.0.redhat-60024</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the javaScript() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.camel.script.ScriptBuilder.*;
Copy to Clipboard Toggle word wrap

Built-in attributes

Table 7.1, “JavaScript attributes” lists the built-in attributes that are accessible when using JavaScript.
Expand
Table 7.1. JavaScript attributes
AttributeTypeValue
contextorg.apache.camel.CamelContextThe Camel Context
exchangeorg.apache.camel.ExchangeThe current Exchange
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesorg.apache.camel.builder.script.PropertiesFunctionFunction with a resolve method to make it easier to use the properties component inside scripts.
The attributes all set at ENGINE_SCOPE.

Example

Example 7.2, “Route using JavaScript” shows a route that uses JavaScript.

Example 7.2. Route using JavaScript

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <langauge langauge="javaScript">request.headers.get('user') == 'admin'</langauge>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Using the properties component

To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:
.setHeader("myHeader").javaScript("properties.resolve(PropKey)")
Copy to Clipboard Toggle word wrap
Where PropKey is the key of the property you want to resolve, where the key value is of String type.
For more details about the properties component, see chapter "Properties" in "EIP Component Reference".

Chapter 8. JoSQL

Overview

The JoSQL (SQL for Java objects) language enables you to evaluate predicates and expressions in Apache Camel. JoSQL employs a SQL-like query syntax to perform selection and ordering operations on data from in-memory Java objects—however, JoSQL is not a database. In the JoSQL syntax, each Java object instance is treated like a table row and each object method is treated like a column name. Using this syntax, it is possible to construct powerful statements for extracting and compiling data from collections of Java objects. For details, see http://josql.sourceforge.net/.

Adding the JoSQL module

To use JoSQL in your routes you need to add a dependency on camel-josql to your project as shown in Example 8.1, “Adding the camel-josql dependency”.

Example 8.1. Adding the camel-josql dependency

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-josql</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the sql() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.sql.SqlBuilder.sql;
Copy to Clipboard Toggle word wrap

Variables

Table 8.1, “SQL variables” lists the variables that are accessible when using JoSQL.
Expand
Table 8.1. SQL variables
NameTypeDescription
exchangeorg.apache.camel.ExchangeThe current Exchange
inorg.apache.camel.MessageThe IN message
outorg.apache.camel.MessageThe OUT message
propertyObjectthe Exchange property whose key is property
headerObjectthe IN message header whose key is header
variableObjectthe variable whose key is variable

Example

Example 8.2, “Route using JoSQL” shows a route that uses JoSQL.

Example 8.2. Route using JoSQL

<camelContext>
  <route>
    <from uri="direct:start"/>
    <setBody>
      <language language="sql">select * from MyType</language>
    </setBody>
    <to uri="seda:regularQueue"/>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Chapter 9. JXPath

Overview

The JXPath language enables you to invoke Java beans using the Apache Commons JXPath language. The JXPath language has a similar syntax to XPath, but instead of selecting element or attribute nodes from an XML document, it invokes methods on an object graph of Java beans. If one of the bean attributes returns an XML document (a DOM/JDOM instance), however, the remaining portion of the path is interpreted as an XPath expression and is used to extract an XML node from the document. In other words, the JXPath language provides a hybrid of object graph navigation and XML node selection.

Adding JXPath package

To use JXPath in your routes you need to add a dependency on camel-jxpath to your project as shown in Example 9.1, “Adding the camel-jxpath dependency”.

Example 9.1. Adding the camel-jxpath dependency

<!-- Maven POM File -->
<properties>
  <camel-version>2.10.0.redhat-60024</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jxpath</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Variables

Table 9.1, “JXPath variables” lists the variables that are accessible when using JXPath.
Expand
Table 9.1. JXPath variables
VariableTypeValue
thisorg.apache.camel.ExchangeThe current Exchange
inorg.apache.camel.MessageThe IN message
outorg.apache.camel.MessageThe OUT message

Example

Example 9.2, “Routes using JXPath” shows a route that use JXPath.

Example 9.2. Routes using JXPath

<camelContext>
  <route>
    <from uri="activemq:MyQueue"/>
    <filter>
      <jxpath>in/body/name = 'James'</xpath>
      <to uri="mqseries:SomeOtherQueue"/>
    </filter>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Chapter 10. MVEL

Overview

MVEL (http://mvel.codehaus.org/) is a Java-based dynamic language that is similar to OGNL, but is reported to be much faster. The MVEL support is in the camel-mvel module.

Syntax

You use the MVEL dot syntax to invoke Java methods, for example:
getRequest().getBody().getFamilyName()
Copy to Clipboard Toggle word wrap
Because MVEL is dynamically typed, it is unnecessary to cast the message body instance (of Object type) before invoking the getFamilyName() method. You can also use an abbreviated syntax for invoking bean attributes, for example:
request.body.familyName
Copy to Clipboard Toggle word wrap

Adding the MVEL module

To use MVEL in your routes you need to add a dependency on camel-mvel to your project as shown in Example 10.1, “Adding the camel-mvel dependency”.

Example 10.1. Adding the camel-mvel dependency

<!-- Maven POM File -->
<properties>
  <camel-version>2.10.0.redhat-60024</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-mvel</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Built-in variables

Table 10.1, “MVEL variables” lists the built-in variables that are accessible when using MVEL.
Expand
Table 10.1. MVEL variables
NameTypeDescription
thisorg.apache.camel.ExchangeThe current Exchange
exchangeorg.apache.camel.ExchangeThe current Exchange
exceptionThrowablethe Exchange exception (if any)
exchangeIDStringthe Exchange ID
faultorg.apache.camel.MessageThe Fault message(if any)
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesMapThe Exchange properties
property(name)ObjectThe value of the named Exchange property
property(name, type)TypeThe typed value of the named Exchange property

Example

Example 10.2, “Route using MVEL” shows a route that uses MVEL.

Example 10.2. Route using MVEL

<camelContext>
  <route>
    <from uri="seda:foo"/>
    <filter>
      <language langauge="mvel">request.headers.foo == 'bar'</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Overview

OGNL (http://www.opensymphony.com/ognl/) is an expression language for getting and setting properties of Java objects. You use the same expression for both getting and setting the value of a property. The OGNL support is in the camel-ognl module.

Adding the OGNL module

To use OGNL in your routes you need to add a dependency on camel-ognl to your project as shown in Example 11.1, “Adding the camel-ognl dependency”.

Example 11.1. Adding the camel-ognl dependency

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-ognl</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the ognl() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.language.ognl.OgnlExpression.ognl;
Copy to Clipboard Toggle word wrap

Built-in variables

Table 11.1, “OGNL variables” lists the built-in variables that are accessible when using OGNL.
Expand
Table 11.1. OGNL variables
NameTypeDescription
thisorg.apache.camel.ExchangeThe current Exchange
exchangeorg.apache.camel.ExchangeThe current Exchange
exceptionThrowablethe Exchange exception (if any)
exchangeIDStringthe Exchange ID
faultorg.apache.camel.MessageThe Fault message(if any)
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesMapThe Exchange properties
property(name)ObjectThe value of the named Exchange property
property(name, type)TypeThe typed value of the named Exchange property

Example

Example 11.2, “Route using OGNL” shows a route that uses OGNL.

Example 11.2. Route using OGNL

<camelContext>
  <route>
    <from uri="seda:foo"/>
    <filter>
      <language langauge="ognl">request.headers.foo == 'bar'</language>
      <to uri="seda:bar"/>
    </filter>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Chapter 12. PHP

Overview

PHP is a widely-used general-purpose scripting language that is especially suited for Web development. The PHP support is part of the camel-script module.

Adding the script module

To use PHP in your routes you need to add a dependency on camel-script to your project as shown in Example 12.1, “Adding the camel-script dependency”.

Example 12.1. Adding the camel-script dependency

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the php() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.camel.script.ScriptBuilder.*;
Copy to Clipboard Toggle word wrap

Built-in attributes

Table 12.1, “PHP attributes” lists the built-in attributes that are accessible when using PHP.
Expand
Table 12.1. PHP attributes
AttributeTypeValue
contextorg.apache.camel.CamelContextThe Camel Context
exchangeorg.apache.camel.ExchangeThe current Exchange
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesorg.apache.camel.builder.script.PropertiesFunctionFunction with a resolve method to make it easier to use the properties component inside scripts.
The attributes all set at ENGINE_SCOPE.

Example

Example 12.2, “Route using PHP” shows a route that uses PHP.

Example 12.2. Route using PHP

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <language language="php">strpos(request.headers.get('user'), 'admin')!== FALSE</language>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Using the properties component

To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:
.setHeader("myHeader").php("properties.resolve(PropKey)")
Copy to Clipboard Toggle word wrap
Where PropKey is the key of the property you want to resolve, where the key value is of String type.
For more details about the properties component, see chapter "Properties" in "EIP Component Reference".

Chapter 13. Property

Overview

The property language provides a convenient way of accessing exchange properties. When you supply a key that matches one of the exchange property names, the property language returns the corresponding value.
The property language is part of camel-core.

XML example

For example, to implement the recipient list pattern when the listOfEndpoints exchange property contains the recipient list, you could define a route as follows:
<camelContext>
  <route>
    <from uri="direct:a"/>
    <recipientList>
      <property>listOfEndpoints</property>
    </recipientList>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Java example

The same recipient list example can be implemented in Java as follows:
from("direct:a").recipientList(property("listOfEndpoints"));
Copy to Clipboard Toggle word wrap

Chapter 14. Python

Overview

Python is a remarkably powerful dynamic programming language that is used in a wide variety of application domains. Python is often compared to Tcl, Perl, Ruby, Scheme or Java. The Python support is part of the camel-script module.

Adding the script module

To use Python in your routes you need to add a dependency on camel-script to your project as shown in Example 14.1, “Adding the camel-script dependency”.

Example 14.1. Adding the camel-script dependency

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the python() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.camel.script.ScriptBuilder.*;
Copy to Clipboard Toggle word wrap

Built-in attributes

Table 14.1, “Python attributes” lists the built-in attributes that are accessible when using Python.
Expand
Table 14.1. Python attributes
AttributeTypeValue
contextorg.apache.camel.CamelContextThe Camel Context
exchangeorg.apache.camel.ExchangeThe current Exchange
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesorg.apache.camel.builder.script.PropertiesFunctionFunction with a resolve method to make it easier to use the properties component inside scripts.
The attributes all set at ENGINE_SCOPE.

Example

Example 14.2, “Route using Python” shows a route that uses Python.

Example 14.2. Route using Python

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <langauge langauge="python">if request.headers.get('user') = 'admin'</langauge>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Using the properties component

To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:
.setHeader("myHeader").python("properties.resolve(PropKey)")
Copy to Clipboard Toggle word wrap
Where PropKey is the key of the property you want to resolve, where the key value is of String type.
For more details about the properties component, see chapter "Properties" in "EIP Component Reference".

Chapter 15. Ref

Overview

The Ref expression language is really just a way to look up a custom Expression from the Registry. This is particular convenient to use in the XML DSL.
The Ref language is part of camel-core.

Static import

To use the Ref language in your Java application code, include the following import statement in your Java source files:
import static org.apache.camel.language.simple.RefLanguage.ref;
Copy to Clipboard Toggle word wrap

XML example

For example, the splitter pattern can reference a custom expression using the Ref language, as follows:
<beans ...>
  <bean id="myExpression" class="com.mycompany.MyCustomExpression"/>
  ...
  <camelContext>
    <route>
      <from uri="seda:a"/>
      <split>
        <ref>myExpression</ref>   
        <to uri="mock:b"/>
      </split>     
    </route>
  </camelContext>
</beans>
Copy to Clipboard Toggle word wrap

Java example

The preceding route can also be implemented in the Java DSL, as follows:
from("seda:a")
  .split().ref("myExpression")
  .to("seda:b");
Copy to Clipboard Toggle word wrap

Chapter 16. Ruby

Overview

Ruby is a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write. The Ruby support is part of the camel-script module.

Adding the script module

To use Ruby in your routes you need to add a dependency on camel-script to your project as shown in Example 16.1, “Adding the camel-script dependency”.

Example 16.1. Adding the camel-script dependency

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-script</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the ruby() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.camel.script.ScriptBuilder.*;
Copy to Clipboard Toggle word wrap

Built-in attributes

Table 16.1, “Ruby attributes” lists the built-in attributes that are accessible when using Ruby.
Expand
Table 16.1. Ruby attributes
AttributeTypeValue
contextorg.apache.camel.CamelContextThe Camel Context
exchangeorg.apache.camel.ExchangeThe current Exchange
requestorg.apache.camel.MessageThe IN message
responseorg.apache.camel.MessageThe OUT message
propertiesorg.apache.camel.builder.script.PropertiesFunctionFunction with a resolve method to make it easier to use the properties component inside scripts.
The attributes all set at ENGINE_SCOPE.

Example

Example 16.2, “Route using Ruby” shows a route that uses Ruby.

Example 16.2. Route using Ruby

<camelContext>
  <route>
    <from uri="direct:start"/>
    <choice>
      <when>
        <langauge langauge="ruby">$request.headers['user'] == 'admin'</langauge>
        <to uri="seda:adminQueue"/>
      </when>
      <otherwise>
        <to uri="seda:regularQueue"/>
      </otherwise>
    </choice>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Using the properties component

To access a property value from the properties component, invoke the resolve method on the built-in properties attribute, as follows:
.setHeader("myHeader").ruby("properties.resolve(PropKey)")
Copy to Clipboard Toggle word wrap
Where PropKey is the key of the property you want to resolve, where the key value is of String type.
For more details about the properties component, see chapter "Properties" in "EIP Component Reference".

Chapter 17. The Simple Language

Abstract

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.

17.1. Java DSL

Simple expressions in Java DSL

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");
Copy to Clipboard Toggle word wrap
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");
Copy to Clipboard Toggle word wrap

Embedding in a string

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?")
Copy to Clipboard Toggle word wrap

Customizing the start and end tokens

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("]");
Copy to Clipboard Toggle word wrap
Note
Customizing the start and end tokens affects all Apache Camel applications that share the same camel-core library on their classpath. For example, in an OSGi server this might affect many applications; whereas in a Web application (WAR file) it would affect only the Web application itself.

17.2. XML DSL

Simple expressions in XML DSL

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>
Copy to Clipboard Toggle word wrap

Alternative placeholder syntax

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>
Copy to Clipboard Toggle word wrap

Customizing the start and end tokens

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>
Copy to Clipboard Toggle word wrap
Note
Customizing the start and end tokens affects all Apache Camel applications that share the same camel-core library on their classpath. For example, in an OSGi server this might affect many applications; whereas in a Web application (WAR file) it would affect only the Web application itself.

Whitespace and auto-trim in XML DSL

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>
Copy to Clipboard Toggle word wrap
is automatically trimmed, so that it is equivalent to this expression (no surrounding whitespace):
<transform> 
  <simple>data=${body}</simple> 
</transform>
Copy to Clipboard Toggle word wrap
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>
Copy to Clipboard Toggle word wrap
or you can switch off auto-trimming, by setting the trim attribute to false, as follows:
<transform trim="false"> 
  <simple>data=${body}
</simple> 
</transform>
Copy to Clipboard Toggle word wrap

17.3. Expressions

Overview

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, ${Expression}, to return a variable value. It is never permissible to omit the enclosing tokens (${ and }).

Contents of a single variable

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}")
Copy to Clipboard Toggle word wrap

Variables embedded in a string

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}.")
Copy to Clipboard Toggle word wrap

date and bean variables

As well as providing variables that access all of the different parts of an exchange (see Table 17.1, “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}")
Copy to Clipboard Toggle word wrap

Specifying the result type

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 a boolean result, you could evaluate a simple expression as follows:
...
.setHeader("cool", simple("true", Boolean.class))
Copy to Clipboard Toggle word wrap
In the XML DSL, specify the result type using the resultType attribute. For example:
<setHeader headerName="cool">
  <!-- use resultType to indicate that the type should be a java.lang.Boolean --> 
  <simple resultType="java.lang.Boolean">true</simple>
</setHeader>
Copy to Clipboard Toggle word wrap

Nested expressions

Simple expressions can be nested—for example:
simple("${header.${bean:headerChooser?method=whichHeader}}")
Copy to Clipboard Toggle word wrap

OGNL expressions

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}")
Copy to Clipboard Toggle word wrap
Where the notation, ${body.address.street}, is shorthand for ${body.getAddress.getStreet}.

OGNL null-safe operator

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}")
Copy to Clipboard Toggle word wrap
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}")
Copy to Clipboard Toggle word wrap

OGNL list element access

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]}")
Copy to Clipboard Toggle word wrap
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]}")
Copy to Clipboard Toggle word wrap

17.4. Predicates

Overview

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.

Syntax

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 RHSValue
Copy to Clipboard Toggle word wrap
Where the variable on the left hand side, LHSVariable, is one of the variables shown in Table 17.1, “Variables for the Simple Language” and the value on the right hand side, RHSValue, is one of the following:
  • Another variable, ${RHSVariable}.
  • A string literal, enclosed in single quotes, ' '.
  • A numeric constant, enclosed in single quotes, ' '.
  • The null object, null.
The simple language always attempts to convert the RHS value to the type of the LHS value.

Examples

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 integer
Copy to Clipboard Toggle word wrap
You can test whether the left hand side is a member of a comma-separated list, as follows:
simple("${in.header.type} in 'gold,silver'")
Copy to Clipboard Toggle word wrap
You can test whether the left hand side matches a regular expression, as follows:
simple("${in.header.number} regex '\d{4}'")
Copy to Clipboard Toggle word wrap
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. types
Copy to Clipboard Toggle word wrap
You 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'")
Copy to Clipboard Toggle word wrap

Conjunctions

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'")
Copy to Clipboard Toggle word wrap
And here is an expression using the || conjunction (logical inclusive or):
simple("${in.header.title} contains 'Camel' || ${in.header.type} == 'gold'")
Copy to Clipboard Toggle word wrap

17.5. Variable Reference

Table of variables

Table 17.1, “Variables for the Simple Language” shows all of the variables supported by the simple language.
Expand
Table 17.1. Variables for the Simple Language
VariableTypeDescription
exchangeIdStringThe exchange's ID value.
idStringThe In message ID value.
body Object
The In message body. Supports OGNL expressions.
in.bodyObjectThe In message body. Supports OGNL expressions.
out.body Object
The Out message body.
bodyAs(Type)TypeThe In message body, converted to the specified type. All types, Type, must be specified using their fully-qualified Java name, except for the types: byte[], String, Integer, and Long. The converted body can be null.
mandatoryBodyAs(Type)TypeThe In message body, converted to the specified type. All types, Type, must be specified using their fully-qualified Java name, except for the types: byte[], String, Integer, and Long. The converted body is expected to be non-null.
header.HeaderNameObject
The In message's HeaderName header. Supports OGNL expressions.
header[HeaderName]Object
The In message's HeaderName header (alternative syntax).
headers.HeaderNameObjectThe In message's HeaderName header.
headers[HeaderName]ObjectThe In message's HeaderName header (alternative syntax).
in.header.HeaderNameObjectThe In message's HeaderName header. Supports OGNL expressions.
in.header[HeaderName]ObjectThe In message's HeaderName header (alternative syntax).
in.headers.HeaderNameObjectThe In message's HeaderName header. Supports OGNL expressions.
in.headers[HeaderName]ObjectThe In message's HeaderName header (alternative syntax).
out.header.HeaderName Object
The Out message's HeaderName header.
out.header[HeaderName]Object
The Out message's HeaderName header (alternative syntax).
out.headers.HeaderNameObjectThe Out message's HeaderName header.
out.headers[HeaderName]ObjectThe Out message's HeaderName header (alternative syntax).
headerAs(Key,Type)TypeThe Key header, converted to the specified type. All types, Type, must be specified using their fully-qualified Java name, except for the types: byte[], String, Integer, and Long. The converted value can be null.
headersMapAll of the In headers (as a java.util.Map type).
in.headersMapAll of the In headers (as a java.util.Map type).
property.PropertyName Object
The PropertyName property on the exchange.
property[PropertyName]Object
The PropertyName property on the exchange (alternative syntax).
sys.SysPropertyNameStringThe SysPropertyName Java system property.
sysenv.SysEnvVarStringThe SysEnvVar system environment variable.
exceptionStringEither the exception object from Exchange.getException() or, if this value is null, the caught exception from the Exchange.EXCEPTION_CAUGHT property; otherwise null. Supports OGNL expressions.
exception.messageStringIf an exception is set on the exchange, returns the value of Exception.getMessage(); otherwise, returns null.
exception.stacktraceStringIf an exception is set on the exchange, returns the value of Exception.getStackTrace(); otherwise, returns null. Note: The simple language first tries to retrieve an exception from Exchange.getException(). If that property is not set, it checks for a caught exception, by calling Exchange.getProperty(Exchange.CAUGHT_EXCEPTION).
date:command:patternStringA date formatted using a java.text.SimpleDateFormat pattern. The following commands are supported: now, for the current date and time; header.HeaderName, or in.header.HeaderName to use a java.util.Date object in the HeaderName header from the In message; out.header.HeaderName to use a java.util.Date object in the HeaderName header from the Out message;
bean:beanID.MethodObjectInvokes a method on the referenced bean and returns the result of the method invocation. To specify a method name, you can either use the beanID.Method syntax; or you can use the beanID?method=methodName syntax.
ref:beanIDObjectLooks 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.
properties:KeyStringThe value of the Key property placeholder (see section "Property Placeholders" in "Implementing Enterprise Integration Patterns").
properties:Location:KeyStringThe value of the Key property placeholder, where the location of the properties file is given by Location (see section "Property Placeholders" in "Implementing Enterprise Integration Patterns").
threadNameStringThe name of the current thread.

17.6. Operator Reference

Binary operators

The binary operators for simple language predicates are shown in Table 17.2, “Binary Operators for the Simple Language”.
Expand
Table 17.2. Binary Operators for the Simple Language
OperatorDescription
==Equals.
>Greater than.
>=Greater than or equals.
<Less than.
<=Less than or equals.
!=Not equal to.
containsTest if LHS string contains RHS string.
not containsTest if LHS string does not contain RHS string.
regexTest if LHS string matches RHS regular expression.
not regexTest if LHS string does not match RHS regular expression.
inTest if LHS string appears in the RHS comma-separated list.
not inTest if LHS string does not appear in the RHS comma-separated list.
isTest if LHS is an instance of RHS Java type (using Java instanceof operator).
not isTest if LHS is not an instance of RHS Java type (using Java instanceof operator).
rangeTest if LHS number lies in the RHS range (where range has the format, 'min...max').
not rangeTest if LHS number does not lie in the RHS range (where range has the format, 'min...max').

Unary operators

The binary operators for simple language predicates are shown in Table 17.3, “Unary Operators for the Simple Language”.
Expand
Table 17.3. Unary Operators for the Simple Language
OperatorDescription
++Increment a number by 1.
--Decrement a number by 1.
\Escape the following character. Note the following special cases: \n for new line, \t for tab, and \r for carriage return.

Combining predicates

The conjunctions shown in Table 17.4, “Conjunctions for Simple Language Predicates” can be used to combine two or more simple language predicates.
Expand
Table 17.4. Conjunctions for Simple Language Predicates
OperatorDescription
&&Combine two predicates with logical and.
||Combine two predicates with logical inclusive or.
andDeprecated. Use && instead.
orDeprecated. Use || instead.

Chapter 18. SpEL

Overview

The Spring Expression Language (SpEL) is an object graph navigation language provided with Spring 3, which can be used to construct predicates and expressions in a route. A notable feature of SpEL is the ease with which you can access beans from the registry.

Syntax

The SpEL expressions must use the placeholder syntax, #{SpelExpression}, so that they can be embedded in a plain text string (in other words, SpEL has expression templating enabled).
SpEL can also look up beans in the registry (typically, the Spring registry), using the @BeanID syntax. For example, given a bean with the ID, headerUtils, and the method, count() (which counts the number of headers on the current message), you could use the headerUtils bean in an SpEL predicate, as follows:
#{@headerUtils.count > 4}
Copy to Clipboard Toggle word wrap

Adding SpEL package

To use SpEL in your routes you need to add a dependency on camel-spring to your project as shown in Example 18.1, “Adding the camel-spring dependency”.

Example 18.1. Adding the camel-spring dependency

<!-- Maven POM File -->
<properties>
  <camel-version>2.10.0.redhat-60024</camel-version>
  ...
</properties>

<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-spring</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Variables

Table 18.1, “SpEL variables” lists the variables that are accessible when using SpEL.
Expand
Table 18.1. SpEL variables
VariableTypeDescription
thisExchangeThe current exchange is the root object.
exchangeExchangeThe current exchange.
exchangeIdStringThe current exchange's ID.
exceptionThrowableThe exchange exception (if any).
faultMessageThe fault message (if any).
requestMessageThe exchange's In message.
responseMessageThe exchange's Out message (if any).
propertiesMapThe exchange properties.
property(Name)ObjectThe exchange property keyed by Name.
property(Name, Type)TypeThe exchange property keyed by Name, converted to the type, Type.

XML example

For example, to select only those messages whose Country header has the value USA, you can use the following SpEL expression:
<route>
  <from uri="SourceURL"/>
  <filter>
    <spel>#{request.headers['Country'] == 'USA'}}</spel>
    <to uri="TargetURL"/>
  </filter>
</route>
Copy to Clipboard Toggle word wrap

Java example

You can define the same route in the Java DSL, as follows:
from("SourceURL")
  .filter().spel("#{request.headers['Country'] == 'USA'}")
  .to("TargetURL");
Copy to Clipboard Toggle word wrap
The following example shows how to embed SpEL expressions within a plain text string:
from("SourceURL")
  .setBody(spel("Hello #{request.body}! What a beautiful #{request.headers['dayOrNight']}"))
  .to("TargetURL");
Copy to Clipboard Toggle word wrap

Chapter 19. The XPath Language

Abstract

When processing XML messages, the XPath language enables you to select part of a message, by specifying an XPath expression that acts on the message's Document Object Model (DOM). You can also define XPath predicates to test the contents of an element or an attribute.

19.1. Java DSL

Basic expressions

You can use xpath("Expression") to evaluate an XPath expression on the current exchange (where the XPath expression is applied to the body of the current In message). The result of the xpath() expression is an XML node (or node set, if more than one node matches).
For example, to extract the contents of the /person/name element from the current In message body and use it to set a header named user, you could define a route like the following:
from("queue:foo")
    .setHeader("user", xpath("/person/name/text()"))
    .to("direct:tie");
Copy to Clipboard Toggle word wrap
Instead of specifying xpath() as an argument to setHeader(), you can use the fluent builder xpath() command—for example:
from("queue:foo")
    .setHeader("user").xpath("/person/name/text()")
    .to("direct:tie");
Copy to Clipboard Toggle word wrap
If you want to convert the result to a specific type, specify the result type as the second argument of xpath(). For example, to specify explicitly that the result type is String:
xpath("/person/name/text()", String.class)
Copy to Clipboard Toggle word wrap

Namespaces

Typically, XML elements belong to a schema, which is identified by a namespace URI. When processing documents like this, it is necessary to associate namespace URIs with prefixes, so that you can identify element names unambiguously in your XPath expressions. Apache Camel provides the helper class, org.apache.camel.builder.xml.Namespaces, which enables you to define associations between namespaces and prefixes.
For example, to associate the prefix, cust, with the namespace, http://acme.com/customer/record, and then extract the contents of the element, /cust:person/cust:name, you could define a route like the following:
import org.apache.camel.builder.xml.Namespaces;
...
Namespaces ns = new Namespaces("cust", "http://acme.com/customer/record");

from("queue:foo")
    .setHeader("user", xpath("/cust:person/cust:name/text()", ns))
    .to("direct:tie");
Copy to Clipboard Toggle word wrap
Where you make the namespace definitions available to the xpath() expression builder by passing the Namespaces object, ns, as an additional argument. If you need to define multiple namespaces, use the Namespace.add() method, as follows:
import org.apache.camel.builder.xml.Namespaces;
...
Namespaces ns = new Namespaces("cust", "http://acme.com/customer/record");
ns.add("inv", "http://acme.com/invoice");
ns.add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Copy to Clipboard Toggle word wrap
If you need to specify the result type and define namespaces, you can use the three-argument form of xpath(), as follows:
xpath("/person/name/text()", String.class, ns)
Copy to Clipboard Toggle word wrap

Auditing namespaces

One of the most frequent problems that can occur when using XPath expressions is that there is a mismatch between the namespaces appearing in the incoming messages and the namespaces used in the XPath expression. To help you troubleshoot this kind of problem, the XPath language supports an option to dump all of the namespaces from all of the incoming messages into the system log.
To enable namespace logging at the INFO log level, enable the logNamespaces option in the Java DSL, as follows:
xpath("/foo:person/@id", String.class).logNamespaces()
Copy to Clipboard Toggle word wrap
Alternatively, you could configure your logging system to enable TRACE level logging on the org.apache.camel.builder.xml.XPathBuilder logger.
When namespace logging is enabled, you will see log messages like the following for each processed message:
2012-01-16 13:23:45,878 [stSaxonWithFlag] INFO  XPathBuilder  -
Namespaces discovered in message: {xmlns:a=[http://apache.org/camel],
DEFAULT=[http://apache.org/default], 
xmlns:b=[http://apache.org/camelA, http://apache.org/camelB]}
Copy to Clipboard Toggle word wrap

19.2. XML DSL

Basic expressions

To evaluate an XPath expression in the XML DSL, put the XPath expression inside an xpath element. The XPath expression is applied to the body of the current In message and returns an XML node (or node set). Typically, the returned XML node is automatically converted to a string.
For example, to extract the contents of the /person/name element from the current In message body and use it to set a header named user, you could define a route like the following:
<beans ...>

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="queue:foo"/>
      <setHeader headerName="user">
        <xpath>/person/name/text()</xpath>
      </setHeader>
      <to uri="direct:tie"/>
    </route>
  </camelContext>

</beans>
Copy to Clipboard Toggle word wrap
If you want to convert the result to a specific type, specify the result type by setting the resultType attribute to a Java type name (where you must specify the fully-qualified type name). For example, to specify explicitly that the result type is java.lang.String (you can omit the java.lang. prefix here):
<xpath resultType="String">/person/name/text()</xpath>
Copy to Clipboard Toggle word wrap

Namespaces

When processing documents whose elements belong to one or more XML schemas, it is typically necessary to associate namespace URIs with prefixes, so that you can identify element names unambiguously in your XPath expressions. It is possible to use the standard XML mechanism for associating prefixes with namespace URIs. That is, you can set an attribute like this: xmlns:Prefix="NamespaceURI".
For example, to associate the prefix, cust, with the namespace, http://acme.com/customer/record, and then extract the contents of the element, /cust:person/cust:name, you could define a route like the following:
<beans ...>

  <camelContext xmlns="http://camel.apache.org/schema/spring"
                xmlns:cust="http://acme.com/customer/record" >
    <route>
      <from uri="queue:foo"/>
      <setHeader headerName="user">
        <xpath>/cust:person/cust:name/text()</xpath>
      </setHeader>
      <to uri="direct:tie"/>
    </route>
  </camelContext>

</beans>
Copy to Clipboard Toggle word wrap

Auditing namespaces

One of the most frequent problems that can occur when using XPath expressions is that there is a mismatch between the namespaces appearing in the incoming messages and the namespaces used in the XPath expression. To help you troubleshoot this kind of problem, the XPath language supports an option to dump all of the namespaces from all of the incoming messages into the system log.
To enable namespace logging at the INFO log level, enable the logNamespaces option in the XML DSL, as follows:
<xpath logNamespaces="true" resultType="String">/foo:person/@id</xpath>
Copy to Clipboard Toggle word wrap
Alternatively, you could configure your logging system to enable TRACE level logging on the org.apache.camel.builder.xml.XPathBuilder logger.
When namespace logging is enabled, you will see log messages like the following for each processed message:
2012-01-16 13:23:45,878 [stSaxonWithFlag] INFO  XPathBuilder  -
Namespaces discovered in message: {xmlns:a=[http://apache.org/camel],
DEFAULT=[http://apache.org/default], 
xmlns:b=[http://apache.org/camelA, http://apache.org/camelB]}
Copy to Clipboard Toggle word wrap

19.3. XPath Injection

Parameter binding annotation

When using Apache Camel bean integration to invoke a method on a Java bean, you can use the @XPath annotation to extract a value from the exchange and bind it to a method parameter.
For example, consider the following route fragment, which invokes the credit method on an AccountService object:
from("queue:payments")
    .beanRef("accountService","credit")
    ...
Copy to Clipboard Toggle word wrap
The credit method uses parameter binding annotations to extract relevant data from the message body and inject it into its parameters, as follows:
public class AccountService {
    ...
    public void credit(
            @XPath("/transaction/transfer/receiver/text()") String name,
            @XPath("/transaction/transfer/amount/text()") String amount
            )
    {
        ...
    }
    ...
}
Copy to Clipboard Toggle word wrap
For more information about bean integration, see section "Bean Integration" in "Implementing Enterprise Integration Patterns".

Namespaces

Table 19.1, “Predefined Namespaces for @XPath” shows the namespaces that are predefined for XPath. You can use these namespace prefixes in the XPath expression that appears in the @XPath annotation.
Expand
Table 19.1. Predefined Namespaces for @XPath
Namespace URIPrefix
http://www.w3.org/2001/XMLSchemaxsd
http://www.w3.org/2003/05/soap-envelopesoap

Custom namespaces

You can use the @NamespacePrefix annotation to define custom XML namespaces. Invoke the @NamespacePrefix annotation to initialize the namespaces argument of the @XPath annotation. The namespaces defined by @NamespacePrefix can then be used in the @XPath annotation's expression value.
For example, to associate the prefix, ex, with the custom namespace, http://fusesource.com/examples, invoke the @XPath annotation as follows:
public class AccountService {
  ...
  public void credit(
    @XPath(
      value = "/ex:transaction/ex:transfer/ex:receiver/text()",
      namespaces = @NamespacePrefix(
        prefix = "ex",
        uri = "http://fusesource.com/examples"
      )
    ) String name,
    @XPath(
      value = "/ex:transaction/ex:transfer/ex:amount/text()",
      namespaces = @NamespacePrefix(
        prefix = "ex",
        uri = "http://fusesource.com/examples"
      )
    ) String amount,
  )
  {
    ...
  }
  ...
}
Copy to Clipboard Toggle word wrap

19.4. XPath Builder

Overview

The org.apache.camel.builder.xml.XPathBuilder class enables you to evaluate XPath expressions independently of an exchange. That is, if you have an XML fragment from any source, you can use XPathBuilder to evaluate an XPath expression on the XML fragment.

Matching expressions

Use the matches() method to check whether one or more XML nodes can be found that match the given XPath expression. The basic syntax for matching an XPath expression using XPathBuilder is as follows:
boolean matches = XPathBuilder
                    .xpath("Expression")
                    .matches(CamelContext, "XMLString");
Copy to Clipboard Toggle word wrap
Where the given expression, Expression, is evaluated against the XML fragment, XMLString, and the result is true, if at least one node is found that matches the expression. For example, the following example returns true, because the XPath expression finds a match in the xyz attribute.
boolean matches = XPathBuilder
                    .xpath("/foo/bar/@xyz")
                    .matches(getContext(), "<foo><bar xyz='cheese'/></foo>"));
Copy to Clipboard Toggle word wrap

Evaluating expressions

Use the evaluate() method to return the contents of the first node that matches the given XPath expression. The basic syntax for evaluating an XPath expression using XPathBuilder is as follows:
String nodeValue = XPathBuilder
                    .xpath("Expression")
                    .evaluate(CamelContext, "XMLString");
Copy to Clipboard Toggle word wrap
You can also specify the result type by passing the required type as the second argument to evaluate()—for example:
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);
Boolean bool = XPathBuilder
                   .xpath("foo/bar")
                   .evaluate(context, "<foo><bar>true</bar></foo>", Boolean.class);
Copy to Clipboard Toggle word wrap

19.5. Enabling Saxon

Prerequisites

A prerequisite for using the Saxon parser is that you add a dependency on the camel-saxon artifact (either adding this dependency to your Maven POM, if you use Maven, or adding the camel-saxon-6.0.0.redhat-024.jar file to your classpath, otherwise).

Using the Saxon parser in Java DSL

In Java DSL, the simplest way to enable the Saxon parser is to call the saxon() fluent builder method. For example, you could invoke the Saxon parser as shown in the following example:
// Java
// 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>");
Copy to Clipboard Toggle word wrap

Using the Saxon parser in XML DSL

In XML DSL, the simplest way to enable the Saxon parser is to set the saxon attribute to true in the xpath element. For example, you could invoke the Saxon parser as shown in the following example:
<xpath saxon="true" resultType="java.lang.String">current-dateTime()</xpath>
Copy to Clipboard Toggle word wrap

Programming with Saxon

If you want to use the Saxon XML parser in your application code, you can create an instance of the Saxon transformer factory explicitly using the following code:
// Java
import javax.xml.transform.TransformerFactory;
import net.sf.saxon.TransformerFactoryImpl;
...
TransformerFactory saxonFactory = new net.sf.saxon.TransformerFactoryImpl();
Copy to Clipboard Toggle word wrap
On the other hand, if you prefer to use the generic JAXP API to create a transformer factory instance, you must first set the javax.xml.transform.TransformerFactory property in the ESBInstall/etc/system.properties file, as follows:
javax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl
Copy to Clipboard Toggle word wrap
You can then instantiate the Saxon factory using the generic JAXP API, as follows:
// Java
import javax.xml.transform.TransformerFactory;
...
TransformerFactory factory = TransformerFactory.newInstance();
Copy to Clipboard Toggle word wrap
If your application depends on any third-party libraries that use Saxon, it might be necessary to use the second, generic approach.
Note
The Saxon library must be installed in the container as the OSGi bundle, net.sf.saxon/saxon9he (normally installed by default). In versions of Fuse ESB prior to 7.1, it is not possible to load Saxon using the generic JAXP API.

19.6. Expressions

Result type

By default, an XPath expression returns a list of one or more XML nodes, of org.w3c.dom.NodeList type. You can use the type converter mechanism to convert the result to a different type, however. In the Java DSL, you can specify the result type in the second argument of the xpath() command. For example, to return the result of an XPath expression as a String:
xpath("/person/name/text()", String.class)
Copy to Clipboard Toggle word wrap
In the XML DSL, you can specify the result type in the resultType attribute, as follows:
<xpath resultType="java.lang.String">/person/name/text()</xpath>
Copy to Clipboard Toggle word wrap

Patterns in location paths

You can use the following patterns in XPath location paths:
/people/person
The basic location path specifies the nested location of a particular element. That is, the preceding location path would match the person element in the following XML fragment:
<people>
  <person>...</person>
</people>
Copy to Clipboard Toggle word wrap
Note that this basic pattern can match multiple nodes—for example, if there is more than one person element inside the people element.
/name/text()
If you just want to access the text inside by the element, append /text() to the location path, otherwise the node includes the element's start and end tags (and these tags would be included when you convert the node to a string).
/person/telephone/@isDayTime
To select the value of an attribute, AttributeName, use the syntax @AttributeName. For example, the preceding location path returns true when applied to the following XML fragment:
<person>
  <telephone isDayTime="true">1234567890</telephone>
</person>
Copy to Clipboard Toggle word wrap
*
A wildcard that matches all elements in the specified scope. For example, /people/person/* matches all the child elements of person.
@*
A wildcard that matches all attributes of the matched elements. For example, /person/name/@* matches all attributes of every matched name element.
//
Match the location path at every nesting level. For example, the //name pattern matches every name element highlighted in the following XML fragment:
<invoice>
  <person>
    <name .../>
  </person>
</invoice>
<person>
  <name .../>
</person>
<name .../>
Copy to Clipboard Toggle word wrap
..
Selects the parent of the current context node. Not normally useful in the Apache Camel XPath language, because the current context node is the document root, which has no parent.
node()
Match any kind of node.
text()
Match a text node.
comment()
Match a comment node.
processing-instruction()
Match a processing-instruction node.

Predicate filters

You can filter the set of nodes matching a location path by appending a predicate in square brackets, [Predicate]. For example, you can select the Nth node from the list of matches by appending [N] to a location path. The following expression selects the first matching person element:
/people/person[1]
Copy to Clipboard Toggle word wrap
The following expression selects the second-last person element:
/people/person[last()-1]
Copy to Clipboard Toggle word wrap
You can test the value of attributes in order to select elements with particular attribute values. The following expression selects the name elements, whose surname attribute is either Strachan or Davies:
/person/name[@surname="Strachan" or @surname="Davies"]
Copy to Clipboard Toggle word wrap
You can combine predicate expressions using any of the conjunctions and, or, not(), and you can compare expressions using the comparators, =, !=, >, >=, <, <= (in practice, the less-than symbol must be replaced by the &lt; entity). You can also use XPath functions in the predicate filter.

Axes

When you consider the structure of an XML document, the root element contains a sequence of children, and some of those child elements contain further children, and so on. Looked at in this way, where nested elements are linked together by the child-of relationship, the whole XML document has the structure of a tree. Now, if you choose a particular node in this element tree (call it the context node), you might want to refer to different parts of the tree relative to the chosen node. For example, you might want to refer to the children of the context node, to the parent of the context node, or to all of the nodes that share the same parent as the context node (sibling nodes).
An XPath axis is used to specify the scope of a node match, restricting the search to a particular part of the node tree, relative to the current context node. The axis is attached as a prefix to the node name that you want to match, using the syntax, AxisType::MatchingNode. For example, you can use the child:: axis to search the children of the current context node, as follows:
/invoice/items/child::item
Copy to Clipboard Toggle word wrap
The context node of child::item is the items element that is selected by the path, /invoice/items. The child:: axis restricts the search to the children of the context node, items, so that child::item matches the children of items that are named item. As a matter of fact, the child:: axis is the default axis, so the preceding example can be written equivalently as:
/invoice/items/item
Copy to Clipboard Toggle word wrap
But there several other axes (13 in all), some of which you have already seen in abbreviated form: @ is an abbreviation of attribute::, and // is an abbreviation of descendant-or-self::. The full list of axes is as follows (for details consult the reference below):
  • ancestor
  • ancestor-or-self
  • attribute
  • child
  • descendant
  • descendant-or-self
  • following
  • following-sibling
  • namespace
  • parent
  • preceding
  • preceding-sibling
  • self

Functions

XPath provides a small set of standard functions, which can be useful when evaluating predicates. For example, to select the last matching node from a node set, you can use the last() function, which returns the index of the last node in a node set, as follows:
/people/person[last()]
Copy to Clipboard Toggle word wrap
Where the preceding example selects the last person element in a sequence (in document order).
For full details of all the functions that XPath provides, consult the reference below.

Reference

For full details of the XPath grammar, see the XML Path Language, Version 1.0 specification.

19.7. Predicates

Basic predicates

You can use xpath in the Java DSL or the XML DSL in a context where a predicate is expected—for example, as the argument to a filter() processor or as the argument to a when() clause.
For example, the following route filters incoming messages, allowing a message to pass, only if the /person/city element contains the value, London:
from("direct:tie")
    .filter().xpath("/person/city = 'London'").to("file:target/messages/uk");
Copy to Clipboard Toggle word wrap
The following route evaluates the XPath predicate in a when() clause:
from("direct:tie")
    .choice()
        .when(xpath("/person/city = 'London'")).to("file:target/messages/uk")
        .otherwise().to("file:target/messages/others");
Copy to Clipboard Toggle word wrap

XPath predicate operators

The XPath language supports the standard XPath predicate operators, as shown in Table 19.2, “Operators for the XPath Language”.
Expand
Table 19.2. Operators for the XPath Language
OperatorDescription
=Equals.
!=Not equal to.
>Greater than.
>=Greater than or equals.
<Less than.
<=Less than or equals.
orCombine two predicates with logical and.
andCombine two predicates with logical inclusive or.
not()Negate predicate argument.

19.8. Using Variables and Functions

Evaluating variables in a route

When evaluating XPath expressions inside a route, you can use XPath variables to access the contents of the current exchange, as well as O/S environment variables and Java system properties. The syntax to access a variable value is $VarName or $Prefix:VarName, if the variable is accessed through an XML namespace.
For example, you can access the In message's body as $in:body and the In message's header value as $in:HeaderName. O/S environment variables can be accessed as $env:EnvVar and Java system properties can be accessed as $system:SysVar.
In the following example, the first route extracts the value of the /person/city element and inserts it into the city header. The second route filters exchanges using the XPath expression, $in:city = 'London', where the $in:city variable is replaced by the value of the city header.
from("file:src/data?noop=true")
    .setHeader("city").xpath("/person/city/text()")
    .to("direct:tie");
        
from("direct:tie")
    .filter().xpath("$in:city = 'London'").to("file:target/messages/uk");
Copy to Clipboard Toggle word wrap

Evaluating functions in a route

In addition to the standard XPath functions, the XPath language defines additional functions. These additional functions (which are listed in Table 19.4, “XPath Custom Functions”) can be used to access the underlying exchange, to evaluate a simple expression or to look up a property in the Apache Camel property placeholder component.
For example, the following example uses the in:header() function and the in:body() function to access a head and the body from the underlying exchange:
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");
Copy to Clipboard Toggle word wrap
Notice the similarity between theses functions and the corresponding in:HeaderName or in:body variables. The functions have a slightly different syntax however: in:header('HeaderName') instead of in:HeaderName; and in:body() instead of in:body.

Evaluating variables in XPathBuilder

You can also use variables in expressions that are evaluated using the XPathBuilder class. In this case, you cannot use variables such as $in:body or $in:HeaderName, because there is no exchange object to evaluate against. But you can use variables that are defined inline using the variable(Name, Value) fluent builder method.
For example, the following XPathBuilder construction evaluates the $test variable, which is defined to have the value, London:
String var = XPathBuilder.xpath("$test")
               .variable("test", "London")
               .evaluate(getContext(), "<name>foo</name>");
Copy to Clipboard Toggle word wrap
Note that variables defined in this way are automatically entered into the global namespace (for example, the variable, $test, uses no prefix).

19.9. Variable Namespaces

Table of namespaces

Table 19.3, “XPath Variable Namespaces” shows the namespace URIs that are associated with the various namespace prefixes.
Expand
Table 19.3. XPath Variable Namespaces
Namespace URIPrefixDescription
http://camel.apache.org/schema/springNoneDefault namespace (associated with variables that have no namespace prefix).
http://camel.apache.org/xml/in/inUsed to reference header or body of the current exchange's In message.
http://camel.apache.org/xml/out/outUsed to reference header or body of the current exchange's Out message.
http://camel.apache.org/xml/functions/functionsUsed to reference some custom functions.
http://camel.apache.org/xml/variables/environment-variablesenvUsed to reference O/S environment variables.
http://camel.apache.org/xml/variables/system-propertiessystemUsed to reference Java system properties.
http://camel.apache.org/xml/variables/exchange-propertyUndefinedUsed to reference exchange properties. You must define your own prefix for this namespace.

19.10. Function Reference

Table of custom functions

Table 19.4, “XPath Custom Functions” shows the custom functions that you can use in Apache Camel XPath expressions. These functions can be used in addition to the standard XPath functions.
Expand
Table 19.4. XPath Custom Functions
FunctionDescription
in:body()Returns the In message body.
in:header(HeaderName)Returns the In message header with name, HeaderName.
out:body()Returns the Out message body.
out:header(HeaderName)Returns the Out message header with name, HeaderName.
function:properties(PropKey)Looks up a property with the key, PropKey (see section "Property Placeholders" in "Implementing Enterprise Integration Patterns").
function:simple(SimpleExp)Evaluates the specified simple expression, SimpleExp.

Chapter 20. XQuery

Overview

XQuery was originally devised as a query language for data stored in XML form in a database. The XQuery language enables you to select parts of the current message, when the message is in XML format. XQuery is a superset of the XPath language; hence, any valid XPath expression is also a valid XQuery expression.

Java syntax

You can pass an XQuery expression to xquery() in several ways. For simple expressions, you can pass the XQuery expressions as a string (java.lang.String). For longer XQuery expressions, you might prefer to store the expression in a file, which you can then reference by passing a java.io.File argument or a java.net.URL argument to the overloaded xquery() method. The XQuery expression implicitly acts on the message content and returns a node set as the result. Depending on the context, the return value is interpreted either as a predicate (where an empty node set is interpreted as false) or as an expression.

Adding the Saxon module

To use XQuery in your routes you need to add a dependency on camel-saxon to your project as shown in Example 20.1, “Adding the camel-saxon dependency”.

Example 20.1. Adding the camel-saxon dependency

<!-- Maven POM File -->
...
<dependencies>
  ...
  <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-saxon</artifactId>
    <version>${camel-version}</version>
  </dependency>
  ...
</dependencies>
Copy to Clipboard Toggle word wrap

Static import

To use the xquery() static method in your application code, include the following import statement in your Java source files:
import static org.apache.camel.builder.saxon.XQueryBuilder.xquery;
Copy to Clipboard Toggle word wrap

Variables

Table 20.1, “XQuery variables” lists the variables that are accessible when using XQuery.
Expand
Table 20.1. XQuery variables
VariableTypeDescription
exchangeExchangeThe current Exchange
in.bodyObjectThe body of the IN message
out.bodyObjectThe body of the OUT message
in.headers.keyObjectThe IN message header whose key is key
out.headers.keyObjectThe OUT message header whose key is key
keyObjectThe Exchange property whose key is key

Example

Example 20.2, “Route using XQuery” shows a route that uses XQuery.

Example 20.2. Route using XQuery

<camelContext>
  <route>
    <from uri="activemq:MyQueue"/>
    <filter>
      <language langauge="xquery">/foo:person[@name='James']</language>
      <to uri="mqseries:SomeOtherQueue"/>
    </filter>
  </route>
</camelContext>
Copy to Clipboard Toggle word wrap

Legal Notice

Trademark Disclaimer

The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Apache, ServiceMix, Camel, CXF, and ActiveMQ are trademarks of Apache Software Foundation. Any other names contained herein may be trademarks of their respective owners.

Legal Notice

Third Party Acknowledgements

One or more products in the Red Hat JBoss Fuse release includes third party components covered by licenses that require that the following documentation notices be provided:
  • JLine (http://jline.sourceforge.net) jline:jline:jar:1.0
    License: BSD (LICENSE.txt) - Copyright (c) 2002-2006, Marc Prud'hommeaux
    All rights reserved.
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
    • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    • Neither the name of JLine nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  • Stax2 API (http://woodstox.codehaus.org/StAX2) org.codehaus.woodstox:stax2-api:jar:3.1.1
    Copyright (c) <YEAR>, <OWNER> All rights reserved.
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
    • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  • jibx-run - JiBX runtime (http://www.jibx.org/main-reactor/jibx-run) org.jibx:jibx-run:bundle:1.2.3
    License: BSD (http://jibx.sourceforge.net/jibx-license.html) Copyright (c) 2003-2010, Dennis M. Sosnoski.
    All rights reserved.
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
    • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    • Neither the name of JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  • JavaAssist (http://www.jboss.org/javassist) org.jboss.javassist:com.springsource.javassist:jar:3.9.0.GA:compile
  • HAPI-OSGI-Base Module (http://hl7api.sourceforge.net/hapi-osgi-base/) ca.uhn.hapi:hapi-osgi-base:bundle:1.2
    License: Mozilla Public License 1.1 (http://www.mozilla.org/MPL/MPL-1.1.txt)
Back to top
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust. Explore our recent updates.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Theme

© 2026 Red Hat