Camel supports most of the Enterprise Integration Patterns (EIP). Basically EIP provide a way to integrate Enterprise applications by means of messaging. We will go through the most common types of Integration Patterns.

Router

camel router

A content-based router allows dynamic routing depending on the content of a message. It can handle multiple messages from the same source and separate them to multiple destinations using body, header, or payload contents, using predicates and/or expressions.

Create Content-based routers in Java:

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));
  
        from("direct:a")
            .choice()
                .when(header("foo").isEqualTo("bar"))
                    .to("direct:b")
                .when(header("foo").isEqualTo("cheese"))
                    .to("direct:c")
                .otherwise()
                    .to("direct:d");
    }
};

A content-based router in Camel is developed a chained call to the choice method and multiple when chained calls.

Each of them defines a predicate and/or expression to check a condition. If it is true, the destination target declared using the to method call will be invoked. If none of the conditions in the when method calls are valid, the destination after the otherwise method will be invoked.

Create Content based Routing in Spring:

Here is the equivalent in Spring:

<camelContext errorHandlerRef="errorHandler" xmlns="http://camel.apache.org/schema/spring">
    <route>
        <from uri="direct:a"/>
        <choice>
            <when>
                <xpath>$foo = 'bar'</xpath>
                <to uri="direct:b"/>
            </when>
            <when>
                <xpath>$foo = 'cheese'</xpath>
                <to uri="direct:c"/>
            </when>
            <otherwise>
                <to uri="direct:d"/>
            </otherwise>
        </choice>
    </route>
</camelContext>

Splitter Pattern

camel splitter eip

The splitter pattern can be used to process a message which contains multiple elements, each of which should be processed in a different way. A large text file broken into multiple parts can be processed by a message queue more effectively than a large payload. This processing is implemented by Camel using the splitter pattern from EIP.

Thes splitter pattern works closely with Camel expressions to find and split the contents into multiple parts.

The Java DSL for a splitter pattern looks like this:

from( source-URI )

.split(expression)

.to( target-URI );

The following Splitter Pattern coded in Java shows how to split a set of records contained in a file to a JMS destination:

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        errorHandler(deadLetterChannel("mock:error"));
 
		from("file:in?noop=true")
			.split().tokenize("\n")
			.to("jms:queue:records");

    }
};

And here is the equivalent coded in Spring:

<route>
	<from uri="file:input?noop=true"/>
		<split streaming="true">
			<tokenize token="\n" />
			<to uri="jms:queue:records"/>
		</split>
</route>

Here is a more complex Split example which uses an XML file containing the following list of records:

<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
   </book>
</catalog>

In order to Split the above XML file, you can use the following Java DSL:

from(sourceUri)
.split(
xpath("/catalog/book")
)
.to(targetUri);

WireTap

camel wire tap eip

In integration projects, systems usually require replication mechanisms. This requirement usually causes some level of code duplication: for example what if you wanted the message headers, exchange properties, or other data in the message exchange? Ideally you could copy the whole incoming exchange and send that to another channel for auditing.

The wire tap pattern implements a replication process, adding new paths to a route, without large changes in the source code. Camel implements the wire tap pattern using a simple but effective mechanism: a method call passing as a parameter to an output destination.

public class JavaRouteBuilder extends RouteBuilder {
   @Override
   public void configure() throws Exception {
      from("file:in?noop=true")
         .wireTap("file:out")
            .to("jms:queue:orders");
   }
}

The wireTap() method will create a replication path where the contents of the actual route will be duplicated and sent to both the final destination and a new destination.

A developer may overuse wireTap to broadcast the output to multiple destinations. There is another pattern called multicasting, which is suitable for these cases.

Here is a more complex example which uses a Java DSL construct to wiretap messages to a JMS queue named logQueue and using a choice to direct to the final JMS destination:

from("jms:inputOrder")
.wireTap("jms:logQueue")
.choice()
.when(header("CamelFileName").endsWith(".xml"))
.to("jms:xmlQueue")
.otherwise()
.to("jms:badOrders");

RecipientList

camel tutorial recipientlist

Some messages will be routed to multiple destinations, depending on a certain condition. A common use case is when a shared service sends a message to a specific customer. To avoid sending confidential data to the wrong customer, the recipient list pattern can be used.

In the following example, according to the header contents, the file will be sent to a number of recipients:

public class JavaRouteBuilder extends RouteBuilder {
   @Override
   public void configure() throws Exception {
      from("jms:xmlOrders")
         .recipientList(header("customers"));
   }
}

In the above example, it's assumed that the header of the JMS message contains a field named customers that will be used to construct the destination name.

On the other hand, if this information is not available in the header of the message, it can be constructed using a Processor as in the following example:

from("jms:xmlOrders")
  .setHeader("customer", xpath("/item/@customer"))
  .process(new Processor() {
      public void process(Exchange exchange) throws Exception {
         String recipients = "jms:orders";
         String customer = exchange.getIn().getHeader("customer", String.class);
         
         if (customer.equals("acme")) {
           recipients += ",jms:production";
         }
         exchange.getIn().setHeader("customers", recipients);
}
})
.recipientList(header("customers"));

0
0
0
s2smodern