In apache camel, which of those is the best way to pass values from an exchange processor to another (and why) :
storing it in the exchange headers
using the setProperty method while building the route.
another way..
One distinction not mentioned by Ben and Petter is that properties are safely stored for the entire duration of the processing of the message in Camel. In contrast, headers are part of the message protocol, and may not be propagated during routing. For example, JMS has limitations what you can store as headers etc.
You may want to read the free chapter 1 of the Camel in Action book as it covers the Camel concepts with Exchange, Message, etc.
Properties and headers are pretty much the same. Headers are, however, converted to/from protocol specific headers on certain components, such as Jms. So,
Meta data inside a route: properties
Meta data to/from outside: headers
the Exchange is passed between Processors. It contains properties, IN message and optional OUT message. Each of these is capable of storing Object data, but in general:
use the Exchange Properties for general meta-data about the message (used less frequently)
use the IN message headers to configure endpoint properties or for meta-data about the message body (used often)
use the IN message body for the payload of the message (used most often)
create an OUT message only if necessary to maintain separate IN vs. OUT messages during processing (by default only IN is used)
That said, it really depends on the component called following your processor. Most have some headers and/or body values that are required to use the endpoint, etc. See the specific component page for these details.
Also, the Exchange/Message are explained in more detail on these pages:
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Exchange.html
http://fusesource.com/docs/router/2.8/prog_guide/MsgFormats-Exchanges.html
Answer is here:
Properties: The properties is a Map and may look like message
headers. The main difference is their lifetime: the properties exist during the whole
exchange execution, whereas the headers are limited to the message duration (and a
message can change a lot during routing, so during the exchange execution). Camel
itself may add some properties for some use cases.
Related
I have this simple route in my RouteBuilder.
from("amq:MyQueue").routeId(routeId).log(LoggingLevel.DEBUG, "Log: ${in.headers} - ${in.body}")
As stated in the doc for HTTP-component:
Camel will store the HTTP response from the external server on the OUT body. All headers from the IN message will be copied to the OUT message, ...
I would like to know if this concept also applies to amq-component, routeId, and log? Is it the default behaviour, that IN always gets copied to OUT?
Thank you,
Hadi
First of all: The concept of IN and OUT messages is deprecated in Camel 3.x.
This is mentioned in the Camel 3 migration guide and also annotated on the getOut method of the Camel Exchange.
However, it is not (yet) removed, but what you can take from it: don't care about the OUT message. Use the getMessage method and don't use getIn and getOut anymore.
To answer your question:
Yes, most components behave like this
Every step in the route takes the (IN) message and processes it
The body is typically overwritten with the new processing result
The headers typically stay, new headers can be added
So while the Camel Exchange traverses the route, typically the body is continuously updated and the header list grows.
However, some components like aggregator create new messages based on an AggregationStrategy. In such cases nothing is copied automatically and you have to implement the strategy to your needs.
I'm attempting to use the Recipient List EIP to dynamically generate the consumer endpoint URI during runtime based on configuration entries in a database (http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html). I've got a number of routes that I want to handle this way so I'd like to build something that can handle multiple routes generically.
Therefore, my idea is to keep an in memory map of these URI values keyed on some type of identifying information (original endpoint URI seems like a logical choice) which would be updated if/when the database is updated to keep the routes in sync, and prevent having to go to the database for every exchange. Using the RouteBuilder, I am setting up the route with the recipient list and Bean expression.
from(endpointUri).recipientList(bean(MyBean.class, "getUri"));
I know that I can capture various objects such as the exchange, body, headers (as long as I know the name), etc using the Bean binding for the getUri method. Is it possible to somehow get the original endpoint URI value so that I can use it as a key to fetch the correct consumer endpoint?
The Exchange interface has getFromEndpoint() method which returns an Endpoint. The Endpoint interface has getEndpointUri() method which returns a String. Perhaps that's what you need? If that's not sufficient, you could set header value(s) at some point and then subsequently retrieve them later in your route.
I have a message with a certain value (e.g. 100, 101) in header and I need to take a specific action depending on that value.
I know I can write a route with when / otherwise branches for content-based routing.
My question is: what if I have about 400 different cases? Is there a best practice in these cases to manage the routing?
Yes use recipient list instead which can compute the endpoint dynamically - eg its a dynamic to. See this FAQ link for further details: http://camel.apache.org/how-do-i-use-dynamic-uri-in-to.html
another option is to use a ProducerTemplate to send messages to any endpoint from a POJO class, just need to inject/pass in a handle to the CamelContext, etc.
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.
It might be a silly question, but say I have a hughe message that I want to process with Camel. How will the number of steps in my route affect the memory usage? Does camel deep copy my message payload for every step in the route, even if the DSL-step only reads from the message or does it do something smart here?
Is it better to keep the route down and do things in a "hughe" bean for large messages or not?
This is an example route that does various things, but not changing the payload.
from("foo:bar")
.log(..)
.setProperty(..)
.setHeader(..)
.log(..)
.choice()
.when(simple(... ) )
.log(..)
.to(..)
.when(simple(..))
.log(..)
.to(..)
.end()
from my understanding, for a simple pipelined route like this, an Exchange is created containing the body once and passed along each step in the route. Other EIPs do cause the Exchange to be copied though (like multicast, wiretap, etc)...
as well, if you have steps along the route which interface with external resources which could result in any type of copy/clone/conversion/serialization of the body unnecessarily, then you might use something like the claim check pattern to reduce this.
The camel exchange is the same through the route the message objects are copied or recereated in the steps. The body is just referenced though. So normally you should not have a problem.
This is handled by each camel processor individually though. So some of the processors may copy the body. Typically this is the case when the processor really works on the body. So in this case it can not be avoided.