How can an incrementable index be obtained - i.e., to use during a loop() in RouteBuilder?

351 views Asked by At

Question: How can an incrementable index be obtained - i.e., to use during a loop() in RouteBuilder - so that iterative calls to "direct:thingC" will "process" subsequent elements (in the arraylist)?

Here is configure() method...

    private final org.apache.camel.Processor proc1 = new Processor1();
    private static final List<String> searchList = Arrays.asList("AA", "BB");
    private static final int z = searchList.size();
    private static int x = 0;    

    //***idea is to both elements using an index during the "loop".... Not working....

    @Override
    public void configure() throws Exception {

    from("timer://foo?fixedRate=true&period=" + 5000) //5 seconds...            
        .to("direct:thingB");

    from("direct:thingB")
        .log("---------------------- (from(\"direct:thingB\"))... ----------x=" + x)
        .loop(searchList.size()).to("direct:thingC");

    from("direct:thingC")
        .log("---------------------- (from(\"direct:thingC\"))... ----------searchList.get(" + x++ + ")=" + searchList.get(x));
    }

log output looks like this (index not incremented: always selects same element)... :-(

2017-09-01 16:13:19,142 | INFO  | 43 - timer://foo | route15                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingB"))... ----------x=0
2017-09-01 16:13:19,142 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(0)=BB
2017-09-01 16:13:19,143 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(0)=BB
2017-09-01 16:13:24,141 | INFO  | 43 - timer://foo | route15                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingB"))... ----------x=0
2017-09-01 16:13:24,141 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(0)=BB
2017-09-01 16:13:24,142 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(0)=BB

the goal is to -instead- have output like this....

2017-09-01 16:13:19,142 | INFO  | 43 - timer://foo | route15                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingB"))... ----------x=0
2017-09-01 16:13:19,142 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(0)=AA
2017-09-01 16:13:19,143 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(1)=BB
2017-09-01 16:13:24,141 | INFO  | 43 - timer://foo | route15                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingB"))... ----------x=0
2017-09-01 16:13:24,141 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(0)=AA
2017-09-01 16:13:24,142 | INFO  | 43 - timer://foo | route16                          | 232 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | ---------------------- (from("direct:thingC"))... ----------searchList.get(1)=BB

Solution: as per Alessandro's suggestion, below


private final String s = "AA,BB";

@Override
public void configure() throws Exception {

    from("timer://foo?fixedRate=true&period=" + 5000) //5 seconds... 
            .setBody(constant(s))            
            .to("direct:thingB")

    from("direct:thingB")
            .split().tokenize(",")
            .to("direct:thingC");       

    from("direct:thingC")
            .log("body=" + body());  //note: this value looks like simple{AA}
}
1

There are 1 answers

1
Alessandro Da Rugna On BEST ANSWER

Don't use loop. From the docs:

The Loop allows for processing a message a number of times, possibly in a different way for each iteration. Useful mostly during testing.
Default mode
Notice by default the loop uses the same exchange throughout the looping. So the result from the previous iteration will be used for the next

Since you want to process the single elements of something that you can "loop" over, set it as body and use split instead.

from("timer://foo?fixedRate=true&period=" + 5000) //5 seconds...            
    setBody(searchList)
    .to("direct:thingB");

from("direct:thingB")
    .split()
        .simple("${body}")
        .log("This is element: ${body} [Element number ${exchangeProperties.CamelSplitIndex} of ${exchangeProperties.CamelSplitSize} total elements]")
    .end()

Splitter will "break" the List into single pieces and process all in a loop.

In general, avoid having static fields if they are input or ouput data. In this case it's better to set them as the body, for example using a Processor bean that sets the desired data.