Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Camel: Splitting a collection and writing to files

Tags:

apache-camel

I´m trying to split an ArrayList and writing each element to it´s own file using Apache Camel like in this simplified example:

from("timer://poll?period=10000").process(new Processor(){
    public void process(Exchange exchange){
        ArrayList<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        exchange.getIn().setBody(list, ArrayList.class);
    }
}).split(body()).log(body().toString()).to("file:some/dir");

The log prints each item but only "three" is saved to a file. What am I doing wrong?

Jan

like image 554
jpstrube Avatar asked Aug 30 '11 07:08

jpstrube


People also ask

How does a Camel split work?

If enabled then Camel will process replies out-of-order, e.g. in the order they come back. If disabled, Camel will process replies in the same order as the messages was split. Will now stop further processing if an exception or failure occurred during processing of an org.

What are Camel routes?

A Camel route is where the integration flow is defined. For example to integrate two systems then a Camel route can be coded to specify how these systems are integrated. An example could be to take files from a FTP server and send to a ActiveMQ messaging system. This can be coded in a route using Java with the Java DSL.

What is Noop true in Camel?

If noop=true, Camel will set idempotent=true as well, to avoid consuming the same files over and over again. Expression (such as File Language) used to dynamically set the filename when moving it before processing. For example to move in-progress files into the order directory set this value to order.


2 Answers

After you called split function, your route is divided in 3 ways, each method or route executed after that is applied on each process way.

In each process way, split method add CamelSplitIndex property.

So this code should work

from("timer://poll?period=10000").process(new Processor(){
    public void process(Exchange exchange){
        ArrayList<String> list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        exchange.getIn().setBody(list, ArrayList.class);
    }
}).split(body()).log(body().toString()).to("file:some/dir?fileName=${header.CamelSplitIndex}");

This is second example with xml file and xpath.

We suppose that you want to explose xml for each node order with an element name inside:

<orders>
  <order>
    <name>Order 1</name>
  </order>
  <order>
    <name>Order 2</name>
  </order>
</order>

We suppose that we want to explode this xml file in 2 files

from("file://repo-source").split(xpath("//orders/order")).setHeader("orderName", xpath("/order/name").stringResult()).to("file://repo?fileName=${header.orderName}.xml");
like image 73
Thibaut Avatar answered Sep 18 '22 11:09

Thibaut


The file producer will by default "override" if a file already exists.

See the fileExist option at its documentation page http://camel.apache.org/file2

Since the input to this route is also a file, then the producer will "inherit" the file name from the input.

So in your case if you want to save each splitted message in a new file, then you would need to set a target file name, using the fileName option

"file:some/dir?fileName=splitted-${id}"

The fileName option supports the simple and file language

http://camel.apache.org/simple.html

http://camel.apache.org/file-language.html

That means the file name can be dynamic computed, such as above, where ${id} is an unique message id.

like image 23
Claus Ibsen Avatar answered Sep 18 '22 11:09

Claus Ibsen