Using Camel File Component to transfer files

The Camel File component is the simplest way to transfer files from a source folder to a destination without any coding required.

The following is an example of minimal Camel application which adds a Route that contains the 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");
}

Also notice that 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. 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

Exit mobile version