I just announced the release of my "REST With Spring" Classes:
1. Overview
This article will demonstrate how to configure and use Apache Camel with Spring.
Apache Camel provides quite a lot of useful components that support libraries such as JPA, Hibernate, FTP, Apache-CXF, AWS-S3 and of course many others – all to help integrating data between two different systems.
For example, using the Hibernate and Apache CXF components, you could pull data from a database and send it to another system over REST API calls.
In this tutorial, we’ll go over a simple Camel example – reading a file and converting its contents to uppercase and then back to lowercase. We’re going to use Camel’s File component and Spring 4.2.
Here are the full details of the example:
- Read file from source directory
- Convert file content to uppercase using a custom Processor
- Write converted output to a destination directory
- Convert file content to lowercase using Camel Translator
- Write converted output to a destination directory
2. Add Dependencies
To use Apache Camel with Spring, you will need the following dependencies in your POM file:
<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>
So, we have:
- camel-core – the main dependency for Apache Camel
- camel-spring – enables us use Camel with Spring
- camel-stream – an optional dependency, which you can use (for example) to display some messages on the console while routes are running
- spring-context – the standard Spring dependency, required in our case as we are going to run Camel routes in a Spring context
3. Spring Camel Context
First, we’ll create the Spring Config file where we will later define our Camel routes.
Notice how the file contains 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-4.2.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-4.2.xsd"> <camelContext xmlns="http://camel.apache.org/schema/spring"> <!-- Add routes here --> </camelContext> </beans>
The <camelContext> element represents (unsurprisingly) the Camel context, which can be compared to a Spring application context. Now your context file is ready to start defining Camel routes.
3.1. Camel Route with Custom Processor
Next we’ll write our first route to convert file content to uppercase.
We need to define a source from which the route will read data. This can be a database, file, console, or any number of other sources. In our case, it will be file.
Then we need to define the processor of the data that will be read from the source. For this example, we are going to write a custom processor class. This class will be a Spring bean which will implement the standard Camel Processor Interface.
Once the data is processed, we need to tell the route to where to direct the processed data. Once again, this could be one of a wide variety of outputs, such as a database, file, or the console. In our case, we are going to store it in a file.
To set up these steps, including the input, processor, and output, add the following route to the Camel context file:
<route> <from uri="file://data/input" /> <!-- INPUT --> <process ref="myFileProcessor" /> <!-- PROCESS --> <to uri="file://data/outputUpperCase" /> <!-- OUTPUT --> </route>
Additionally, we must define the myFileProcessor bean:
<bean id="myFileProcessor" class="org.apache.camel.processor.FileProcessor" />
3.2. Custom Uppercase Processor
Now we need to create the custom file processor we defined in our bean. It must implement the Camel Processor interface, defining a single process method, which takes an Exchange object as its input. This object provides the details of the data from the input source.
Our method must read the message from the Exchange, uppercase the content, and then set that new content back into the Exchange object:
public class FileProcessor implements Processor { public void process(Exchange exchange) throws Exception { String originalFileContent = (String) exchange.getIn().getBody(String.class); String upperCaseFileContent = originalFileContent.toUpperCase(); exchange.getIn().setBody(upperCaseFileContent); } }
This process method will be executed for every input received from the source.
3.3. Lowercase Processor
Now we will add another output to our Camel route. This time, we will convert the same input file’s data into lowercase. This time, we will not use a custom processor, however; we will use Apache Camel’s Message Translator feature. This is the updated Camel route:
<route> <from uri="file://data/input" /> <process ref="myFileProcessor" /> <to uri="file://data/outputUppperCase" /> <transform> <simple>${body.toLowerCase()}</simple> </transform> <to uri="file://data/outputLowerCase" /> </route>
4. Running the Application
In order to have our routes be processed, we simply need to load the Camel context file into a Spring application context:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("camel-context.xml");
Once the route has been run successfully, two files will have been created: one with uppercase content, and one with lowercase content.
5. Conclusion
If you’re doing integration work, Apache Camel can definitely make things easier. The library provides plug-and-play components that will help you reduce boilerplate code and focus on the main logic of processing data.
And if you want to explore the Enterprise Integration Patterns concepts in detail, you should have a look at this book written by Gregor Hohpe and and Bobby Woolf, who conceptualize the EIPs very cleanly.
The example described in this article is available in a project on GitHub.