Templates by BIGtheme NET

Using Recipient Lists In Camel Routers

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.
23
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
24

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 ****