I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

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:

  1. Read file from source directory
  2. Convert file content to uppercase using a custom Processor
  3. Write converted output to a destination directory
  4. Convert file content to lowercase using Camel Translator
  5. 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.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS

newest oldest most voted
Notify of
Giriraj Gurjar
Guest
Giriraj Gurjar

Nicely written and well explained

Eugen Paraschiv
Guest

Glad it helped Giriraj. Cheers,
Eugen.

Sanket
Guest
Sanket

My Project ran but no output file is created.

Console Output:

Oct 12, 2016 3:36:04 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org[email protected]17f052a3: startup date [Wed Oct 12 15:36:04 IST 2016]; root of context hierarchy
Oct 12, 2016 3:36:04 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [camel-context.xml]
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Oct 12, 2016 3:36:11 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org[email protected]17f052a3: startup date [Wed Oct 12 15:36:04 IST 2016]; root of context hierarchy

Grzegorz Piwowarek
Guest
Grzegorz Piwowarek

Hi, Sanket!
It’s very hard to diagnose the problem without knowing the whole context. Logs that you provided suggest some problems with logging configuration but I highly doubt that this is the reason why your project is not working as expected

Sammy
Guest
Sammy

Thanks you Baeldung. Very well explained basics in simple language.