Apache Camel

Apache Camel Routing Tutorial

1.Introduction

Data that are exchanged between companies have increased a lot. The number of applications, which must be integrated, is increasing too. The interfaces use different technologies, protocols and data formats. Nevertheless, the integration of these applications shall be modeled in a standardized way, realized efficiently and supported by automatic tests. Such a standard exists with the Enterprise Integration Patterns (EIP), which have become the industry standard for describing, documenting and implementing integration problems. Apache Camel implements the EIPs and offers a standardized, internal domain-specific language (DSL) to integrate applications. This article gives an introduction to Apache Camel including several code examples.

2. What is Enterprise Integration Patterns

As the name implies, these are tested solutions for specific design problems encountered during many years in the development of IT systems. And what is all the more important is that they are technology-agnostic which means it does not matter what programming language or operating system you use.
EIPs can be used to split integration problems into smaller pieces and model them using standardized graphics. Everybody can understand these models easily. Besides, there is no need to reinvent the wheel every time for each integration problem.

Patterns are divided into seven sections:
1. Messaging Systems
2. Messaging Channels
3. Message Constructions
4. Message Routing
5. Message Transformation
6. Messaging Endpoints
7. System management

Using EIPs, Apache Camel closes a gap between modeling and implementation. There is almost a one-to-one relation between EIP models and the DSL of Apache Camel.

3. Basic concepts about Apache Camel

Apache Camel is an open source project and implementation of famous Enterprise Integration Patterns. The core of Apache Camel is very small and just contains commonly used components (i.e. connectors to several technologies and APIs) such as Log, File, Mock or Timer.

Further components can be added easily due to the modular structure of Apache Camel. Maven is recommended for dependency management because most technologies require additional libraries. Though, libraries can also be downloaded manually and added to the classpath, of course.

The core functionality of Apache Camel is its routing engine. It allocates messages based on the related routes. A route contains flow and integration logic. It is implemented using EIPs and a specific DSL. Each message contains a body, several headers, and optional attachments. The messages are sent from a provider to a consumer. In between, the messages may be processed, e.g. filtered or transformed.

Messages between a provider and a consumer are managed by a message exchange container, which contains a unique message id, exception information, incoming and outgoing messages (i.e. request and response), and the used message exchange pattern (MEP). In-Only MEP is used for one-way messages such as JMS whereas In-Out MEP executes request-response communication such as a client-side HTTP based request and its response from the server side.

After the briefly explaining of the basic concepts of Apache Camel, the following sections will give more details and code examples.

3.1 The Architecture of Apache Camel

Camel uses a Java-based Routing Domain Specific Language (DSL) or an XML Configuration to configure routing and mediation rules which are added to a CamelContext to implement the various Enterprise Integration Patterns.

At a high-level Camel consists of a CamelContext which contains a collection of Component instances. A Component is essentially a factory of Endpoint instances. You can explicitly configure Component instances in Java code or an IoC container like Spring or Guice, or they can be auto-discovered using URIs.

An Endpoint acts rather like a URI or URL in a web application or a Destination in a JMS system; you can communicate with an endpoint; either sending messages to it or consuming messages from it. You can then create a Producer or Consumer on an Endpoint to exchange messages with it.

The DSL makes heavy use of pluggable Languages to create an Expression or Predicate to make a truly powerful DSL which is extensible to the most suitable language depending on your needs.

To get the detailed information about the architecture, use this link http://camel.apache.org/architecture.html

3.2 What is CamelContext

The CamelContext is the runtime system of Apache Camel and connects its different concepts such as routes, components or endpoints.

Below are the steps that we need to consider while configuring the CamelContext:

  1. Create CamelContext.
  2. Add endpoints or components.
  3. Add Routes to connect the endpoints.
  4. Invoke CamelContext.start() – This starts all the camel-internal threads which are responsible for receiving, sending and processing messages in the endpoints.
  5. Lastly, invoke CamelContext.stop() when all the messages are exchanged and processed. This will gracefully stop all the camel-internal threads and endpoints.

The following code snippet shows a Java main method, which starts the CamelContext and stops it after 30 seconds. Usually, the CamelContext is started when loading the application and stopped at shutdown.

CamelStarter.java

public class CamelStarter {
public static void main(String[] args) throws Exception {
	CamelContext context = new DefaultCamelContext();
	context.addRoutes(new IntegrationRoute());
	context.start();
	Thread.sleep(30000);
	context.stop();
	}
}

3.3 What is Routes

Routes are a crucial part of Apache Camel. The flow and logic of an integration is specified here. The following example shows a route using Java DSL:

MyFirstRouterBuilder.java

import org.apache.camel.builder.RouteBuilder;

public class MyFirstRouterBuilder extends RouteBuilder {
     @Override
    public void configure() throws Exception {
        try{
            from( "file:d:/vids").to("file:d:/temp");
        }catch(Exception e){

        }
     }
}

