Thursday 9 June 2016

How to Configure and Use Apache Camel with Spring

 1. Overview


This article will help you to configure and use Apache Camel with Spring Framework.

Apache Camel implements Enterprise Integration Patters.  If you want to explore EIP concept in detail, you can read this book written by Gregor Hohpe and and Bobby Woolf, who conceptualize the Enterprise Integration Patters.
Apache Camel provides many useful components like JPAHibernateFTPApache-CXFApache CXF-REST,  AWS-S3 and many more. Basically these components are useful in integrating data between two different systems. For eg. Pull data from database and send it to another system over REST API calls.


In this tutorial, for simplicity purpose we will use Apache Camel's File component and Apache Camel version 2.16.1 with Spring version 4.2.4.RELEASE.

We will use Apache Camel to perform following task:
  • Read file from source directory.
  • Convert file content to UpperCase using custom Processor.
  • Write converted output to destination directory.
  • Convert file content to LowerCase using Camel Translator Feature.
  • Write converted output to destination directory.
We will follow these steps to develop and run this application:
  • Create Project skeleton using maven.
  • Add Apache Camel dependencies to pom file.
  • Create Camel Context file.
  • Define Camel Route for converting file content to UpperCase using custom processor.
  • Update Camel Route for converting file content to LowerCase using Camel's Message Translator.
  • Create ApplicationRunner class with main method to load and run Camel Context.
  • Create input and output directories.
  • Build application and run Camel Context.

2. Create Maven Project


Let's start with generating project artifacts using maven command. Run following command to generate project skeleton.
mvn archetype:generate -DgroupId=org.apache.camel -DartifactId=ApacheCamelFileProcessor -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Once this command is runs successfully, you can see generated project directory ApacheCamelFileProcessor.

3. Add Maven Dependencies


Add following dependencies to to ApacheCamelFileProcessor/pom.xml file.

