Sunday, March 14, 2010

Camel framework introduction - Part 1

The issue of systems integration
In IT domain, we often have lots of heterogeneous systems which don't understand each other (different technologies, different communcation protocols, etc.).
But this is required and this is a need to be able to link those systems together, because systems which are not connected to each other have limited interest.

This raises many issues as data format, routes, monitoring, etc.
For instance, how do we do to connect two applications, where the first one speak old school CSV file although the second one does only understand XML over JMS ?

Entreprise Integration Patterns
Apache Camel is an integration framework, which implements EIP (Entreprise Integration Pattern) defined by Gregor Hohpe & Bobby Woolf.
EIP are integration patterns which enable us to resolv issues with proven solutions.
Camel framework supports about 50 EIP.


Endpoints
Endpoints represent systems, physical ressources, virtual ressources, etc.
For example, we have endpoints HTTP, JMS, FTP to interface with different protocols, but also endpoints Direct, Seda to be able to communicate into a same Camel context (we'll be back to this point).
2 types of Endpoints :
  • provider
  • consumer

Examples
  • Invoices directory: file://invoices/032010
  • Invoices JMS queue: jms://zenika/invoices

Routes
A route (path between 2 endpoints) can be very simple, or very complex as well (data transformation, multicast, messages filters, etc).
Routes enable us to route messages from origin to destination.

Camel can configure routes with 2 methods :
  • XML XBean configuration
  • DSL using (Domain Specific Language)


For example, this is a read of a file from a directory, then the write of this file into an other directory (very simple route) :
XML Method

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/bean
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="file://C://invoices//in" />
   <to uri="file://C://invoices//out" />
  </route>
 </camelContext>
</beans>


DSL Method
1. Java packages to scan listing (camel-context.xml file)


<beans xmlns="http://www.springframework.org/schema/beans" xsi="http://www.w3.org/2001/XMLSchema-instance" 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">
  <packagescan>
   <package>com.zenika.camel.routes</package>
  </packagescan>
 </camelcontext>
</beans>


2. Routes coding

package com.zenika.camel.routes;

import org.apache.camel.builder.RouteBuilder;

public class InvoicesRoute extends RouteBuilder {

 @Override
 public void configure() throws Exception {
   from("file://C://invoices//in").to("file://C://invoices//out");
 }
}


DSL way is less verbose and simpler to maintain.
You only have to define Java packages to be scanned, and have to code routes in Java with the DSL.

This way is also type safe, and then much more secured than the XML way.
Indeed, it's impossible to code an operation which is not supported (compilation error).

Furthermore, all Camel syntax is fully supported in the XML way.


Camel context, heart of the framework
In order to use our route, we need a Camel context.
This context loads, configures and executes routes. This is the engine of the framework.
The framework is not dedicated to be used in standalone mode (except for testing purpose).
Camel must be used inside a container (ServiceMix, ActiveMQ, CXF or Tomcat).

Here is a simple example to create the Camel context :

package com.zenika.camel.test;

import org.apache.camel.CamelContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Tester {
 public static void main(String... args) throws Exception {

  BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/camel-context.xml");
  CamelContext camelContext = (CamelContext) beanFactory.getBean("camelContext");

  camelContext.start();
  Thread.sleep(2000); // to have time to run the route
  camelContext.stop();
 }
}


With those few code lines, we have set up a route which copies all files from the invoices/in to the invoices/out directory.

We'll see next time other endpoints (as the Direct), and routes more complex as well, with data transformation and routing logic.