camel: use header value in multiple routes - apache-camel

Is it possible to set a header in one route and then use it again later in another route in the same context?
For example, I have a route that sets a header as so:
<setHeader headerName="clientId">
<xpath>/Alarm/clientid/text()</xpath>
</setHeader>
The route uses Dead Letter Channel to send the message to an error route in the same context when delivery fails and I would like to use the clientId header I defined above in the message the error route sends, but currently calling the header returns nothing (an empty string I assume).

It should work , I am using camel 2.15.1 ,check the code below , if you run it you should see the header
<bean id="mybean" class="java.lang.Exception" />
<camel:camelContext xmlns="http://camel.apache.org/schema/spring"
trace="false">
<camel:errorHandler id="deadLetterErrorHandler"
type="DeadLetterChannel" deadLetterUri="direct:b">
</camel:errorHandler>
<camel:route>
<camel:from uri="timer:foo?repeatCount=1" />
<camel:setHeader headerName="myheader">
<camel:simple>Sundar</camel:simple>
</camel:setHeader>
<camel:to uri="direct:a" />
</camel:route>
<camel:route errorHandlerRef="deadLetterErrorHandler">
<camel:from uri="direct:a" />
<camel:throwException ref="mybean"></camel:throwException>
</camel:route>
<camel:route>
<camel:from uri="direct:b" />
<camel:log message="${in.header.myheader}"/>
</camel:route>
</camel:camelContext>
It should print a log like below
24 Feb 2016 19:09:47,707 route3 INFO Sundar

Related

Camel blueprint <setHeader headerName="CamelHttpPath" id="_setHeader1"><el>${header.uriPattern}</el></setHeader> waiting for dependencies

I have the following Camel Context.
<camelContext id="_camuatomicservicecontext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="_camuatomicserviceroute1">
<from id="_from1" uri="direct-vm:camuatomicservice">
<description>accepts vm messages directly </description>
</from>
<log id="_log1" message="Camu Atomic Service body = ${body}, header= ${header.uriPattern}"/>
<!-- <to id="_to1" uri="restlet:protocol:localhost:8189/"/> -->
<setHeader headerName="api.key" id="_setHeader1">
<constant>replace later with properties api.key Does not matter for this poc</constant>
</setHeader>
<setHeader headerName="CamelHttpPath" id="_setOutHeader1">
<el>${header.uriPattern}</el>
</setHeader>
<to id="_to1" pattern="InOut" uri="netty4-http:http:localhost:8189/path"/>
<log id="_log2" message="CamuAtomicService Response body ${body}"/>
</route>
</camelContext>
From the documentation I expect the CamelHttpPath header to override the endpoint configuration "/path" such that calling Facade Services can pass the header.uriPattern in and dynamically change the resource they want to access. The bundle worked fine until I added the setHeader for CamelHttpPath and now getting "Waiting for dependencies." I assume I need to install a feature, but Simple EL in other bundles on that server work already so not sure what feature I need to install.
Instead of I used and it worked fine. The choice was farther down in the options.

rabbitMQ message forwarding from one queue to another

Could you please help me to resolve the problem I am facing?
When forwarding message from one queue to another ( no message seems to be published ) ,
steps:
timer publish current date to queue 'inbox'- this part working
from 'inbox' to 'outbox' - this is not working
from 'outbox' to print console
Follows the spring xml.
<route>
<camel:from
uri="rabbitmq://localhost:5672/outBox?sername=guest&password=guest" />
<camel:to uri="stream:out" />
</route>
<route>
<camel:from
uri="rabbitmq://localhost:5672/inbox?username=guest&password=guest" />
<camel:to
uri="rabbitmq://localhost:5672/outBox?username=guest&password=guest" />
</route>
<route>
<camel:from uri="timer:foo?period=10" />
<setBody>
<simple>${body}Message at ${date:now:yyyy-MM-dd HH:mm:ss}</simple>
</setBody>
<to
uri="rabbitmq://localhost:5672/inbox?username=guest&password=guest" />
</route>
According to http://camel.apache.org/rabbitmq.html the URI format is
rabbitmq://hostname[:port]/exchangeName?[options]
Thus inbox in your code is not queue name but exchange.
Use queue= option to specify the queue

Apache Camel - Delay when exception occurs