The DSL is easy to use. Everybody should be able to understand the above example without even knowing Apache Camel. The route realizes a part of the described use case. Orders are put in a file directory from an external source. The orders are processed and finally moved to the target directory.

Routes have to extend theRouteBuilder class and override the configure method. The route itself begins with a from endpoint and finishes at one or more to endpoints. In between, all necessary process logic is implemented. Any number of routes can be implemented within one configure method.

The following snippet shows the same route realized via Spring XML DSL:

applicationcontext.xml

<beans … >
<bean class="mwea.TransformationBean" id="transformationBean"/>
<bean class="mwea.LoggingProcessor" id="loggingProcessor"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<package>mwea</package>
<route>
        <from uri="file:target/inbox"/>
                    <process ref="loggingProcessor"/>
                    <bean ref="transformationBean"/>
        <to uri="file:target/outbox"/>
    </route>
</camelContext>
</beans>

3.4 What is Components

In the meantime, over 100 components are available. Besides widespread technologies such as HTTP, FTP, JMS or JDBC, many more technologies are supported, including cloud services from Amazon, Google, GoGrid, and others. New components are added in each release. Often, also the community builds new custom components because it is very easy.

The most amazing feature of Apache Camel is its uniformity. All components use the same syntax and concepts. Every integration and even its automatic unit tests look the same. Thus, complexity is reduced a lot. Consider changing the above example: If orders should be sent to a JMS queue instead of a file directory, just change the to endpoint from file:target/outbox to jms:queue:orders. That’s it! (JMS must be configured once within the application before, of course).

To get a feel of the versatility of Camel you can browse the list of Components and URIs it supports using the link http://camel.apache.org/components.html

4. Technology Stack

In this example we will be using following technology stack:

  1. Maven 4.0 – Build and dependency tool. You can visit here for more details
  2. Apache Camel 2.15.1 – Open-source integration framework based on known Enterprise Integration Patterns.
  3. Spring 4.1.5.RELEASE – Comprehensive programming and configuration model for modern Java-based enterprise applications
  4. Spring Tool Suite (STS) – An Eclipse-based development environment that is customized for developing Spring applications.
  5. ActiveMQ Binary Distributions – The latest stable release is the ActiveMQ 5.14.5 Release. See the Download Archives for all time releases.

5. Apache Camel Routing Examples

How to implement the different ways of Apache Camel Routing.

5.1 Dependencies

To continue using our example, we need to add the dependent jar files to the classpath. This can be achieved either by deploying directly the jar file or using the Maven. Since we are using Maven for our example we will be using the pom.xml for the dependency of the following jars:

  • Camel-Core
  • Camel-Stream
  • Camel-JMS
  • ActiveMQ-Camel
  • Camel-Spring
  • Spring-Context

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>org.springframework.samples</groupId>
  <artifactId>AMQP</artifactId>
  <version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-core</artifactId>
			<version>2.15.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-stream</artifactId>
			<version>2.15.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-jms</artifactId>
			<version>2.15.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-camel</artifactId>
			<version>5.6.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-pool</artifactId>
			<version>5.11.1</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.1</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>
	</dependencies>	
</project>

5.2 XML Request

The below XML request is used to send as an input message to a JMS Queue or Topic and consume messages from a JMS Queue or Topic.

order.xml

<?xml version="1.0" encoding="UTF-8"?>
<orders>
	<order product="electronics">
		<items>
			<item>Laptop</item>
			<item>Mobile</item>
		</items>
	</order>
	<order product="books">
		<items>
			<item>Design Patterns</item>
			<item>XML</item>
		</items>
	</order>
</orders>

5.3 Spring XML-Based Configuration

The Camel Spring XML Extensions allow you to use a very concise XML syntax to describe your Camel configuration when you are using Spring to wire together your application.

SpringXMLRoute.java

package com.camelrouting;

import java.io.FileInputStream;
import java.io.InputStream;

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 SpringXMLRoute {

	public static void main(String[] args) throws Exception { 
	ApplicationContext appContext = new ClassPathXmlApplicationContext(
            "SpringXMLRouteContext.xml");
    CamelContext camelContext = SpringCamelContext.springCamelContext(
            appContext, false);
    try {            
        camelContext.start();
        ProducerTemplate template = camelContext.createProducerTemplate();
        InputStream orderxml = new FileInputStream("src/main/resources/order.xml");
        template.sendBody("direct:SpringXMLRouteStart", orderxml);
    } finally {
        camelContext.stop();
    }

	}

}

Application Context File to filter routing message to the external file.

SpringXMLRouteContext.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:SpringXMLRouteStart" />
			<log message="Split by article Element"/>
			
			<!--To printout the filter routing message to the external file  -->
			<split>
				<xpath>//order[@product='electronics']/items</xpath>
				<to uri="file:src/main/resources/orderxmlroute/"  />
			</split>
		</route>
	
	</camelContext>

