blob: 103b9369c0529df7a768852d8f52aace47355bac [file] [log] [blame]
[[Predicate-Predicates]]
=== Predicates
Camel supports a pluggable interface called
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Predicate.html[Predicate]
which can be used to integrate a dynamic predicate into
link:enterprise-integration-patterns.adoc[Enterprise Integration
Patterns] such as when using the <<filter-eip,Message Filter>>
or <<contentBasedRouter-eip,Content Based Router>>.
A Predicate is being evaluated to a boolean value so the result is
either `true` or `false`. This makes link:predicate.adoc[Predicate] so
powerful as it is often used to control the routing of message in which
path they should be routed.
A simple example is to route an link:exchange.adoc[Exchange] based on a
header value:
[source,java]
----
from("jms:queue:order")
.choice()
.when(header("type").isEqualTo("widget")).to("bean:widgetOrder")
.when(header("type").isEqualTo("wombat")).to("bean:wombatOrder")
.otherwise()
.to("bean:miscOrder")
.end();
----
In the route above the link:predicate.adoc[Predicate] is the
`header("type").isEqualTo("widget")` as its constructed as an
link:expression.adoc[Expression] that is evaluated as a
link:predicate.adoc[Predicate]. To do this the various Builder classes
helps us here to create a nice and fluent syntax. `isEqualTo` is a
builder method that returns a link:predicate.adoc[Predicate] based on
the input.
Sometimes the fluent builders can get long and a bit complex to read,
then you can just define your predicate outside the route and then just
refer to the predicate in the route:
[source,java]
----
Predicate isWidget = header("type").isEqualTo("widget");
----
And then you can refer to it in the route as:
[source,java]
----
from("jms:queue:order")
.choice()
.when(isWidget).to("bean:widgetOrder")
.when(isWombat).to("bean:wombatOrder")
.otherwise()
.to("bean:miscOrder")
.end();
----
[[Predicate-NegatingaPredicate]]
==== Negating a Predicate
You can use the *not* method on the `PredicateBuilder` to negate a
predicate.
First we import the not static, so it makes our route nice and easy to
read:
[source,java]
----
import static org.apache.camel.builder.PredicateBuilder.not
----
And then we can use it to enclose an existing predicate and negate it as
the example shows:
[source,java]
----
from("direct:start")
.choice()
.when(not(header("username").regex("goofy|pluto"))).to("mock:people")
.otherwise().to("mock:animals")
.end();
----
[[Predicate-CompoundPredicates]]
==== Compound Predicates
You can also create compound predicates using boolean operators such as
`and, or, not` and many others.
Currently this feature is only available in the Java-based DSLs, but not
in the Spring nor Blueprint DSLs.
Using the
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/builder/PredicateBuilder.html[`PredicateBuilder`]
class, you can combine predicates *from different Expression Languages*
based on logical operators and comparison operators:
* `not`, `and`, `or`
* `isNull`, `isNotNull`
* `isEqualTo`, `isGreaterThan`, `isLessThan`
* `startsWith`, `endsWith`
* `in` ("any of X predicates stands true")
Additionally, with `PredicateBuilder` you can create Regular Expressions
and use them as predicates, applying them to the result of an
expression, e.g. `PredicateBuilder.regex(header("foo"), "\d{4}")`
applies the regular expression to the header = foo.
Combining different Expression Languages is also possible, e.g.:
[source,java]
----
PredicateBuilder.and(XPathBuilder.xpath("/bookings/flights"), simple("${property.country = 'Spain'}"))
----
The sample below demonstrates further use cases:
[source,java]
----
// We define 3 predicates based on some user roles
// we have static imported and/or from org.apache.camel.builder.PredicateBuilder
// First we have a regular user that is just identified having a username header
Predicate user = header("username").isNotNull();
// The admin user must be a user AND have a admin header as true
Predicate admin = and(user, header("admin").isEqualTo("true"));
// And God must be an admin and (either have type god or a special message containing Camel Rider)
Predicate god = and(admin, or(body().contains("Camel Rider"), header("type").isEqualTo("god")));
// As you can see with the predicates above we can stack them to build compound predicates
// In our route below we can create a nice content based router based on the predicates we
// have defined. Then the route is easy to read and understand.
// We encourage you to define complex predicates outside the fluent router builder as
// it will just get a bit complex for humans to read
from("direct:start").choice()
.when(god).to("mock:god")
.when(admin).to("mock:admin")
.when(user).to("mock:user")
.otherwise().to("mock:guest")
.end();
----
[[Predicate-ExtensiblePredicates]]
==== Extensible Predicates
Camel supports extensible Predicates using multiple
link:languages.adoc[Languages]; the following languages are supported
out of the box
* link:bean-language.adoc[Bean Language] for using Java for expressions
* link:constant.adoc[Constant]
* the unified link:el.adoc[EL] from JSP and JSF
* link:header.adoc[Header]
* link:jsonpath.adoc[JSonPath]
* link:jxpath.adoc[JXPath]
* link:mvel.adoc[Mvel]
* link:ognl.adoc[OGNL]
* link:ref-language.adoc[Ref Language]
* link:exchangeproperty.adoc[ExchangeProperty] link:property.adoc[Property]
* link:scripting-languages.adoc[Scripting Languages] such as
** link:beanshell.adoc[BeanShell]
** link:javascript.adoc[JavaScript]
** link:groovy.adoc[Groovy]
** link:python.adoc[Python]
** link:php.adoc[PHP]
** link:ruby.adoc[Ruby]
* link:simple.adoc[Simple]
** link:file-language.adoc[File Language]
* link:spel.adoc[Spring Expression Language]
* link:sql.adoc[SQL]
* link:tokenizer.adoc[Tokenizer]
* link:xpath.adoc[XPath]
* link:xquery.adoc[XQuery]
* https://github.com/camel-extra/camel-extra/blob/master/components/camel-vtdxml/src/main/docs/vtdxml-component.adoc[VTD-XML]
Most of these languages is also supported used as
link:annotation-based-expression-language.adoc[Annotation Based
Expression Language].
You can easily write your own plugin predicate by implementing the
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Predicate.html[Predicate
interface].
There are also a number of helper builders available such as the
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/builder/PredicateBuilder.html[PredicateBuilder
class]
[[Predicate-UsingPredicatesinyourIDE]]
==== Using Predicates in your IDE
To use different expression and predicates in your IDE you need to
perform a static import of the builder class for the language(s) you
wish to use.
[width="100%",cols="50%,50%",options="header",]
|=======================================================================
|Language(s) |Builder class to import
|link:scripting-languages.adoc[Scripting Languages] such as
link:beanshell.adoc[BeanShell], link:javascript.adoc[JavaScript],
link:groovy.adoc[Groovy], link:php.adoc[PHP], link:python.adoc[Python]
and link:ruby.adoc[Ruby]
|http://camel.apache.org/maven/current/camel-script/apidocs/org/apache/camel/builder/script/ScriptBuilder.html[org.apache.camel.builder.script.ScriptBuilder]
|link:sql.adoc[SQL]
|http://camel.apache.org/maven/current/camel-josql/apidocs/org/apache/camel/builder/sql/SqlBuilder.html[org.apache.camel.builder.josql.SqlBuilder]
|link:xpath.adoc[XPath]
|http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/builder/xml/XPathBuilder.html[org.apache.camel.builder.xml.XPathBuilder]
|link:xquery.adoc[XQuery]
|http://camel.apache.org/maven/current/camel-saxon/apidocs/org/apache/camel/builder/saxon/XQueryBuilder.html[org.apache.camel.builder.saxon.XQueryBuilder]
|=======================================================================
[[Predicate-SeeAlso]]
==== See Also
* link:expression.adoc[Expression]