Recipient List – routing a message to a list of endpoints

When you want to dynamically (at runtime) decide a list of endpoints that an individual message should be sent to, use the Recipient List EIP. This EIP is made up of two phases: deciding where to route the message, and subsequently invoking those route steps. It can be thought of as a dynamic Multicast, and behaves in much the same way.

Recipient List – routing a message to a list of endpoints

This recipe will show you how to route a message to a number of dynamically specified endpoints.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.routing.recipientlist package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with recipientList.

How to do it...

Use the recipientList DSL statement, which includes an Expression that tells it where to get, the list of endpoints for routing the message at runtime.

In the XML DSL, this routing logic is written as:

<route>
  <from uri="direct:start"/>
  <setHeader headerName="endpointsToBeTriggered">
    <method ref="messageRouter"
            method="getDestinationsFromMessage"/>
  </setHeader>
  <recipientList>
    <header>endpointsToBeTriggered</header>
  </recipientList>
</route>

In the Java DSL, the same thing is expressed as:

from("direct:start")
  .setHeader("endpointsToBeTriggered")
    // you implement the method below
    .method(MessageRouter.class,
            "getDestinationsFromMessage")
  .recipientList(header("endpointsToBeTriggered"));

How it works...

The first phase of the process, deciding which steps to route to, could be as follows:

  1. An explicit step that you decide via a custom piece of logic based on the message contents.
  2. Skipped, as the list of endpoint URIs is already contained somewhere in the message.

The second phase triggers the EIP implementation with an Expression telling it where the endpoint addresses to route to are found in the message.

In the preceding example, we set a header on the message with a list of endpoint URIs as a string delimited with a comma (,) symbol.

public class MessageRouter {
  public String getDestinationsFromMessage (Exchange exchange) {
    String orderType = exchange.getIn()
        .getHeader("orderType", String.class);
    if (orderType == null) {
      return "direct:unrecognized";
    } else if (orderType.equals("priority")) {
      return "direct:order.priority,direct:billing";
    } else {
      return "direct:order.normal,direct:billing";
    }
  }
}

You can change the character used to delimit the list of endpoints in the String through the delimiter attribute.

You do not have to use a header, the Recipient List DSL statement can use any Expression to determine the list of endpoint URIs to send to.

The recipentList statement can also process any iterable type, so you could just as well return an array, a java.util.Collection, java.util.Iterator, or org.w3c.dom.NodeList. By default, the EIP will iterate over the endpoint URIs in order, and invoke them with a copy of the original exchange one after the other in the same thread.

There's more...

If one of the endpoint URIs named by your Expression is unrecognized, Camel will throw an org.apache.camel.ResolveEndpointFailedException. "Unrecognized" in this context means that one of the endpoint URIs that was returned by the Recipient List Expression referred to an endpoint that could not be resolved by Camel. The body of the exception might look as follows:

Failed to resolve endpoint: randommq://cheese due to: No component found with scheme: randommq

This is a type of exception that cannot be handled by the route. It indicates a serious problem with the routing logic that is not detected until runtime. You can, however, relax this constraint by using the ignoreInvalidEndpoints attribute:

from("direct:start")
  .setHeader("multicastTo")
    .constant("direct:first,direct:second,randommq:cheese")
  .recipientList()
    .header("multicastTo").ignoreInvalidEndpoints();

The Recipient List and Multicast EIPs share a lot of functionality. In fact, the only real difference is that the list of endpoints is worked out through an Expression. With both EIPs it is possible to:

  • Execute each endpoint using a different thread via parallelProcessing
  • Aggregate responses from the endpoints together using a custom AggregationStrategy
  • Avoid calling any uncalled endpoints via stopOnException
  • Share the transactional context via shareUnitOfWork
  • Perform deep cloning of the exchange using onPrepareRef

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.199.191