</beans>

Application Context File to print out the routing message on the IDE console.

SpringXMLRouteContext.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:SpringXMLRouteStart" />
			<!-- To printout the routing message on the IDE console  -->
			<to uri="stream:out" /> 
		</route>
	
	</camelContext>

</beans>

Application Context File to configure Active MQ Messaging Queue.

SpringXMLRouteContext.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
       ">
       
	<!--The Active MQ messaging Queue configuration  -->    
	<!-- Active MQ WebConsole URL : http://localhost:8161/ -->   
	
	<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://localhost:61616/" />
	</bean>
	<bean id="jmsConfig" 
	   class="org.apache.camel.component.jms.JmsConfiguration">
	   <property name="connectionFactory" ref="jmsConnectionFactory"/>
	   <property name="concurrentConsumers" value="10"/>
	</bean>   
    <bean id="activemq"
            class="org.apache.activemq.camel.component.ActiveMQComponent">
            <property name="configuration" ref="jmsConfig"/>
    </bean>
    
       
       
       
	<camelContext xmlns="http://camel.apache.org/schema/spring" >
		<route>
			<from uri="direct:SpringXMLRouteStart" />
			<log message="Split by article Element"/>
	
			<!--To send the filter routing message to the Messaging Queue  -->
			<!-- <choice>
	            <when>
	                <xpath>//order[@product='electronics']/items</xpath>
	                <to uri="activemq:queue:Q1"/>
	            </when>
	            <when>
	                <xpath>//order[@product='books']/items</xpath>
	                <to uri="activemq:queue:Q2"/>
	            </when>
	            <otherwise>
	                <to uri="activemq:queue:Q3"/>
	            </otherwise>
       	     </choice>
			
			
		</route>
	
	</camelContext>
</beans>

5.4 Java DSL-Based Configuration

Apache Camel offers a Java based DSL using the fluent builder style. The Java DSL is available by extending the RouteBuilder class and implement the configure method.

JavaDSLRoute Java Class to filter routing message to the external file.

JavaDSLRoute.java

package  com.camelrouting;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class JavaDSLRoute {
	
	public static void main(String[] args) throws Exception {
		CamelContext context = new DefaultCamelContext();
		
		try {
		
			context.addRoutes(new RouteBuilder() {
				@Override
				public void configure() throws Exception {
					from("direct:JavaDSLRouteStart").
				
					//To filter routing message to the external file 
						split(xpath("//order[@product='electronics']/items")).
						to("file:src/main/resources/orderxmlroute/");
				}
			});
			context.start();
			ProducerTemplate template = context.createProducerTemplate();
			InputStream orderxml = new FileInputStream("src/main/resources/order.xml");
			template.sendBody("direct:JavaDSLRouteStart", orderxml);
		} finally {
			context.stop();
		}
	}
}

JavaDSLRoute Java Class to route message on the IDE console.

JavaDSLRoute.java

package  com.camelrouting;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class JavaDSLRoute {
	
	public static void main(String[] args) throws Exception {
		CamelContext context = new DefaultCamelContext();
		
		try {
			context.addRoutes(new RouteBuilder() {
				@Override
				public void configure() throws Exception {
					from("direct:JavaDSLRouteStart").
					// To route message on the IDE console  
						to("stream:out");
				}
				});
			context.start();
			ProducerTemplate template = context.createProducerTemplate();
			InputStream orderxml = new FileInputStream("src/main/resources/order.xml");
			template.sendBody("direct:JavaDSLRouteStart", orderxml);
		} finally {
			context.stop();
		}
	}
}

6. Summary

Here in this Apache Camel Routing Example, we have learned about the different way to configure the camel route for different purposes as follows:

  • To filter routing message to the external file.
  • To print out the routing message on the IDE console.
  • To configure Active MQ Messaging Queue.

So, now you are ready to implement the routes in the Apache Camel applications.

7. References

  1. http://camel.apache.org/
  2. http://camel.apache.org/routes.html
  3. http://camel.apache.org/message-router.html
  4. http://camel.apache.org/enterprise-integration-patterns.html

8. Download the Spring Tool Suite Project

Download
You can download the full source code of this example here: CamelRoutes.zip

Simranjit Singh

Simranjit Singh has graduated from Computer Science Department of the Guru Nanak Dev University of Amritsar, Punjab, India. He also holds a Master degree in Software Engineering from the Birla Institute of Technology & Science of Pilani, Rajasthan, India. He works as a Senior Consultant in the e-commerce sector where he is mainly involved with projects based on Java and Big Data technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Gaurav
Gaurav
5 years ago

Did you forget about “IntegrationRoute”. I do not see mention about it, but just in one class

Anurag Telang
Anurag Telang
4 years ago

Buddy, its awesome… to the point. Thanks

Back to top button