Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Instant Apache Camel Message Routing

You're reading from   Instant Apache Camel Message Routing Route, transform, split, multicast messages, and do much more with Camel

Arrow left icon
Product type Paperback
Published in Aug 2013
Publisher Packt
ISBN-13 9781783283477
Length 62 pages
Edition 1st Edition
Arrow right icon
Author (1):
Arrow left icon
Bilgin Ibryam Bilgin Ibryam
Author Profile Icon Bilgin Ibryam
Bilgin Ibryam
Arrow right icon
View More author details
Toc

Routing messages to different destinations (Simple)


In the previous tutorial, we routed all the messages through the same processing steps. Integrating real applications usually involves more complex routing scenarios where each message type is processed differently. In this tutorial, we are going to route a message into different locations based on the message content, using a Context-Based Router pattern.

Getting ready

The complete source code for this tutorial is located under the following project: camel-message-routing-examples/routing-different-destinations.

How to do it...

We will extend the previous example by adding conditions to direct incoming files into different folders based on file names:

from("file://source")
        .choice()
        .when(simple("${in.header.CamelFileName} contains 'widget.txt'"))
            .to("file://widget")
        .when(simple("${in.header.CamelFileName} contains 'gadget.txt'"))
            .to("file://gadget")
        .otherwise()
            .to("log://org.apache.camel.howto?showAll=true");

How it works...

A Context-Based Router is similar to a switch statement or to the if then-elseif statement in Java. The incoming message will be directed to one of the possible channels, depending on the condition that is evaluated, usually against the message content. In our example, there are three possible destinations for the incoming messages, and the conditions are written using Simple language. The condition has to be a predicate, that is, an expression that returns only true or false. If the result is true, the message is routed into that channel of the Context-Based Router, otherwise the next condition in order is evaluated. Similar to the default case in a Java switch statement, there is an optional otherwise element for this pattern. If the message doesn't match any of the predicates, it will be directed to the default channel of the route.

Camel expressions operate on the routed message and are used as part of various integration patterns. There are two types of expressions: one that implements the Expression interface and can produce a value from any type, and the other that implements the Predicate interface and produces a Boolean result. Expressions give access to all parts of the routed message, which in Camel world is represented by the Exchange class and has the following structure:

The Exchange class wraps the mandatory In Message representing the request data coming from an inbound channel, and an optional Out Message for the response going into an outbound channel. Each message consists of a payload called Body with Object type and Headers, which is a Map for storing key-value pairs associated with the message. The Exchange class also has Properties for storing Camel specific data, Message Exchange Pattern (MEP), ExchangeId, and Exception field for tracking exceptions if any were encountered during routing. Usually, when a processor receives Exchange, it reads the data from In Message (including Body and Headers), and depending on MEP writes the processed results to Out Message or updates In Message, to be passed to the next processor in the route. In our example, file consumer reads a file from the source folder then puts its reference to the message body, and populates various headers with information about the file (this is where the CamelFileName header gets populated). Then the expressions in the Context-Based Router retrieve the file name from the headers and do the comparison. If the file name contains the string widget.txt the message is sent to the widget folder, otherwise the next condition is evaluated which does a similar comparison with the gadget.txt string. If the message doesn't satisfy any of the conditions, it is sent to the default channel where it is logged and not written to any folder.

There's more...

Next, we will have a look at the other expression languages that Camel supports, and how to make the routing even more dynamic, using Java beans for deciding which is the next endpoint for a message.

Expression languages

The Predicate statement used in the previous example was created using Simple language, but there are many other supported languages. It includes popular scripting languages such as Beanshell, Groovy, Ruby, Python and languages for working with XML, such as XPath, XQuery, the Unified EL, OGNL, among others. The choice of language usually depends on the message format and personal preferences, but Simple language is flexible enough for most occasions. Simple language is a home grown language developed by the Camel community for writing powerful expressions. It gives easy access to different parts of the Exchange, such as input body ${in.body} or a specific message header ${in.header.userId}, properties {property.someKey}, environment variables ${sysenv.someOtherKet}, and so on. It also has good operator support used mostly for predicates such as >=, contains, !=, regex, &&, ||, and so on.

Dynamic routing

A Context-Based Router can direct a message to the correct recipient if all the recipients are known in advance. All of the outbound channels of the Context-Based Router have to be specified as part of its definition, and only then it can choose one based on the message content. This introduces a dependency of the router to all possible destinations and prevents it from choosing a destination dynamically. Dynamic Router pattern solves this problem by choosing a destination for each message at runtime, and configuring itself using control messages from each participating destination.

In Camel, a Dynamic Router pattern is implemented with the dynamicRouter statement that accepts an expression to determine where the message should go next. After routing the message, the expression is evaluated again using the updated message to determine where the message should be routed next. Evaluating the expression and routing the message continues until the expression returns null to indicate the end of routing for that message. So it is important for the expression to return null at some point, otherwise Camel will continue routing the same message endlessly. Because of this complex nature, dynamicRouter expressions usually use Bean expressions:

from("direct:start")
    .dynamicRouter(method(DestinationChooser.class, "nextEndpoint"));

Note

For an example using the Dynamic Router, have a look at http://camel.apache.org/dynamic-router.html.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at R$50/month. Cancel anytime