javaapache-camelroutessplitterintegration-patterns

Apache Camel: Splitter, CBR or Dynamic Router?


I have the following POJO:

public class MyPOJO {
    private Fizz fizz;
    private Buzz buzz;

    // ctor, getters, setters, etc.
}

And the following route (Spring XML):

<route id="myroute">
    <from uri="timer://runOnce?repeatCount=1&amp;delay=10" />

    <to uri="bean:myPOJOFactory?method=newMyPOJO" />

    <!-- Not sure what to do here -->
    <!-- MyPOJO#Fizz should get routed to direct:fizzFarm. -->
    <!-- MyPOJO#Buzz should get routed to direct:buzzFarm. -->
</route>

Where myPOJOFactory is:

public class MyPOJOFactory {
    public MyPOJO newMyPOJO(Exchange exchange) {
        Fizz fizz = new Fizz(true, 3);
        Buzz buzz = new Buzz("awesome");

        MyPOJO pojo = new MyPOJO(fizz, buzz);

        exchange.getOut().setBody(pojo);
    }
}

I need a way to now split the MyPOJO instance (created inside the myPOJOFactory bean) into its constituent Fizz and Buzz properties, and route the Fizz one way, and the Buzz another way.

My understanding of a Splitter is that it just takes the body of the exchange and breaks it up into a collection of 2+ objects. But I don't think this is what I want, because although I do want the MyPOJO to get "split" into its constituent Fizz and Buzz fields, I want them routed to different destinations. Perhaps Fizz goes to direct:fizzFarm and Buzz goes to direct:buzzFarm.

My understanding of a Content-Based Router (<choice/>) is that it allows you to add condition if-else-if logic into a route. But I don't think I want this either because what I need isn't conditional: I always want the MyPOJO#Fizz to go to direct:fizzFarm, and I always want the MyPOJO#Buzz to go to direct:buzzFarm.

My understanding of a Dynamic Router is that it will dynamically route messages to different destinations, although I'm not quite sure how yet. I believe this is what I want, however, coming out of the myPOJOFactory bean, the exchange will contain a MyPOJO object. I feel like I have to first split the MyPOJO prior to sending it into a dynamic router. That way, the dynamic router will be able to clearly see whether the message is a Fizz or a Buzz, and route it correctly.

So I believe I need to use a splitter in conjunction with a dynamic router. I'm just not seeing the forest through the trees. Something like this:

<route id="myroute">
    <from uri="timer://runOnce?repeatCount=1&amp;delay=10" />

    <to uri="bean:myPOJOFactory?method=newMyPOJO" />

    <split>
        <tokenize token="Somehow split MyPOJO into Fizz and Buzz here" />
        <to uri="direct:dynrouter" />
    </split>

    <from uri="direct:dynrouter" />

    <dynamicRouter>
        <!-- ??? Somehow route Fizz to direct:fizzFarm, and Buzz to direct:buzzFarm
    </dynamicRouter>
</route>

Any ideas as to how I can accomplish this (#1 splitting MyPOJO into Fizz and Buzz, and #2 setting up a router to route Fizz and Buzz to different destinations)?


Solution

  • You're right, since the logic is always the same, the routers might be overkill.

    Splitters are most often used with objects of the same type (e.g. splitting a list and processing each item separately)

    So can I suggest the Multicast EIP, something like this should work:

    from("timer://runOnce?repeatCount=1&delay=10")
        .bean(myPOJOFactory.class)
        .multicast().to("direct:sendFizz", "direct:sendBuzz")
    
    from("direct:sendFizz")
        .setBody(simple("${body.fizz"))
        .to("direct:fizzFarm")
    
    from("direct:sendBuzz")
        .setBody(simple("${body.buzz"))
        .to("direct:buzzFarm")
    

    (This is obviously DSL syntax, you can also try it in XML).