Last week I had to implement an interface for a customer in which an XML file had to be loaded into the database. But … the database table needed to be truncated first. At first, I thought that a chaining router would suffice. I soon found out that the behaviour of this router was not desirable at all.
Mule ESB contains multicasting and chaining routers to join a set of outbound endpoints. They differ in behaviour. When using a multicasting-router a message is send to multiple endpoints in a parallel way. So, you’re not sure if endpoint A has processed the message when endpoint B is about to start.
The chaining-router sends the message to the outbound endpoint collection in a sequential way, but the outcome of endpoint A will be send to endpoint B as payload. In other words, the endpoint will not process the same MuleMessage.
So, what to use if both types are not suitable?
Mule allows you to setup multiple routers (inbound as well as outbound). Class org.mule.routing.outbound.DefaultOutboundRouterCollection represents the collection of outbound routers in your Mule configuration. By using the (optional) matchAll attribute on the outbound router collection, the MuleMessage will be copied sent to *all* outbound routers (look at the public MuleMessage route(final MuleMessage message, final MuleSession session) method).
The following code snippet shows hows this should be implemented. It’s not a complete config .. but you’ll get the point. Notice the matchAll attribute!
1 2 3 4 5 6 7 8 9 10 11 12 13 | <service name="foobar"> <inbound> <vm:inbound-endpoint path="do.it"/> </inbound> <outbound matchAll="true"> <pass-through-router> <jdbc:outbound-endpoint queryKey="truncateCustomers"/> </pass-through-router> <expression-splitter-router evaluator="xpath" expression="//Customer"> <jdbc:outbound-endpoint queryKey="insertCustomer"/> </expression-splitter-router> </outbound> </service> |
Suppose an XML document containing Customers is offered to the inbound endpoint. What happens is that the Customers database table is truncated first and next the XML document is split up using the xpath expression. The end result is that the Customer table is replaced with the contents of the XML document.
In short: there are numerous situations where you would like to offer the MuleMessage to the complete outbound router collection. Use the matchAll attribute in these situation.
Happy Mule’ing !!
UPDATE: seems that there’s an even simpler solution to the problem that I’ve overlooked. (although my described solution works as advertised).
Using the following code snippet will do the trick as well:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <service name="foo"> ... <outbound> <multicasting-router> <jdbc:outbound-endpoint queryKey="truncateCustomers" synchronous="true"/> <vm:outbound-endpoint path="processCustomers" synchronous="true"/> </multicasting-router> </outbound> </service> <service name="bar"> <inbound> <vm:inbound-endpoint path="processCustomers"/> </inbound> <outbound> <expression-splitter-router evaluator="xpath" expression="//Customer"> <jdbc:outbound-endpoint queryKey="insertCustomer"/> </expression-splitter-router> </outbound> </service> |
Notice that the matchAll attribute has been replaced with synchronous. This last attribute results in the fact that the incoming message will *not* move on to the next outbound router in the collection until it has been consumed by a previous one.
With the introduction of Mule 3, this will probably all change (for the better).
Pascal, I wonder if you missed some critical point about the multicasting router. If you make its endpoint sync, it will _not_ proceed to the next endpoint until the previous one is done.
Shows once again that Mule is very versatile ;)
Anyway, I overlooked the synchronous processing … I’ll update the post and add the ‘sync’ info.