I have written a camel route that polls a file folder, picks up request, checks for memory consumption on server (in a java file). If its below threshold it drops the request on a JMS queue otherwise it throws an exception and picks it again for processing.
What i need to do is that when exception is thrown i need to delay processing for a configurable amount of time say 15 mins. This will give some time for server to stabilize instead of keeping it polling unnecessarily.
I am using errorHandler mechanism of camel however it doesnt seem to work. Camle keeps on picking up the request without any delay. Please help with this issue.
Below is the bundle context snapshot:
<camel:onException>
<camel:exception>java.lang.Exception</camel:exception>
<camel:redeliveryPolicy backOffMultiplier="500" />
<camel:log message="Default error handler was called"></camel:log>
</camel:onException>
<camel:route>
<!-- Reading from REST url -->
<camel:from uri="<my url>" />
<!-- If else loop -->
<camel:choice>
<camel:when>
<camel:xpath>Some path</camel:xpath>
<!-- Parsing OrderNumber and OrderVersion-->
<camel:log message="Recieved request ${headers.OrderNumber}-${headers.OrderVersion}.xml"/>
<camel:setHeader headerName="OrderNumber">
<xpath>Some path</xpath>
</camel:setHeader>
<camel:setHeader headerName="OrderVersion">
<camel:xpath>Some path</camel:xpath>
</camel:setHeader>
<!-- Request being put in file folder -->
<to
uri="file:data/inbox?fileName=${header.OrderNumber}-${header.OrderVersion}.xml"
pattern="InOut" />
</camel:when>
<!-- For all other requests put on queue -->
<camel:otherwise>
<camel:log message="Request ${headers.OrderNumber}-${headers.OrderVersion}.xml directly sent to queue"/>
<to uri="my queue"
pattern="InOut" />
</camel:otherwise>
</camel:choice>
</camel:route>
<camel:route errorHandlerRef="errorHandler">
<!-- Route to put message from folder to JMS queue if memory consumption is below limit-->
<camel:from uri="file:data/inbox"/>
<camel:process ref="checkMemoryConsumption"/>
<camel:convertBodyTo type="String" />
<camel:log message="Sucessfully processing service order ${headers.OrderNumber}-${headers.OrderVersion}.xml"/>
<to uri="my queue"
pattern="InOut" />
</camel:route>
Did you try redeliveryDelay of redeliveryPolicyProfile?
Below policy profile will retry 3 times with the delay of 1000mS between each try.
<redeliveryPolicyProfile id="myRedeliveryProfile"
maximumRedeliveries="3"
redeliveryDelay="1000" allowRedeliveryWhileStopping="false"
retryAttemptedLogLevel="INFO" />
Read more on here
By making below modification in my bundle context (bundle context displayed above), re-delivery policy kicked in and seems to do the trick.

Reading Camel Constant From Property file

I am trying to read time delay from property file .
have defined in my property file :
time_inMilis=15000
I have configured my camel context xml to be :
<bean id="property" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:/D:/Develop/resources/my.properties
</value>
</property>
</bean>
<camel:camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" location="file:/D:/Develop/resources/my.properties"/>
<camel:route id="delayQueue">
<camel:from uri="seda:queue1" />
<delay asyncDelayed="true">
<constant>${time_inMilis}</constant>
</delay>
<camel:to uri="seda:queue2" />
</camel:route>
</camel:camelContext>
camel do not throw any error but it seems that it ignores ${time_inMilis} and set 0 for my delay time.
What is the right way to read the delay constant from my property file ?
First, it would be enough just to use camel:propertyPlaceholder instead of declaring bean property.
Second mistake is that you are using Constant instead of Simple expression when trying to read your time_inMilis property value.
Third, when trying to get value of you property, you should specifically tell Camel that your are looking at properties.
If your context defines propertiesPlaceholder like this:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="props" location="classpath:/org/smp/eip/sample.properties"/>
<package>org.apache.camel.example.spring</package>
</camelContext>
them with java DSL you'll be able to read the textProeprty value like this
from("file:src/data?noop=true")
.transform().simple("Text read from properties: ${properties:textProperty}")
.bean(new SomeBean());
Using Spring DSL from your original post, the correct way of reading property would be:
<camel:route id="delayQueue">
<camel:from uri="seda:queue1" />
<delay asyncDelayed="true">
<simple>${properties:time_inMilis}</simple>
</delay>
<camel:to uri="seda:queue2" />
</camel:route>

how to write concise apache camel xml

