Apache Camel

Spring Boot & Apache Camel: Navigating the Data Processing Desert

Matt McCandless Apache, Articles, Java, Spring, Spring Boot Leave a Comment

Attention: The following article was published over 5 years ago, and the information provided may be aged or outdated. Please keep that in mind as you read the post.

If you are like me, you find that flat-file processing can be pretty dry.

Considering what Apache Camel does, its name is very fitting. While there are plenty of reasons for the name, it definitely makes sense that Apache Camel does a lot of lugging things around for you.

This article will set up a basic Spring Boot app that incorporates Apache Camel to move some sample files around.

Apache Camel

This particular Apache offering is quite vast. From processing flat files, connecting to databases, and hooking up to SalesForce, Camel has a lot of handy components for you to use. To see what is available, check out www.camel.apache.org/components/latest/index.html.

The basic idea here is to create what Camel calls a route. Routes can be defined as file drops to scheduled events or just simple recurring timers. There are a whole host of options on which to build a route. The next thing to understand is how messages are exchanged from route to route. For simplicity’s sake, we’ll just stick with the exchange. Think of the exchange as an object that has a bunch of fields for designating where it’s going, the body, a header, and a lot of other things.

For our purposes, we will mostly be concerned with the body of the exchange. This is where our message will be found that we need to process. So let’s get started with a basic setup.

Lace-Up Your Boots for Camel

We’ll use Maven to set up our project. Setting up your pom.xml file, the most important things are pulling in the camel-core and camel-spring-boot-starter dependencies.

Related Posts:  RAG Architecture Pattern Explained

Take note of the Camel “version” and the “rcversion” variables. Some of the things offered by the latest Camel are only release candidates but work well. You can see that it is just a plain-Jane Boot app other than that.

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>camel_starter.App</start-class>
        <java.version>1.8</java.version>
        <camel.version>3.0.0</camel.version>
        <camel.rcversion>3.0.0-RC3</camel.rcversion>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-starter</artifactId>
            <version>${camel.rcversion}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>${camel.version}</version>
        </dependency>
    </dependencies>

Get That Camel Moving

Create your first route by extending RouteBuilder. It will require you to override the configure() method. This is where all the dromedary magic happens. Do note that to get Boot to pick it up that you must add the @Component annotation to the class.

 @Component
public class FileMoveRoute extends RouteBuilder {
    @Override
	public void configure() throws Exception {

Tell The Camel What To Do

The “from” line tells the Camel route what to do. In this case, it is listening to a folder for a dropped file. It doesn’t matter what the file is named or the type. We also are giving it a routeId with a unique string. There can only be one route with this ID. It will not start up properly if another exists. Lastly, we can log out a simple INFO message.

 from("file://d:/data/testmove")
 .routeId("uniqueRouteName")
 .log("Firing My First Route!")

Which Way to Go?

Now that we told the camel what to do, it has to decide what is next. We have created three options.

  1. Checking to see if the file has the word “start” in the filename
  2. Checking to see if the file has the word “edit” in the filename
  3. Default failure
.choice()
            .when(fileIsStart)
            .to("direct:GoToMyFileMover")
        .endChoice()
        .otherwise()
        .choice()
            .when(fileIsEdit)
            .to("direct:EditMyFileFirst")
        .endChoice()
        .otherwise()
        .to("direct:GoToMyFailureRoute");

Direct Routes

Direct routes are just that! It will take your message directly to the “from” route with the same name. Pretty simple really. Hard for a camel to get lost!

Related Posts:  Web and Mobile Dev with Expo and Express

Explaining The “When” and Predicates

A Camel predicate is a simple check returning a boolean to determine if you meet its criteria.

Predicate fileIsStart = new Predicate(){
    
        @Override
        public boolean matches(Exchange exchange) {
            File file = exchange.getIn().getBody(File.class);
            return file.getName().contains("start");
        }
    };

    Predicate fileIsEdit = new Predicate(){
    
        @Override
        public boolean matches(Exchange exchange) {
            File file = exchange.getIn().getBody(File.class);
            return file.getName().contains("edit");
        }
    };

Camel Directions

First is our simple file mover. This route moves our dropped file over to another folder. Easy and simple, we’ve made it from start to finish. Our camel can rest.

 from("direct:GoToMyFileMover")
        .to("file://d:/data/moved")
        .log("File Moved Successfully");

Second, we have an editing scenario. We simply write out a new file to an edit directory. We will give it a name. You can see how easy it is to set the body and see the output of our new file. We use the .process method in Camel to intercept the route and create a new file.
We are overriding the process method of Processor to do so. You can create standalone processors and call them by passing them here, but for our purposes, we’ll not get into those weeds. We dropped off our packages along the way at an oasis.

from("direct:EditMyFileFirst")
        .process(new Processor(){
        
            @Override
            public void process(Exchange exchange) throws Exception {
                exchange.getIn().setBody("Edited file has been written!");                
            }
        })
        .to("file://d:/data/edited?fileName=Edited.txt")
        .log("Edit File Created!");

Lastly, if our file doesn’t meet our criteria we log a message. “Send help” request goes back to the Camel company.

from("direct:GoToMyFailureRoute")
        .log("Your File Didn't go anywhere, but was processed.");

In all three scenarios, the file we send through is moved to a .camel subfolder. This gives a record of what the original file was and that it was processed.

Camel Trip Over

Well, we hope you enjoyed the short ride and see how easy it is to get started with Spring Boot & Apache Camel. Check out the starter project.

Again, there are a vast amount of available components for connecting to all sorts of things. Check out the list and see what journeys you can set out on. Enjoy the ride!

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments