camel modifying header of split from inside aggregation strategy - apache-camel

Is it possible to modify a header that was set coming into aggregationstrategy
split messages
setheader groupname to "one"
aggregate on correlationkey header -groupname=one
The aggregation strategy will know at some point that it wants to change the correlation key to something else. But if i set the groupname on the header of the incoming new exchange, it is not creating a new correlationkey
How can I accomplish this ?

You cannot change correlation key inside the AggregationStrategy neither in the Splitter EIP or the Aggregate EIP.
The correlation key is determined beforehand using the correlationExpression you set on those EIPs.
The AggregationStrategy is used for merging the exchanges together.
See more details on the Camel EIP documentation of these patterns, or check some of the Camel books such as Camel in Action which has extensive coverage of these EIPs

Related

How to use Aggregator options such as completionSize, completionTimeout with split-aggregate

I can use an aggregator with completionSize and completionTimeout as below:
from("direct:aggregate")
.routeId("aggregate")
.aggregate(constant(true), new JSONAggregator())
.completionSize(500)
.completionTimeout(3000)
.convertBodyTo(String.class)
.log("${body}")
.end();
However, when I use an aggregationStrategy in conjunction with a splitter, I do not get these options. How can I implement aggregator options with a splitter?
You can't use these options with the Split EIP. The Splitter combined with an aggregation strategy simply re-aggregates all the parts of the input message it has splitted before.
Example: Split a message with 5000 lines, transform each line and re-aggregate these lines according to the strategy.
Because the aggragtion size is defined by the input message, you can't use any other aggregate completion options.
However, what you can do is, to use the Split EIP without aggregation strategy followed later in the processing by an independant Aggregate EIP. Then you can configure the aggregator as you like.

Apache camel - How to use activemq Selective consumer using message body

I want two consumer with single activemq queue and wanted to filter while consuming. Selective is best option for me (please suggest if there is other). But sender does not sending me any header parameter or any property, selective only works with header or properties, now I wanted to filter message on message body . Is there any way to use selective with message body
My two messages body are differed by test and test2
{
"test":{
"abc":"123",
"cde":"123"
}
}
{
"test2":{
"abc":"321",
"cde":"321"
}
}
I want something like selective with message body
from("jms:selective?selector=" + java.net.URLEncoder.encode(${body.test})).
to("cxf:bean:replica01");
from("jms:selective?selector=" + java.net.URLEncoder.encode(${body.test2})).
to("cxf:bean:replica02");
Please suggest if there is any way to do so.
As the selector documentation for ActiveMQ 5.x points out, you can use XPath based selectors for messages which have XML bodies. However, the bodies of your messages aren't XML so there doesn't appear to be anyway to get the functionality you're looking for.
Keep in mind that as far as the broker is concerned the body of a message is just an array of bytes whereas message headers/properties are typed which allows for the kinds of comparison operations that make selectors viable.

Camel aggregation from two queues in Java DSL

I have two queues which having same type of objects in them. I want to aggregate them into a single queue through java DSL. Could anyone tell me if this is possible? If so, any code references?
If I understand your question correctly, it is possible to do such a thing.
If you need just to drive them into a single route (without any aggregations, enrichments, etc.) you can just proceed with this piece of code:
from('direct:queue1')
.to('direct:start');
from('direct:queue2')
.to('direct:start');
from('direct:start')
//there goes your processing
If you need to aggregate them later on, use Aggregator. Or you can use example from java-addict301's answer if it solves your case.
I believe this may be doable in Camel using the Content Enricher pattern.
Specifically, the following paradigm can be used to retrieve a message from one queue (where direct:start is) and enrich it with a message from the second queue (where direct:resource is). The combined message can then be built in your AggregationStrategy implementation class.
AggregationStrategy aggregationStrategy = ...
from("direct:start")
.enrich("direct:resource", aggregationStrategy)
.to("direct:result");
from("direct:resource")

Camel: Tracing history of exchanges when a splitter is used

I'm using Apache Camel, and trying to create a log of the history of the processing of each message in a workflow.
For simple straight-through workflows, where a message comes in, is processed by a few steps, and then leaves, this could be as simple as just keeping a sequential log of the exchanges. I can do this by writing a custom TraceEventHandler, which is called at each exchange and allows me to do logging.
However, if a splitter is involved, I don't know how to calculate the provenance of any given exchange. I could maintain my own log of exchanges, but in the case of a splitter, not all previous activity would be an ancestor of the current exchange. That is, if an incoming message is split into part1 and part2, which are then each processed separately, I don't want to consider the processing of part1 when calculating the history of part2.
A TraceEventHandler has this method:
#Override
public void traceExchange(ProcessorDefinition<?> node, Processor target,
TraceInterceptor traceInterceptor,Exchange exchange) throws Exception {
}
and I expected that there would be an Exchange method like Exchange getPreviousExchange() that I could call inside traceExchange, but I can find no such thing.
Any advice? I'm not married to using a custom TraceEventHandler if there's a better way to do this.
Thanks.
You can find the previous Exchange id by looking up the exchange property with the key "CamelCorrelationId".
If you want to track the post-split processing as separate branches, then you need to consider the Camel property "CamelSplitIndex". This property will indicate which iteration of the split you're processing and when combined with the CamelCorrelationId as William suggested, will provide the full picture.

AMQP - Does the consumer have acess to the routing key?

I've set up a topic exchange such that the consumer queue is bound with "#.topic". I'd like to use different acknowledgement strategies based on the prefix. Is the full routing key sent to the consumer? If so, how do I access it? An answer in terms of AMQP concepts would probably be sufficient, but an answer involving rabbitmq-c would be ideal.
Even when you do a binding like you have given in your example the message received contains the full routing key. This means you can extract that in order to help you process the message. Unfortunately I only know how to do this in Java so try to extrapolate from there.
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String routingKey = delivery.getEnvelope().getRoutingKey();
The delivery object contains a body which is the payload and can be retrieve with delivery.getBody() and an Envelope object which contains other information like the full routing key.

Resources