I am new to Apache Camel. I have setup my application to use Apache Camel using XML based configuration. My configuration contains multiple routes which have similar set of steps. I was trying to find if there a way to place common or repeating parts of these different routes in one place and refer them from routes instead of repeating them again and again ?
for e.g. in my below camel route configuration, route 2 is repeating few steps from route 1. So is there a way to extract the common steps of the route 1 and route 2 and then refer extracted part from route 1 and 2?
<context:property-placeholder location="classpath:quartz.properties" />
<context:component-scan base-package="com"></context:component-scan>
<camel:route>
<camel:from uri="quartz://deadlines/SDGWD?cron=15+34+14+?+*+MON-SUN+*" />
<camel:onCompletion>
<camel:to uri="seda:checkAnyPendingDeadlines"/>
</camel:onCompletion>
<camel:to uri="bean:sdgwdNotifier" />
<camel:choice>
<camel:when>
<camel:method ref="deadlineHandler" method="canProcessDeadline" />
<camel:bean ref="deadlineHandler" method="prepareDeadline" />
<camel:bean ref="sdgwdProcessor" method="initiateMessageProcessing" />
<camel:bean ref="schedulerXdrTransformer" method="marshall" />
<camel:to uri="wmq:SU.SES" />
<camel:bean ref="sdgwdProcessor" method="waitForAcknowledgment" />
<camel:bean ref="sdgwdProcessor" method="afterMessageProcessed" />
<camel:bean ref="deadlineHandler" method="onDeadlineProcessingCompletion" />
</camel:when>
<camel:otherwise>
<camel:bean ref="deadlineHandler" method="enqueDeadline" />
</camel:otherwise>
</camel:choice>
</camel:route>
<camel:route>
<camel:from uri ="seda:checkAnyPendingDeadlines"/>
<camel:onCompletion>
<camel:to uri ="seda:checkAnyPendingDeadlines"/>
</camel:onCompletion>
<camel:to uri="bean:deadlineHandler?method=getNextProcessableDeadline" />
<camel:choice>
<camel:when>
<camel:method ref="deadlineHandler" method="canProcessDeadline" />
<camel:bean ref="deadlineHandler" method="prepareDeadline" />
<camel:choice>
<camel:when>
<camel:simple>${body.deadline} == ${type:settlementcontrol.scheduler.model.Deadline.SDGW} </camel:simple>
<camel:bean ref="sdgwdProcessor" method="initiateMessageProcessing" />
<camel:bean ref="schedulerXdrTransformer" method="marshall" />
<camel:to uri="wmq:SU.SES" />
<camel:bean ref="sdgwdProcessor" method="waitForAcknowledgment" />
<camel:bean ref="sdgwdProcessor" method="afterMessageProcessed" />
<camel:bean ref="deadlineHandler" method="onDeadlineProcessingCompletion" />
</camel:when>
</camel:choice>
</camel:when>
<camel:otherwise>
<camel:bean ref="deadlineHandler" method="enqueDeadline" />
</camel:otherwise>
</camel:choice>
</camel:route>
Thanks,
Vaibhav
Is common route, which contains repeating part of your flow, sufficient? If so, then create something like this:
<camel:route id="myCommonPartOfFlow">
<camel:from uri="direct-vm:common-in"/>
[common part]
</camel:route>
You can invoke your sub (myCommonPartOfFlow) route from your main routes now:
<camel:to uri="direct-vm:common-in/>
You can either use a direct component to create subroutes that factor out common parts or split your routes so that the common routes have their own route and then other routes can send messages to the common route. For example, if you have two routes that do the following processes "Process A" -> "Process B" -> "Process C" and "Process D" -> "Process B" -> "Process E" then you can separate Process B into its own route and do the following:
from("jms:queue:processB") - "Process C" -> end()
Process A -> set Header "JMSReplyTo", jms:queue:processC -> to("jms:queue:processB")
Process C -> set Header "JMSReplyTo", jms:queue:processE -> to("jms:queue:processB")
The for the sake of brevity I used Java DSL but the same can be done with XML DSL. I also used "process A" and the like to abstract what could be multiple steps in the route. The concepts of linking the routes is the same no matter what the process is. The advantage to this approach is that it allows federation of "process B" to handle the extra load and distribute processing around your infrastructure. Once you go to Asynchrounous programming, your capabilities rise quite a bit.

Resources