Using Camel File Component to transfer files

The Apache Camel File component is the simplest way to transfer files from a source folder to a destination without any coding required. This tutorial will teach you how to create a Camel application using the File component and how to configure to move (or don’t move) the file in the Route.

Setting up the Camel Project

To kick-start a Camel project, you can take a look at this tutorial: Apache Camel tutorial for beginners

Next, let’s adapt the RouteBuilder to include a Route that contains the Apache File component:

public class MainApp {
  public static void main(String args[]) throws Exception {
    CamelContext context = new DefaultCamelContext();
    context.addRoutes(
        new RouteBuilder() {
          public void configure() {
            from("file:src/data?noop=true").to("file:target/messages/others");
          }
        });
    context.start();
    Thread.sleep(5000);
    context.stop();
  }
}

Here is the Route with the File Component:

public class MyRouteBuilder extends RouteBuilder {
  public void configure() {
    from("file:src/data?noop=true").to("file:target/messages/others");
  }
}

Here is the project tree when running the above route:

src
├── data
│   └── file.txt
└── main
    ├── java
    │   └── com
    │       └── masterspringboot
    │           └── camel
    │               ├── MainApp2.java
    │               ├── MainApp.java
    │               └── MyProcessor.java
    └── resources
        └── log4j2.properties

As you can see, the ‘file.txt’ has been copied to target/messages/other.

In this route, the source and target folders are inside your Maven project. You can use absolute paths instead:

public void configure() {
  from("file:/path/data?noop=true").to("file:/path/target/messages/others");
}

Move file after processing

During the transfer from source folder we have set noop=true, this tells that the transferred file should remain in the source folder even after the transfer(copy paste). If this is not specified then after the transfer the file gets deleted from the source folder(cut&paste).

Also, if noop is set to “true”, Camel will set idempotent=true as well, to avoid consuming the same files over and over again.

Using a Processor for the File component

Let’s add a bit of complexity to our example. In most case, you would like to perform operations on the File that are moved in the Route.

camel file component

The simplest way to do that, is to chain a Processor Bean in the Route:

public void configure() {
  from("file:src/data?noop=true").process(new MyProcessor()).to("file:target/messages/others");
}

Within the class MyProcessor, we will collect the File from the Message Body and do the required actions with it. Finally, you need to set the Exchange Body with the new text content:

public class MyProcessor implements Processor {
  public void process(Exchange exchange) throws Exception {
    String myString = exchange.getIn().getBody(String.class);
    myString += System.getProperty("line.separator");
    myString += "Processed with MyProcessor";
    System.out.println("Processed!");
    exchange.getIn().setBody(myString);
  }

  public MyProcessor() {}
}

Filtering which files need to be copied

There are several strategies to filter which file has to be copied from the source folder to the target folder. The simplest option is to include a regular expression (such as the file suffix) to the “include” parameter. For example, to include just “*.txt” files:

public void configure() {
  from("file:src/data?noop=true&include=.*.txt").process(new MyProcessor()).to("file:target/messages/others");
}

Using ProducerTemplate to produce File content

If you want to decouple the Camel source files from the Route, you can use the abstract direct Camel component and use the ProducerTemplate class to send the file content. Here is a basic example:

public class MainApp {
  public static void main(String args[]) throws Exception {
    CamelContext context = new DefaultCamelContext();
    context.addRoutes(
        new RouteBuilder() {
          public void configure() {
            from("direct:transferFile")
                .process(new MyProcessor())
                .to("file:target/messages/others");
          }
        });
    ProducerTemplate producerTemplate = context.createProducerTemplate();
    context.start();
    String fileText =
        new String(Files.readAllBytes(Paths.get("src/data/file.txt")), StandardCharsets.UTF_8);
    Map<String, Object> headerMap = new HashMap<String, Object>();
    headerMap.put(Exchange.FILE_NAME, "file.txt");
    producerTemplate.sendBodyAndHeaders("direct:transferFile", fileText, headerMap);
    Thread.sleep(5000);
    context.stop();
  }
}

As you can see, the producer is set to “direct:transferFile” and the content of file is collected by a plain Java 7 function:

String fileText = new String(Files.readAllBytes(Paths.get("src/data/file.txt")), StandardCharsets.UTF_8);

Also, notice we are setting the Header of the ProducerTemplate to include the actual file name that will be injected into the Route.

Source code for this tutorial: https://github.com/fmarchioni/masterspringboot/tree/master/camel/camel-file

Found the article helpful? if so please follow us on Socials
Twitter Icon       Facebook Icon       LinkedIn Icon       Mastodon Icon