2

I'm being given a file containing numeric IDs that are delimited by newlines ("\n"):

123948
939904
129384
234049

etc. I want to use Camel to transform the file into an instance of the following POJO:

public class IDFile {
    private String fileName;    // The name of the file
    private List<Long> ids;     // All the IDs in the file (123948, 939904, etc.)

    // Constructor, getters/setters, etc.
}

I'm trying to see if I can use Camel's Splitter component to do this form me, but it feels like I'm trying to force a round peg into a square hole:

<route>
    <from uri="file://input/idfile"/>
    <split streaming="true">
        <tokenize token="\n" />
        <to uri="bean://idfileProcessor?method=process"/>
    </split>
</route>

The above looks like it would split my file into a List<Long>, but I need the file name associated with the list as well. Any ideas?

halfer
  • 19,824
  • 17
  • 99
  • 186
IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • 1
    does idfileProcessor maps to IDFile somewhere. because it looks like its a processor. if it is could you show us how are you processing the exchange? – Ashish Dec 18 '13 at 15:29
  • Thanks @Ashish (+1) - I guess my thinking was to have the `` *perform the transform for me*, so that by the time the message gets to `idfileProcessor` (yes, a Camel `Processor`), I can just extract the `IDFile` POJO out of the exchange like so: `IDFile idFile = (IDFile)exchange.getIn().getBody();`. The `idfileProcessor` could then *process* the `IDFile` instance. Sorry for the confusion! – IAmYourFaja Dec 18 '13 at 15:51

1 Answers1

4

There is a header "CamelFileName" on the exchange. Your processor/bean is passed a reference to the exchange and you can get the header from there and associate it with the token you have been invoked with.

Your route could look like this:

<camel:route id="splitter_test">
    <camel:from uri="file:///home/steppra1/camel_test?delete=true&amp;idempotent=true" />
    <camel:to uri="bean:splitBean?method=init" />
    <camel:split streaming="true">
        <camel:tokenize token="\n" />
        <camel:to uri="bean:splitBean?method=addToken" />
    </camel:split>
    <camel:to uri="bean:splitBean?method=done" />
    <camel:log message="${in.body}" loggingLevel="INFO" logName="split_test" />
</camel:route>

The bean you are using to maintain the state on the exchange object:

public class SplitBean {
    public Object init(Exchange exchange) {
        exchange.setProperty("splitTokens", new ArrayList<Integer>());
        return exchange.getIn().getBody();
    }

    public Object addToken(Exchange exchange) {
        ((List<Integer>)exchange.getProperty("splitTokens")).add(Integer.parseInt((String)exchange.getIn().getBody()));
        return null;
    }

    public Tuple done(Exchange exchange) {
        return new Tuple<String, List<Integer>>((String)exchange.getIn().getHeader("CamelFileName"), (List<Integer>)exchange.getProperty("splitTokens"));
    }
}

A file containing the rows

1
2
3
5

fed to the route under the names splitter.text and splitter_2.txt yields the following log output:

2013-12-18 18:20:02,081 INFO  split_test - Tuple [first=splitter.txt, second=[1, 2, 3, 5]]
2013-12-18 18:20:46,610 INFO  split_test - Tuple [first=splitter_2.txt, second=[1, 2, 3, 5]]

HTH

Ralf
  • 6,735
  • 3
  • 16
  • 32
  • Thanks @Ralf (+1) - inside my `idfileProcessor` (which is just a Java class implementing Camel's `Processor`, and hence contains a `public void process(Exchange)` method), can you provide a code sample for how I'd be able to obtain my `IDFile` instance, meaning I would need both the `String fileName` field (somehow obtained from the CamelFileName header you mentioned) as well as the `List ids`? Thanks again! – IAmYourFaja Dec 18 '13 at 15:54
  • I have updated the answer with an example using a bean, not a processor. Sorry, I did not read your comment carefully enough. In your processor you can access the file name like in I did in the `done(Exchange)` method. I also have the feeling that no Java bean should be required for this and that you could do it with one of the supported script languages right in the Spring DSL. Maybe someone else could provide an example for that? – Ralf Dec 19 '13 at 07:30