Apache Camel Exchange to Propagate from one process to another - apache-camel

I am looking out for a way by which in Apache Camel, I can stop a exchange to propagate from one process to another, without stoping and restarting the route itself. I had below route configured and what I am basically looking out is to return the exchange from messageMultiplierProcessor based on some conditions without changing/modifying the exchange body or setting/resetting it headers.
<route id="business-logic-route">
<from uri="direct:business-logic-endpoint"/>
<setProperty propertyName="esq.route.name">
<constant>TestRoute</constant>
</setProperty>
<process ref="messageMultiplierProcessor" />
<process ref="calculatedFieldsProcessor" />

You can conditionally stop a route at any point using "when" & "stop":
<when>some condition</when>
<stop/>

Related

Apache Camel AMQP with selector is consuming any message

I am trying to use selectors on an amqp with Azure Service Bus consumer. However, for some reason the route is also consuming messages that do not match the selector.
Here's an example:
This route generates messages and append a header:
<route id="MessageGenerator">
<from uri="timer:generator?delay=5000&period=5000"/>
<setHeader headerName="INSTANCE_ID">
<simple>{{env:INSTANCE_ID}}</simple>
</setHeader>
<to uri="amqp:queue:external_queue" />
</route>
While this route should consume only those that contain INSTANCE_ID matching 2 possible values: env:INSTANCE_ID or Any.
<route id="ExternalConsumer">
<from uri="amqp:queue:external_queue?selector=INSTANCE_ID IN ('{{env:INSTANCE_ID}}', 'Any')"/>
<log message="{{env:INSTANCE_ID}} consumed message with Instance ID: ${header.INSTANCE_ID}" logName="AMQP_TEST" loggingLevel="INFO"/>
</route>
But the the log shows that it is consuming any message, regardless of the selector specifying which ones.
Am I missing something?
Thanks!
Issue here was that Azure Service Bus does NOT support selectors on queues. I switched to topics, which already have filters per subscription.

Exchange id in camel request ends with even number

I am using Apache Camel in OSGI scenario using Karaf in version 2.15.1. I am using the exchange.getExchangeId() to print the exchange id in a request/reply. The exchange pattern is set to InOnly. The route looks like this:
<route id="ip_client_rpc">
<from uri="restlet:http://localhost:7070/lsp/patron/id?restletMethod=POST&synchronous=true"/>
<to uri="log:${headers}"/>
<setExchangePattern pattern="InOnly"/>
<process ref="rabbit_client"/>
<to uri="log:${headers}"/>
</route>
However when I print the exchange id sent to the rabbitmq queue it always ends with an even number.
Request from client:ID-VirtualDev-49301-1443430754519-5-6
Request from client:ID-VirtualDev-49301-1443430754519-5-8
Request from client:ID-VirtualDev-49301-1443430754519-5-10
Request from client:ID-VirtualDev-49301-1443430754519-5-12
Request from client:ID-VirtualDev-49301-1443430754519-5-14
Is there a reason why the final digit is always even? Is there another exchange being created that I am missing?
Thanks
Camel uses the same id generator for generating unique ids for different things, its just by chance that its even in this case. Could be that a breadcrumb or message id was also generated that takes the odd number.

Catching exception across camel contexts

I have two routes - each in a different camel context:
<camelContext id="camelContext1" xmlns="http://camel.apache.org/schema/blueprint">
<onException>
<exception>com.me.MyException</exception>
<to uri="log:osgiExecutorLog"/>
</onException>
<route id="MyRoute">
<from uri="amq:test" />
<to uri="direct:MyDirect"/>
</route>
</camelContext>
<camelContext id="camelContext2" xmlns="http://camel.apache.org/schema/blueprint">
<route id="MyRoute">
<from uri="direct:MyDirect" />
<process ref="myProc"/>
</route>
</camelContext>
There are conditions where myProc will throw MyException and I want the onException in camel context 1 to catch that. I tried my luck hard but could not get that to work; is it like catching exceptions across camel contexts not supported or am I missing something?
Instead of trying to throw an exception back to the other context (which may or may not even be possible due to the mechanisms in camel 2.x) you could catch the exception and send a message to some sort of error handling endpoint.
This can be easily defined in a different route builder or context, as long as you know the endpoint name.
Each route then has exactly the same boilerplate exception handler at the top, for example:
onException(Exception.class).handled(true).to("direct-vm:errors")
We routinely use this sort of custom error handling between different route builders (in the same context, but the pattern can apply across contexts just as easily).
In our application, for example, we catch the exceptions, aggregate them in a list, and whenever 15 seconds goes by without a new exception we send an email via smtp - all too easy with a camel route defined as from("direct:errors")...

infinite message delivery loop with activeMQ and Broker Camel Component

I'm using activeMQ 5.9.
I'm trying to implement an interception type route in my activemq.xml, where I check if a particular header equals some value then send it to a different queue, otherwise allow it to continue.
I'm following the info here: http://activemq.apache.org/broker-camel-component.html
My camel.xml file looks like this:
<camelContext id="camel" trace="false" xmlns="http://camel.apache.org/schema/spring">
<route id="routeAboveQueueLimitTest">
<from uri="activemq:queue:do.something"/>
<choice>
<when>
<simple>${header.scope} == 'test'</simple>
<to uri="activemq:queue:test.do.something"/>
</when>
<otherwise>
<to uri="activemq:queue:do.something"/>
</otherwise>
</choice>
</route>
</camelContext>
Then when I put a message on "activemq:queue:do.something" with header called scope = "test" it correctly routes to the "activemq:queue:test.do.something" queue. However, when it doesn't have that header, it puts it back on the "activemq:queue:do.something" queue and processes it again and again and again!
That kind of seems logical, but the above page clearly says that you have to explicitly send it back to the broker component, and the 2nd example on the page shows exactly that.
I realise this could be worked around by sending it to a different queue if it doesn't have the header but that is undesirable at this stage.
I think the intercept pattern would be much better suited for what you are looking.
<intercept>
<when><simple>${header.scope} == 'test'</simple></when>
<to uri="activemq:queue:test.do.something"/>
</intercept>
More info here: http://camel.apache.org/intercept.html
This will allow messages without the scope header set to 'test' to continue, but will redirect messages that do have the test header.
InterceptSendToEndpoint is a better option here...
<interceptSendToEndpoint uri="activemq:queue:do.something">
<when><simple>${header.scope} == 'test'</simple></when>
<to uri="activemq:queue:test.do.something"/>
<stop/>
</interceptSendToEndpoint>

Camel: communicating between two routes

I'm basically new to camel. I set up a camel context with two routes that are using seda endpoints.
Simplyfying, all starts with a "from" file endpoint (sorry for the terminology if wrong) listening on a directory:
<route>
<from uri="file:mydir"/>
<process ref="a bean that change the body of the message by setting a custom object"/>
<to uri="seda:incoming"/>
</route>
<route>
<from uri="seda:incoming"/>
<process ref="a bean that does something with the custom object above"/>
....
</route>
now, what described above works perfectly but i need to change seda with activemq queues and after doing that the body of the message received by the 2nd processor is empty.
How can I obtain the same behaviour of seda endpoints using activemq channels?
exchange.getIn().setBody(myCustomBean)
and
exchange.getIn().setHeader("inputfile", aFileInstance)
If you expect to get some result when aquiring from activemq queue, you should send serializable object to queue. Otherwise object will not be transferred.
At your case there's no guarantee that myCustomBean and aFileInstance are serializable.
Basically try sending the Strings into the queue. Or make your objects serializable.

Resources