Introduction to Apache Camel

Apache Camel is a versatile open-source integration framework based on known Enterprise Integration Patterns.

I thing this is enough to decide whether to read or not to read this article. If you thing lightweight Integration framework could be something interesting but you need  further readingo to decide, so maybe the shortest path is to look at  Stackoverflow discussion about what actually Apache Camel is. Read short introduction to Apache Camel with example below.

Basics

Apache Camel is java library and engine which is well situated for different Integration patterns. However Camel is not BPMN Engine or ESB but it could be under the hood implementation of such products. Apache Camel is a programmers tool for mediation and integration problems. Let's understand it by looking on the entities.

Entities

Lets' start by basic Camel entities: Message and Exchange.

Message

org.apache.camel.Message - is the fundamental entity containing the data being carried and routed in Camel. Massages are contained out of

  • Unique Identifier: of type java.lang.String .
  • Headers may provide some hints about content. Headers are organized as name-value pairs. The name is a unique, case-insensitive string, and the value is of type java.lang.Object.
  • The body is of type java.lang.Object . It  means that it’s up to you  to make sure that the receiver can understand the content of the message. When the sender and receiver use different body formats you can use a number of camel mechanisms to transform the data into an specific format. In many cases the conversion can happen automatically with pre-defined type converters.
  • The fault flag it is a bit special thing to distinguish between normal and fault returns as defined by some Standards (e.g. WSDL).

Exchange

org.apache.camel.Exchange is abstraction for an exchange of messages  as part of a "conversation". Below are components of a such conversation, that make this abstraction more comprehensive.

  • Exchange ID
  • MEP a particular Message Exchange Pattern like InOnly or InOut. When the pattern is InOnly, the exchange contains only IN- Message.
  • Exception when it occurs at any time during routing.
  • Properties  are similar to message headers, but they last for the duration of the entire exchange also camel may add some properties to a particular exchange.
  • IN-Message  or request message is mandatory.
  • OUT-Message or replay message exists if the MEP is defined as InOut.

Camel Context

Now let's look on the big picture. We see different architectural pieces connecting to each other and the glue between them is actually Camel Context. It's a kind of a container that puts the entities together, sometimes it's called Camel Run-time.

Camel Context

Endpoint

Fundamental concept in Camel. Endpoint  as endpoint of  a channel through which a system can send or receive messages. In Camel endpoints are configured by URIs. At run-time Camel will look up an endpoint based on the URI notation. This is one of very mighty but still comprehensive and maintainable. Let's look on some examples:

//Pooling on data/inbox every 2 seconds file:data/inbox?delay=2000 
//JMS queendpoid with name order jms:queue:order 
//Run's external Application with output.txt as parameter. 
exec:archiver.exe?output.txt  

Component

Components are associated with The Endpoints URI, they are connected by Shema (like file: , jms: )  and act as  a factory of endpoints. There are over 80 Camel Componets currently and of course one can build custom component. Start by extending org.apache.camel.impl.DefaultComponent.

Route

Route defines path or a channel how a Message actually moves through the system. The routing engine self isn’t exposed to the developer, but developer defines routes and trust the engine all the heavy lifting work (and boilerplate coding). Each route has a unique identifier that can be used for logging, debugging, monitoring, and starting and stopping routes.

Routes also have exactly one input source for messages, therefore they’re effectively tied to an input endpoint. Routes a defined in domain specific language (DSL). Camel provides java, scala and XM based Route-DSL.

//simple route. 
from("file:data/inbox").to("jms:queue:order")  

routing can get very flexible and defined by filters, multicasting, recipient lists, parallelism and more. Since i want this article be a short introduction i give you just some more commented example. One of the interesting connection solution is the usage of "direct:" schema, which provides direct, synchronous invocation of any consumers when receives call from producer.

//Every 10 seconds timer sends an Exchange to direct:prepare 
from("timer://foo?fixedRate=true&period=10000").to("direct:prepare");  
// Onother Routes can begin from "direct:prepare" // This now depends on timer, logging and putting a message to the queue. from(direct:prepare).to("log:com.mycompany.order?level=DEBUG")
.to("jms:queue:order?jmsMessageType=Text"); 

Processor

org.apache.camel.Processor is a Message consumer of Message Exchange. Processors are of course elements of Routes and can be used for message format translation or other transformation.

Processor myProcessor = new Processor() {  
    public void process(Exchange exchange) {
        exchange.getBody();
        //e.g do something with Body..
    }
};

from("file:data/inbox").filter(header("foo").isEqualTo("bar"))  
    .process(myProcessor).to("jms:queue:order")

As we see processors can be used to various data transformations.

Example

Create new Camel project with maven (Camel archetypes overwiev). Next maven call will create sample project.

mvn  archetype:generate -DgroupId=org.holbreich -DartifactId=filecopy -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -Dversion=1.0.0-SNAPSHOT  

This project contains following source code:

package org.holbreich.filecopy;  
import org.apache.camel.main.Main;

public class MainApp {  
/**
* A main() so we can easily run these routing rules in our IDE
*/
public static void main(String... args) throws Exception {  
   Main main = new Main();
   main.enableHangupSupport();
   main.addRouteBuilder(new MyRouteBuilder());
   main.run(args);
   }
}

and

package org.holbreich.filecopy;  
import org.apache.camel.builder.RouteBuilder;

/**
* A Camel Java DSL Router
*/
public class MyRouteBuilder extends RouteBuilder {

/**
* Let's configure the Camel routing rules using Java code...
*/
public void configure() {  
    // here is a sample which processes the input files
    // (leaving them in place - see the 'noop' flag)
    // then performs content based routing on the message using XPath
    from("file:src/data?noop=true")
      .choice()
       .when(xpath("/person/city = 'London'"))
        .to("file:target/messages/uk")
        .otherwise()
      .to("file:target/messages/others");
  }
}

This example is runnable already, try it out!

Please feel free to ask your questions...