Aggregator
This applies for Camel version 2.3 or newer. If you use an older version then use this Aggregator link instead.
The Aggregator from the EIP patterns allows you to combine a number of messages together into a single message.
A correlation Expression is used to determine the messages which should be aggregated together. If you want to aggregate all messages into a single message, just use a constant expression. An AggregationStrategy is used to combine all the message exchanges for a single correlation key into a single message exchange.
Aggregator options
The aggregator supports the following options:
Option |
Default |
Description |
---|---|---|
correlationExpression |
|
Mandatory Expression which evaluates the correlation key to use for aggregation. The Exchange which has the same correlation key is aggregated together. If the correlation key could not be evaluated an Exception is thrown. You can disable this by using the |
aggregationStrategy |
|
Mandatory |
strategyRef |
|
A reference to lookup the |
completionSize |
|
Number of messages aggregated before the aggregation is complete. This option can be set as either a fixed value or using an Expression which allows you to evaluate a size dynamically - will use |
completionTimeout |
|
Time in millis that an aggregated exchange should be inactive before its complete. This option can be set as either a fixed value or using an Expression which allows you to evaluate a timeout dynamically - will use |
completionInterval |
|
A repeating period in millis by which the aggregator will complete all current aggregated exchanges. Camel has a background task which is triggered every period. You cannot use this option together with completionTimeout, only one of them can be used. |
completionPredicate |
|
A Predicate to indicate when an aggregated exchange is complete. |
completionFromBatchConsumer |
|
This option is if the exchanges are coming from a Batch Consumer. Then when enabled the Aggregator2 will use the batch size determined by the Batch Consumer in the message header |
eagerCheckCompletion |
|
Whether or not to eager check for completion when a new incoming Exchange has been received. This option influences the behavior of the |
groupExchanges |
|
If enabled then Camel will group all aggregated Exchanges into a single combined |
ignoreInvalidCorrelationKeys |
|
Whether or not to ignore correlation keys which could not be evaluated to a value. By default Camel will throw an Exception, but you can enable this option and ignore the situation instead. |
closeCorrelationKeyOnCompletion |
|
Whether or not too late Exchanges should be accepted or not. You can enable this to indicate that if a correlation key has already been completed, then any new exchanges with the same correlation key be denied. Camel will then throw a |
discardOnCompletionTimeout |
|
Camel 2.5: Whether or not exchanges which complete due to a timeout should be discarded. If enabled then when a timeout occurs the aggregated message will not be sent out but dropped (discarded). |
aggregationRepository |
|
Allows you to plugin you own implementation of |
aggregationRepositoryRef |
|
Reference to lookup a |
parallelProcessing |
|
When aggregated are completed they are being send out of the aggregator. This option indicates whether or not Camel should use a thread pool with multiple threads for concurrency. If no custom thread pool has been specified then Camel creates a default pool with 10 concurrent threads. |
executorService |
|
If using |
executorServiceRef |
|
Reference to lookup a |
Exchange Properties
The following properties are set on each aggregated Exchange:
header |
type |
description |
---|---|---|
|
int |
The total number of Exchanges aggregated into this combined Exchange. |
|
String |
Indicator how the aggregation was completed as a value of either: |
About AggregationStrategy
The AggregationStrategy
is used for aggregating the old (lookup by its correlation id) and the new exchanges together into a single exchange. Possible implementations include performing some kind of combining or delta processing, such as adding line items together into an invoice or just using the newest exchange and removing old exchanges such as for state tracking or market data prices; where old values are of little use.
Notice the aggregation strategy is a mandatory option and must be provided to the aggregator.
Here are a few example AggregationStrategy implementations that should help you create your own custom strategy.
//simply combines Exchange String body values using '+' as a delimiter class StringAggregationStrategy implements AggregationStrategy { public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { if (oldExchange == null) { return newExchange; } String oldBody = oldExchange.getIn().getBody(String.class); String newBody = newExchange.getIn().getBody(String.class); oldExchange.getIn().setBody(oldBody + "+" + newBody); return oldExchange; } } //simply combines Exchange body values into an ArrayList<Object> class ArrayListAggregationStrategy implements AggregationStrategy { public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { Object newBody = newExchange.getIn().getBody(); ArrayList<Object> list = null; if (oldExchange == null) { list = new ArrayList<Object>(); list.add(newBody); newExchange.getIn().setBody(list); return newExchange; } else { list = oldExchange.getIn().getBody(ArrayList.class); list.add(newBody); return oldExchange; } } }
About completion
When aggregation Exchanges at some point you need to indicate that the aggregated exchanges is complete, so they can be send out of the aggregator. Camel allows you to indicate completion in various ways as follows:
- completionTimeout - Is an inactivity timeout in which is triggered if no new exchanges have been aggregated for that particular correlation key within the period.
- completionInterval - Once every X period all the current aggregated exchanges are completed.
- completionSize - Is a number indicating that after X aggregated exchanges it's complete.
- completionPredicate - Runs a Predicate when a new exchange is aggregated to determine if we are complete or not
- completionFromBatchConsumer - Special option for Batch Consumer which allows you to complete when all the messages from the batch has been aggregated. |
Notice that all the completion ways are per correlation key. And you can combine them in any way you like. It's basically the first which triggers that wins. So you can use a completion size together with a completion timeout. Only completionTimeout and completionInterval cannot be used at the same time.
Notice the completion is a mandatory option and must be provided to the aggregator. If not provided Camel will thrown an Exception on startup.
Persistent AggregationRepository
The aggregator provides a pluggable repository which you can implement your own org.apache.camel.spi.AggregationRepository
.
If you need persistent repository then you can use either Camel HawtDB or SQL Component components.
Examples
See some examples from the old Aggregator which is somewhat similar to this new aggregator.
Setting options in Spring XML
Many of the options are configurable as attributes on the <aggregate>
tag when using Spring XML.
Using completionTimeout
In this example we want to aggregate all incoming messages and after 3 seconds of inactivity we want the aggregation to complete. This is done using the completionTimeout
option as shown:
And the same example using Spring XML:
Using completionSize
In this example we want to aggregate all incoming messages and when we have 3 messages aggregated (in the same correlation group) we want the aggregation to complete. This is done using the completionSize
option as shown:
And the same example using Spring XML:
Using completionPredicate
In this example we want to aggregate all incoming messages and use a Predicate to determine when we are complete. The Predicate can be evaluated using either the aggregated exchange (default) or the incoming exchange. We will so both situations as examples. We start with the default situation as shown:
And the same example using Spring XML:
And the other situation where we use the eagerCheckCompletion
option to tell Camel to use the incoming Exchange. Notice how we can just test in the completion predicate that the incoming message is the END message:
And the same example using Spring XML:
Using dynamic completionTimeout
In this example we want to aggregate all incoming messages and after a period of inactivity we want the aggregation to complete. The period should be computed at runtime based on the timeout
header in the incoming messages. This is done using the completionTimeout
option as shown:
And the same example using Spring XML:
Note: You can also add a fixed timeout value and Camel will fallback to use this value if the dynamic value was null
or 0
.
Using dynamic completionSize
In this example we want to aggregate all incoming messages based on a dynamic size per correlation key. The size is computed at runtime based on the mySize
header in the incoming messages. This is done using the completionSize
option as shown:
And the same example using Spring XML:
Note: You can also add a fixed size value and Camel will fallback to use this value if the dynamic value was null
or 0
.
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.
Manually Force the Completion of All Aggregated Exchanges Immediately
Available as of Camel 2.9
You can manually complete all current aggregated exchanges by sending in a message containing the header Exchange.AGGREGATION_COMPLETE_ALL_GROUPS set to true. The message is considered a signal message only, the message headers/contents will not be processed otherwise.
See also
- The Loan Broker Example which uses an aggregator
- Blog post by Torsten Mielke about using the aggregator correctly.
- The old Aggregator
- HawtDB or SQL Component for persistence support
- Aggregate Example for an example application