Description :
1) If we are not priorities the customers all orders coming from small and top-tier customers
are going directly into production.
2) We can define customer types like small and top-tier. Only For top-tier customers orders
processed parallel by the both accounting and production departments.
For small customer, first orders will go to accounting first. Here In accounting check customer
credit balance… so on.
Example :
We can Recipient List.
A recipient list inspects the incoming message and determines a list of recipients based on
the content of the message. In this case, the message is only sent to the A, B, and D destinations.
Ways to specify recipient list in routers:
There are different ways of mentioning Recipient list in routers.
Type 1:
Camel provides a recipientList method for implementing the Recipient List EIP
from("jms:xmlOrders").recipientList(header("recipients"));
In above example, router will take the list of recipients from a header named
recipients, where each recipient is separated from the next by a comma.
This is useful if you already have some information in the message.
Type 2:
We can use an expression to create the list.
In order for the recipient list to extract meaningful endpoint URIs, the expression result
must be iterable.
from("jms:xmlOrders") .setHeader("customer", xpath("/order/@customer")) .process(new Processor() { public void process(Exchange exchange) throws Exception { String recipients = "jms:accounting"; String customer = exchange.getIn().getHeader("customer", String.class); if (customer.equals("honda")) { recipients += ",jms:production"; } exchange.getIn().setHeader("recipients", recipients); } }) .recipientList(header("recipients"));
Type 3:
We can use recipient list annotation @RecipientList
This behavior only gets invoked, however, if the class is used with Camel’s bean integration
from("jms:xmlOrders").bean(RecipientListBean.class);
RecipientListBean.java
public class RecipientListBean { @RecipientList public String[] route(@XPath("/order/@customer") String customer) { if (isGoldCustomer(customer)) { return new String[] {"jms:accounting", "jms:production"}; } else { return new String[] {"jms:accounting"}; } } private boolean isGoldCustomer(String customer) { return customer.equals("honda"); } }
UsingRecipientListsInCamelRouters.java
package com.venkatjavasource.camel; import javax.jms.ConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.jms.JmsComponent; import org.apache.camel.impl.DefaultCamelContext; public class UsingRecipientListsInCamelRouters { public static void main(String[] args) throws Exception { // Create CamelContext CamelContext context = new DefaultCamelContext(); // Connect to embedded ActiveMQ JMS broker ConnectionFactory connectionFactory = new ActiveMQConnectionFactory( "vm://localhost"); context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory)); // add our route to the CamelContext context.addRoutes(new RouteBuilder() { @Override public void configure() { // Content-based router from("file:/venkatjavasource/camel/from?noop=false").choice() .when(header("CamelFileName").endsWith(".xml")) .to("jms:xmlOrders") .when(header("CamelFileName").regex("^.*(csv|csl)$")) .to("jms:csvOrders").otherwise().to("jms:badOrders"); from("jms:xmlOrders") .setHeader("customer_type", xpath("/order/@customer_type")) .process(new Processor() { public void process(Exchange exchange) throws Exception { String recipients = "jms:accounting"; String customer = exchange.getIn().getHeader( "customer_type", String.class); if ("Gold".equals(customer)) { recipients += ",jms:production"; } exchange.getIn().setHeader("recipients", recipients); } }).recipientList(header("recipients")); // test that our route is working from("jms:accounting").process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Accounting received order: " + exchange.getIn().getHeader("CamelFileName")); } }); from("jms:production").process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Production received order: " + exchange.getIn().getHeader("CamelFileName")); } }); } }); // start the route and let it do its work context.start(); Thread.sleep(2000); // stop the CamelContext context.stop(); } }
Demo :
We have two order files Order1.xml and Order1.xml in file:/venkatjavasource/camel/from
Order1.xml
Order2.xml
In Java code, we have condition. If customer_type is gold, then only order will be submitted
to account and production departments. Otherwise only to accounting.
Out Put :
Accounting received order: Order1.xml
Accounting received order: Order2.xml
Production received order: Order2.xml
In the above example, we hard coded the customer_type value, that decide to whether to
production JMS queue to recipient list or not.
This is not good practice always. we can use @RecipientList, to do this business validations.
UsingRecipientListsWithBeanInCamelRouters.java
package com.venkatjavasource.camel; import javax.jms.ConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.jms.JmsComponent; import org.apache.camel.impl.DefaultCamelContext; import com.venkatjavasource.camel.RecipientListBean; public class UsingRecipientListsWithBeanInCamelRouters { public static void main(String[] args) throws Exception { // Create CamelContext CamelContext context = new DefaultCamelContext(); // Connect to embedded ActiveMQ JMS broker ConnectionFactory connectionFactory = new ActiveMQConnectionFactory( "vm://localhost"); context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory)); // add our route to the CamelContext context.addRoutes(new RouteBuilder() { @Override public void configure() { // Content-based router from("file:/venkatjavasource/camel/from?noop=false").choice() .when(header("CamelFileName").endsWith(".xml")) .to("jms:xmlOrders") .when(header("CamelFileName").regex("^.*(csv|csl)$")) .to("jms:csvOrders").otherwise().to("jms:badOrders"); from("jms:xmlOrders").bean(RecipientListBean.class); // test that our route is working from("jms:accounting").process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Accounting received order: " + exchange.getIn().getHeader("CamelFileName")); } }); from("jms:production").process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Production received order: " + exchange.getIn().getHeader("CamelFileName")); } }); } }); // start the route and let it do its work context.start(); Thread.sleep(2000); // stop the CamelContext context.stop(); } }
RecipientListBean.java
package com.venkatjavasource.camel; import org.apache.camel.RecipientList; import org.apache.camel.language.XPath; public class RecipientListBean { @RecipientList public String[] route(@XPath("/order/@customer_type") String customer) { if (isGoldCustomer(customer)) { return new String[] { "jms:accounting", "jms:production" }; } else { return new String[] { "jms:accounting" }; } } private boolean isGoldCustomer(String customer) { System.out.println("Customer Type is: " + customer); return customer.equals("Gold"); } }
Out Put :
Customer Type is: Silver
Accounting received order: Order1.xml
Customer Type is: Gold
Accounting received order: Order2.xml
Production received order: Order2.xml
*** Venkat – Happy leaning ****