In this article, I will show you examples of Camel’s content based routing. You can guess from the name, the routing of a message is based on the content of the message. You can also base it on the headers or properties associated with the message.
This example uses the following frameworks:
- Maven 3.2.3
- Apache Camel 2.15.1
- Spring 4.1.5.RELEASE
- Eclipse as the IDE, version Luna 4.4.1.
Dependencies
We are just relying camel’s core components, the spring based components and the logger component in case you want to log something so our pom.xml
consists of:
camel-core
– camel core components like timer, bean etcslf4j-api
– in case you want to use logslf4j-log4j12
– if you want to use log4j as the slf4j implementationcamel-stream
– for printing the messages to consolespring-context
– for spring supportcamel-spring
– include it if you want to define route in spring
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javarticles.camel</groupId> <artifactId>camelContentBasedRouting</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>2.15.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring</artifactId> <version>2.15.2</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-stream</artifactId> <version>2.15.2</version> </dependency> </dependencies> </project>
Content Based Routing Example
Content Based Routing is similar to Filtering but it has multiple predicates.
It starts with choice()
and then follows one or more when()
. Each when()
contains a predicate expression. If the message matches the predicate, the contained processing steps will be executed. If none of the when()
matches, then the processing steps contained with otherwise()
will be executed.
from("direct:start") .choice() .when(simple("${body} contains 'Java'")) .to("direct:javaArticles") .log("Added to 'Java Articles'") .when(simple("${header.views} > 10000")) .to("direct:popularArticles") .log("Added to 'Popular Articles'") .otherwise() .to("direct:allArticles") .log("Added to 'All Articles'") .end() .log("Processing of ${body} done");
CamelContentBasedRouterExample:
package com.javarticles.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; public class CamelContentBasedRouterExample { public static final void main(String[] args) throws Exception { CamelContext camelContext = new DefaultCamelContext(); try { camelContext.addRoutes(new RouteBuilder() { public void configure() { from("direct:start") .choice() .when(simple("${body} contains 'Java'")) .to("direct:javaArticles") .log("Added to 'Java Articles'") .when(simple("${header.views} > 10000")) .to("direct:popularArticles") .log("Added to 'Popular Articles'") .otherwise() .to("direct:allArticles") .log("Added to 'All Articles'") .end() .log("Processing of ${body} done"); from("direct:javaArticles") .log("Java Articles") .to("stream:out"); from("direct:popularArticles") .log("Popular Articles") .to("stream:out"); from("direct:allArticles") .log("All Articles") .to("stream:out"); } }); ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("direct:start", "Java Threads"); template.sendBodyAndHeader("direct:start", "Camel Content Based Router", "views", 20000); template.sendBody("direct:start", "Spring Integration"); } finally { camelContext.stop(); } } }
Output:
09:20| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://start] 09:20| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[direct://javaArticles] 09:20| INFO | DefaultCamelContext.java 3164 | Route: route3 started and consuming from: Endpoint[direct://popularArticles] 09:20| INFO | DefaultCamelContext.java 3164 | Route: route4 started and consuming from: Endpoint[direct://allArticles] 09:20| INFO | DefaultCamelContext.java 2453 | Total 4 routes, of which 4 is started. 09:20| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.2 (CamelContext: camel-1) started in 0.344 seconds 09:20| INFO | MarkerIgnoringBase.java 95 | Java Articles Java Threads 09:20| INFO | MarkerIgnoringBase.java 95 | Added to 'Java Articles' 09:20| INFO | MarkerIgnoringBase.java 95 | Processing of Java Threads done 09:20| INFO | MarkerIgnoringBase.java 95 | Popular Articles Camel Content Based Router 09:20| INFO | MarkerIgnoringBase.java 95 | Added to 'Popular Articles' 09:20| INFO | MarkerIgnoringBase.java 95 | Processing of Camel Content Based Router done 09:20| INFO | MarkerIgnoringBase.java 95 | All Articles Spring Integration 09:20| INFO | MarkerIgnoringBase.java 95 | Added to 'All Articles' 09:20| INFO | MarkerIgnoringBase.java 95 | Processing of Spring Integration done
Nested Content Based Routers
In this example, we define nested Content Based Routers.
Ok, What is nested Content Based Routers?
As the name suggests, one Content Based Router may contain another inner Content Based Router, that is, there is another inner choice()
in one of the processing steps of the when()
.
CamelNestedContentBasedRouterExample:
package com.javarticles.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; public class CamelNestedContentBasedRouterExample { public static final void main(String[] args) throws Exception { CamelContext camelContext = new DefaultCamelContext(); try { camelContext.addRoutes(new RouteBuilder() { public void configure() { from("direct:start") .choice() .when(simple("${body} contains 'Java'")) .to("direct:javaArticles") .log("Added to 'Java Articles'") .when(simple("${header.views} > 10000")) .to("direct:popularArticles") .log("Added to 'Popular Articles'") .otherwise() .to("direct:allArticles") .log("Added to 'All Articles'") .end() .log("Processing of ${body} done"); from("direct:javaArticles") .log("Java Articles") .choice() .when(simple("${header.views} > 10000")) .to("direct:popularJavaArticles") .log("Added to 'Popular Java Articles'") .otherwise() .to("direct:allArticles") .log("Added to 'All Articles'"); from("direct:popularArticles") .log("Popular Articles") .to("stream:out"); from("direct:allArticles") .log("All Articles") .to("stream:out"); from("direct:popularJavaArticles") .log("Popular Java Articles") .to("stream:out"); } }); ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("direct:start", "Java Threads"); template.sendBodyAndHeader("direct:start", "Java Collections", "views", 20000); template.sendBodyAndHeader("direct:start", "Camel Content Based Router", "views", 20000); template.sendBody("direct:start", "Spring Integration"); } finally { camelContext.stop(); } } }
As you can see from above, we have defined the inner choice()
in its own route instead of defining it in the main route as this will help readability.
Output:
09:14| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://start] 09:14| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[direct://javaArticles] 09:14| INFO | DefaultCamelContext.java 3164 | Route: route3 started and consuming from: Endpoint[direct://popularArticles] 09:14| INFO | DefaultCamelContext.java 3164 | Route: route4 started and consuming from: Endpoint[direct://allArticles] 09:14| INFO | DefaultCamelContext.java 3164 | Route: route5 started and consuming from: Endpoint[direct://popularJavaArticles] 09:14| INFO | DefaultCamelContext.java 2453 | Total 5 routes, of which 5 is started. 09:14| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.2 (CamelContext: camel-1) started in 0.373 seconds 09:14| INFO | MarkerIgnoringBase.java 95 | Java Articles 09:14| INFO | MarkerIgnoringBase.java 95 | All Articles Java Threads 09:14| INFO | MarkerIgnoringBase.java 95 | Added to 'All Articles' 09:14| INFO | MarkerIgnoringBase.java 95 | Added to 'Java Articles' 09:14| INFO | MarkerIgnoringBase.java 95 | Processing of Java Threads done 09:14| INFO | MarkerIgnoringBase.java 95 | Java Articles 09:14| INFO | MarkerIgnoringBase.java 95 | Popular Java Articles Java Collections 09:14| INFO | MarkerIgnoringBase.java 95 | Added to 'Popular Java Articles' 09:14| INFO | MarkerIgnoringBase.java 95 | Added to 'Java Articles' 09:14| INFO | MarkerIgnoringBase.java 95 | Processing of Java Collections done 09:14| INFO | MarkerIgnoringBase.java 95 | Popular Articles Camel Content Based Router 09:14| INFO | MarkerIgnoringBase.java 95 | Added to 'Popular Articles' 09:14| INFO | MarkerIgnoringBase.java 95 | Processing of Camel Content Based Router done 09:14| INFO | MarkerIgnoringBase.java 95 | All Articles Spring Integration 09:14| INFO | MarkerIgnoringBase.java 95 | Added to 'All Articles' 09:14| INFO | MarkerIgnoringBase.java 95 | Processing of Spring Integration done
Content Based Router using Spring DSL
You can define the Content Based Routing in spring DSL using <choice>
, <when>
and <otherwise>
as shown below.
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd "> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:start" /> <choice> <when> <simple>${body} contains 'Java'</simple> <to uri="direct:javaArticles" /> <log message="Added to 'Java Articles'" /> </when> <when> <simple>${header.views} > 10000</simple> <to uri="direct:popularArticles" /> <log message="Added to 'Popular Articles'" /> </when> <otherwise> <to uri="direct:allArticles" /> <log message="Added to 'All Articles'" /> </otherwise> </choice> <log message="Processing of ${body} done" /> </route> <route> <from uri="direct:javaArticles" /> <log message="Java Articles" /> <to uri="stream:out" /> </route> <route> <from uri="direct:popularArticles" /> <log message="Popular Articles" /> <to uri="stream:out" /> </route> <route> <from uri="direct:allArticles" /> <log message="All Articles" /> <to uri="stream:out" /> </route> </camelContext> </beans>
Let’s test the spring DSL.
CamelContentBasedRouterExampleUsingSpring:
package com.javarticles.camel; import org.apache.camel.CamelContext; import org.apache.camel.ProducerTemplate; import org.apache.camel.spring.SpringCamelContext; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class CamelContentBasedRouterExampleUsingSpring { public static final void main(String[] args) throws Exception { ApplicationContext appContext = new ClassPathXmlApplicationContext( "applicationContext.xml"); CamelContext camelContext = SpringCamelContext.springCamelContext( appContext, false); try { ProducerTemplate template = camelContext.createProducerTemplate(); camelContext.start(); template.sendBody("direct:start", "Java Threads"); template.sendBodyAndHeader("direct:start", "Camel Content Based Router", "views", 20000); template.sendBody("direct:start", "Spring Integration"); } finally { camelContext.stop(); } } }
Output:
09:28| INFO | DefaultCamelContext.java 3164 | Route: route1 started and consuming from: Endpoint[direct://start] 09:28| INFO | DefaultCamelContext.java 3164 | Route: route2 started and consuming from: Endpoint[direct://javaArticles] 09:28| INFO | DefaultCamelContext.java 3164 | Route: route3 started and consuming from: Endpoint[direct://popularArticles] 09:28| INFO | DefaultCamelContext.java 3164 | Route: route4 started and consuming from: Endpoint[direct://allArticles] 09:28| INFO | DefaultCamelContext.java 2453 | Total 4 routes, of which 4 is started. 09:28| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.2 (CamelContext: camel-1) started in 0.261 seconds 09:28| INFO | DefaultCamelContext.java 2418 | Apache Camel 2.15.2 (CamelContext: camel-1) is starting 09:28| INFO | DefaultCamelContext.java 2453 | Total 4 routes, of which 4 is started. 09:28| INFO | DefaultCamelContext.java 2454 | Apache Camel 2.15.2 (CamelContext: camel-1) started in 0.000 seconds 09:28| INFO | MarkerIgnoringBase.java 95 | Java Articles Java Threads 09:28| INFO | MarkerIgnoringBase.java 95 | Added to 'Java Articles' 09:28| INFO | MarkerIgnoringBase.java 95 | Processing of Java Threads done 09:28| INFO | MarkerIgnoringBase.java 95 | Popular Articles Camel Content Based Router 09:28| INFO | MarkerIgnoringBase.java 95 | Added to 'Popular Articles' 09:28| INFO | MarkerIgnoringBase.java 95 | Processing of Camel Content Based Router done 09:28| INFO | MarkerIgnoringBase.java 95 | All Articles Spring Integration 09:28| INFO | MarkerIgnoringBase.java 95 | Added to 'All Articles' 09:28| INFO | MarkerIgnoringBase.java 95 | Processing of Spring Integration done
Download the source code
This was an example about Camel Content Based Routing.