You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Next »

Resequencer

The Resequencer from the EIP patterns allows you to reorganise messages based on some comparator. By default in Camel we use an Expression to create the comparator; so that you can compare by a message header or the body or a piece of a message etc.

Camel supports two resequencing algorithms:

  • Batch resequencing collects messages into a batch, sorts the messages and sends them to their output.
  • Stream resequencing re-orders (continuous) message streams based on the detection of gaps between messages.

Batch Resequencing

The following example shows how to use the batch-processing resequencer so that messages are sorted in order of the body() expression. That is messages are collected into a batch (either by a maximum number of messages per batch or using a timeout) then they are sorted in order and then sent out to their output.

Using the Fluent Builders

Error formatting macro: snippet: java.lang.NullPointerException

This is equvalent to

from("direct:start").resequencer(body()).batch().to("mock:result");

To define a custom configuration for the batch-processing resequencer you should provide a configuration object.

from("direct:start").resequencer(header("seqnum")).batch(new BatchResequencerConfig(300, 4000L)).to("mock:result")

This sets the batchSize to 300 and the batchTimeout to 4000 ms (by default, the batch size is 100 and the timeout is 1000 ms).

So the above example will reorder messages from endpoint direct:a in order of their bodies, to the endpoint mock:result. Typically you'd use a header rather than the body to order things; or maybe a part of the body. So you could replace this expression with

resequencer(header("JMSPriority"))

for example to reorder messages using their JMS priority.

You can of course use many different Expression languages such as XPath, XQuery, SQL or various Scripting Languages.

You can also use multiple expressions; so you could for example sort by priority first then some other custom header

resequencer(header("JMSPriority"), header("MyCustomerRating"))

Using the Spring XML Extensions

Stream Resequencing

The next example shows how to use the stream-processing resequencer. Messages are re-ordered based on their sequence numbers given by a seqnum header using gap detection and timeouts on the level of individual messages.

Using the Fluent Builders

Error formatting macro: snippet: java.lang.NullPointerException

To define a custom configuration for the stream-processing resequencer you should provide a configuration object.

from("direct:start").resequencer(header("seqnum")).stream(new StreamResequencerConfig(5000, 4000L)).to("mock:result")

This sets the resequencer's capacity to 5000 and the timeout to 4000 ms (by default, the capacity is 100 and the timeout is 1000 ms).

The stream-processing resequencer algorithm is based on the detection of gaps in a message stream rather than on a fixed batch size. Gap detection in combination with timeouts removes the constraint of having to know the number of messages of a sequence (i.e. the batch size) in advance. Messages must contain a unique sequence number for which a predecessor and a successor is known. For example a message with the sequence number 3 has a predecessor message with the sequence number 2 and a successor message with the sequence number 4. The message sequence 2,3,5 has a gap because the sucessor of 3 is missing. The resequencer therefore has to retain message 5 until message 4 arrives (or a timeout occurs).

If the maximum time difference between messages (with successor/predecessor relationship with respect to the sequence number) in a message stream is known, then the resequencer's timeout parameter should be set to this value. In this case it is guaranteed that all messages of a stream are delivered in correct order to the next processor. The lower the timeout value is compared to the out-of-sequence time difference the higher is the probability for out-of-sequence messages delivered by this resequencer. Large timeout values should be supported by sufficiently high capacity values. The capacity parameter is used to prevent the resequencer from running out of memory.

By default, the stream resequencer expects long sequence numbers but other sequence numbers types can be supported as well by providing custom comparators.

ExpressionResultComparator<Exchange> comparator = new MyComparator();
StreamResequencerConfig config = new StreamResequencerConfig(5000, 4000L, comparator);
from("direct:start").resequencer(header("seqnum")).stream(config).to("mock:result");

Using the Spring XML Extensions

<camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring">
  <route>
    <from uri="direct:start"/>
    <resequencer>
      <simple>in.header.seqnum</simple>
      <to uri="mock:result" />
      <stream-config capacity="5000" timeout="4000"/>
    </resequencer>
  </route>
</camelContext>

Further Examples

For further examples of this pattern in use you could look at the batch-processing resequencer junit test case and the stream-processing resequencer junit test case

Using This Pattern

If you would like to use this EIP Pattern then please read the Getting Started, you may also find the Architecture useful particularly the description of Endpoint and URIs. Then you could try out some of the Examples first before trying this pattern out.

  • No labels