Apache Camel Content Based Routing

0

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:

  1. Maven 3.2.3
  2. Apache Camel 2.15.1
  3. Spring 4.1.5.RELEASE
  4. 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:

  1. camel-core – camel core components like timer, bean etc
  2. slf4j-api – in case you want to use log
  3. slf4j-log4j12 – if you want to use log4j as the slf4j implementation
  4. camel-stream – for printing the messages to console
  5. spring-context – for spring support
  6. camel-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.

You can download the source code here: camelContentBasedRoutingExample.zip
Share.

Comments are closed.