<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/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>org.apache.camel</groupId>
 <artifactId>ApacheCamelFileProcessor</artifactId>
 <packaging>jar</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>ApacheCamelFileProcessor</name>
 <url>http://maven.apache.org</url>
 <properties>
  <env.camel.version>2.16.1</env.camel.version>
  <env.spring.version>4.2.4.RELEASE</env.spring.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-core</artifactId>
   <version>${env.camel.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-spring</artifactId>
   <version>${env.camel.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-stream</artifactId>
   <version>${env.camel.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${env.spring.version}</version>
  </dependency>
 </dependencies>
</project>


Once pom file is updated with these dependencies  you need to run following maven build command to download jar files.

mvn clean install

4. Camel Context file


Create Spring Context file where we will define Camel Routes later. Create file ApacheCamelFileProcessor/src/main/resources/camel-context.xml. This is content to your context file with all required Apache Camel and Spring namespaces and schema locations.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
  http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

 <camelContext xmlns="http://camel.apache.org/schema/spring">
        <!-- Add routes here -->
 </camelContext>

</beans>

This <camelContext> element represents Camel Context which we can compare with Spring Application Context. Now your context file is ready to start defining Camel Routes.

5. Camel Route file.


Now we will write our first route to convert file content to UpperCase.
We need to define source from where route will read data, which can be database, file, console etc. In our case it will be file. eg. <from uri="file:input_directory_location" />
Then we need to define the processor of the data read from source. We are going to write custom processor class in our case. This custom processor class will be a spring bean which will implement standard Camel Processor Interface. eg. <process ref="customProcessorbeanId" />
Once data is processed we need to tell route to where to store the processed data which can again be anything like database, file or display on console. In our case we are going to store it in file. eg. <to uri="file:output_directory_location" />
This is how your your camel-context.xml file will look like with route.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
  http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

 <camelContext xmlns="http://camel.apache.org/schema/spring">
  
  <route customId="true" id="rout1">
   <!-- Read files from input directory -->
   <from uri="file://data/input" />
   <!-- Transform content to UpperCase -->
   <process ref="myFileProcessor" />
   <!-- Write converted file content -->
   <to uri="file://data/outputUppperCase" />
  </route>
 
 </camelContext>
 <bean id="myFileProcessor" class="org.apache.camel.processor.FileProcessor" />
</beans>

We need to create those directories mentioned in URI's and put some files in input directory. We will create them before running application.

5.1. Create Custom Processor


Create class org.apache.camel.processor.FileProcessor which is mentioned in camel-context.xml file as bean.
Now implement org.apache.camel.Processor interface which is standard processor interface provided by Apache Camel. After implementing this interface we need to define its process(Exchange exchange) method. This Exchange object holds all details of data read from source.
Then we need to read content of the message (file content in our case) and do processing on that content. Once processing is completed we will set the new content to Exchange object.
This is the Custom Processor for reading the file content and converting it to UpperCase and setting it on Exchange object.
package org.apache.camel.processor;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;

public class FileProcessor implements Processor {

 public void process(Exchange exchange) throws Exception {
  //Read file content
  String originalFileContent = (String)exchange.getIn().getBody(String.class);
  
  //Convert file content to upper case.
  String upperCaseFileContent = originalFileContent.toUpperCase();
  
  //Update file content.
  exchange.getIn().setBody(upperCaseFileContent);
 }

}
This process method will get executed for every input received from source.

6. Update Camel Route for converting content to lowercase.


We will update Camel route to convert same file content to lowerCase. However for converting data to lowerCase we will not create custom processor. Instead we will use Apache Camel's Message Translator feature to convert data to lowerCase.
Once data is converted to lowerCase using Message Translator, we need to define the destination where converted data will be stored.
This is the updated Camel Route in camel-context.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
  http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

 <camelContext xmlns="http://camel.apache.org/schema/spring">
  
  <route>
   
   <!-- Read files from input directory -->
   <from uri="file://data/input" />   
   <!-- Transform content to UpperCase using custom processor -->
   <process ref="myFileProcessor" />   
   <!-- Write converted file content -->
   <to uri="file://data/outputUppperCase" />
   
   <!-- Transform content to LowerCase using message translator -->
   <transform>
    <simple>${body.toLowerCase()}</simple>
   </transform>   
   <!-- Write converted file content -->
   <to uri="file://data/outputLowerCase" />   
  </route>
 
 </camelContext>

 <bean id="myFileProcessor" class="org.apache.camel.processor.FileProcessor" />
</beans>

7. Create Application Runner.

Now let's create application runner to run this application. This class will load Camel context file. As this is Spring context we will load it exactly same way as we load Spring context file.
Create class org.apache.camel.main.App with main method to load camel-context.xml file as follow.

package org.apache.camel.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(final String[] args) throws Exception {
     //Load application context
     ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("camel-context.xml");
        Thread.sleep(5000);
        applicationContext.close();
    }
}

8. Create Input and Output Directories.


Create following directories mentioned in Camel Route in camel-context.xml file.
  • ApacheCamelFileProcessor/data/input
  • ApacheCamelFileProcessor/data/outputLowerCase
  • ApacheCamelFileProcessor/data/outputUppperCase
Create sample input file as ApacheCamelFileProcessor/data/input/sample.txt with data:
THIS IS UPPERCASE CONTENT. this is lowecase content.

9. Build and Run Application.


To build this application execute following maven command in ApacheCamelFileProcessor directory.
mvn clean install
Now let's run this application. To run this application you can either run our main class org.apache.camel.main.App from your IDE or you can execute following maven command:
mvn exec:java -Dexec.mainClass="org.apache.camel.main.App"
Once application run successfully, you can find following:
ApacheCamelFileProcessor/data/outputUppperCase/sample.txt with following content:
THIS IS UPPERCASE CONTENT. THIS IS LOWECASE CONTENT.
ApacheCamelFileProcessor/data/outputLowerCase/sample.txt with following content:
this is uppercase content. this is lowecase content.

Download complete project from Git repository.



4 comments: