Introduction to Apache Camel

Introduction to Apache Camel

In a recent AEM project I was introduced to Apache Camel, a solution for migrating content from one endpoint/platform to another. As it applies to an AEM migration, a Camel implementation may be vital to saving time and resources, particularly in cases where the amount of content to migrate is enormous, where it would be prohibitively tedious for authors to attempt recreating pages by hand in AEM’s Site Author mode.

Camel uses abstraction and uniformity to bring content from one area to another, in a repeatable way without over-customization. The goal is all about not reinventing the wheel, allowing developers to 1)write simple statements and 2)avoid having to build lower-level functionality such as XML parsing and retry logic. Basic themes I will discuss are EIPs, DSLs, Routes, Processors, Components, and automated testing.

Enterprise Integration Patterns
Enterprise Integration Patterns (EIPs) establish a common vocabulary of things you would want to do when transferring information. As an example, let’s say I want to delay the sending of a message (Delayer EIP), or split the message into parts each of which should be processed differently (Splitter EIP). Enterprise Integration Patterns are deliberately abstract and apply to most imaginable scenarios. Often they're used to assist in Routes. Click for a list of EIPs.

Domain-Specific Languages
Domain-specific languages (DSLs) are supported languages that define the integration logic. I am most familiar with Java DSL (as shown in the examples below), but routes can be written in Spring XML DSL, Scala DSL, and others. Click for a current list of Camel’s supported DSLs.

The easiest way to get started is to use a Maven archetype (here's a comprehensive list of archetypes). You can also easily add Maven dependencies if you need more supported functionality. For example, the Java Message Service (JMS) is an API that conveniently standardizes creation and transmission of messages. To use it you need to add dependencies for 1)the JMS component and 2)a ConnectionFactory from a JMS provider like Apache ActiveMQ. (See here for more JMS providers.)

In Java the program always begins at a main method. Here we set the context and add routes, then start, and then stop.

public class myMainClass {
	public static void main(String args[]) throws Exception {
		CamelContext context = new DefaultCamelContext();
		context.addRoutes(new MyRouteBuilder());

Routes extend the Routebuilder class and override the configure() method. The route begins at a “from” endpoint and finishes at one or more “to” endpoints, including any necessary processing logic in between. There can be more than one .from/.to route within the same configure() method.

public class MyRouteBuilder extends RouteBuilder {
	public void configure() throws Exception {
			.process(new MyProcessor())

In Camel, the same syntax and concepts apply no matter what the technology. Every developer can figure out what the code does, and not have to mess with lower-level custom code if a change is needed. Theoretically we’d only have to change "file:data/myDestination" to “jms:queue:myDestination”, if we decide to send to a JMS queue instead of to a File.

Processors implement the Processor class and override the process(Exchange exchange) method. The “exchange” parameter is the container for the message that is being processed or transformed. Processors add custom logic where needed; notice the .process in the code example above.

public class myProcessor implements Processor {
	public void process(Exchange exchange) throws Exception {
		Object body = exchange.getIn().getBody();
		if (body != null) {
			//TO-DO: manipulate incoming message

An alternative to a Processor class is a Bean, or POJO (“plain old Java object”). See the “MyBean” heading here. A Bean also does processing logic but with different syntax.

Components add another layer of abstraction and may be very convenient (once again, not reinventing the wheel). You can leverage existing components, or build your own custom ones. For example, if I want to send and receive files over FTP with added options, I use ftp:contextPath[?options]. This is a complete list of available components in Apache Camel.

Automatic unit and integration tests are also available. To harness Camel’s testing capabilities, the test class must extend CamelTestSupport. Tests can be run the same as JUnit tests, in the IDE or inside a build script. One useful thing (among others) is that mocks are implicitly supported. No other mock framework such as EasyMock or Mockito is required.

To review, Apache Camel removes a multitude of obstacles that would be present in creating a custom migration program from the ground up. Alternative solutions include Spring Integration and Mule; they too perform standardized integrations using EIPs, and function in the Java Virtual Machine environment. Apache Camel is strong in the number of DSLs it can support, plus components ready-made for almost every imaginable technology. A technical comparison of the three is on Kai Wähner’s blog here. More information on Camel alternatives here.

I ordered two books that were very helpful along the way, and they will remain in our library at the 6D Center of Excellence!

Share this post


comments powered by Disqus