I'm trying to make timer using camel to execute some method in bean every 5 sec for example.
I defined in camel context timer route :
<camel:route id="PERGING-sent">
<from uri="timer://foo?fixedRate=true&period=5000"/>
<to uri="bean:purger?method=purge"/>
<to uri="mock:result"/>
</camel:route>
the problem in that every 5 sec this method is executing twice !
Very odd...
What can I do to prevent this from happening ?
I found the Problem.
some were in the code I call twice to :
context = new `ClassPathXmlApplicationContext("MyCamelContext.xml")`
so the routing is creating twice , so is the timer.
Related
I noticed that after successful doTry/doCatch handling global onException handler is no longer invoked. Here's my sample code:
<doTry>
<to uri="direct:triggerError"/>
<doCatch>
<exception>com.foo.bar.MyException</exception>
<log message="IN DOCATCH"/>
</doCatch>
<doFinally>
<log message="IN FINALLY"/>
</doFinally>
</doTry>
<throwException message="Now handle it in global handler" exceptionType="com.foo.bar.MyOtherException"/>
And in my camel context I have this:
<onException>
<exception>com.foo.bar.MyOtherException</exception>
<handled>
<constant>true</constant>
</handled>
<log message="HANDLING MY OTHER EXCEPTION"/>
<to uri="direct:commonAPIErrorProcessor"/>
</onException>
What I observe is the exception is properly caught in doCatch and doFinally is invoked, but the global onException is never called and I get a stack trace in response. How can I fix it?
I tried it with Camel 3.4.0 and 3.7.0, same results.
The problem in your example is that you call another route within doTry. This seems to confuse the Camel no matter if you use XML or Java DSL (in both DSLs the same effect).
As long as you use simple "statements" in doTry, everything works perfect. When you call another route, it is as you describe very confusing.
Camel catches the exception thrown by the other route, but afterwards the error handler stays "disabled". It seems like Camel loses the doTry scope and therefore never finishes the "error handling disabled state" that is enabled by doTry.
I therefore assume that the "route jump" is not the intended use case for doTry/doCatch. Since it overwrites the normal error handling, it should probably be used only very locally within a route.
I have an Apache Camel route which invokes restlet component. To better understand what is happening at runtime I also keep the execution state in a database (number of retries, last execution state). I would like to use the redelivery mechanism from the exception handler but which performs some processing on every failure to update my database record.
<bean class="com.tcl.ExceptionOccurredRefProcessor" id="exProc" />
<camelContext errorHandlerRef="eh">
<errorHandler id="eh" onExceptionOccurredRef="exProc"> <redeliveryPolicy
maximumRedeliveries="3" maximumRedeliveryDelay="2000"
retryAttemptedLogLevel="WARN" />
</errorHandler>
<to uri="-------"/> //Invoke rest service
<onException id="_onException1" onExceptionOccurredRef="exProc" useOriginalMessage="true">
<exception>java.lang.Exception</exception>
<handled>
<simple>true</simple>
</handled>
...........
</onException>
</camelContext>
For this I tried to use onExceptionOccurred component with redelivery component and referred on camelContext as in above code but the message got delivered only once and stopped the execution.
Any suggestions please?
First of all: the code you pasted is a bit confusing because there is no Camel route, just a plain to element that cannot be alone in the Camel context.
However, I guess your problem is a "hidden" Camel handling. As documented in the Camel Docs of the Exception Clause, the onException clause overrides the maximumRedeliveries to 0 by default unless you explicitly set the option.
<onException>
<exception>java.lang.Exception</exception> // max. redelivery = 0
</onException>
<onException>
<exception>java.lang.Exception</exception>
<redeliveryPolicy maximumRedeliveries="3"/> // max. redelivery = 3
</onException>
I an not sure about the other redelivery options like maximumRedeliveryDelay, but at least the maximumRedeliveries is overridden if not explicitly set.
I have my camel setup along the lines of:
<route>
<from ur="servlet:///test"/>
<to uri="direct:check1"/>
<to uri="direct:check2"/>
<to uri="direct:check3"/>
<to uri="direct:myprocessor"/>
</route>
Since I'm setting this up as a request/reply (in-out) pattern, I'm confused around if there is a process-stopping issue on check1, 2, or 3 on one specific message/exchange how to 'fast fail' a response back without going through the rest of the routes?
Throwing exceptions and using the onException DSL will achieve what you need. If you throw an exception in one of the checks it will be caught in the onException block without going further through the rest of the route.
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>
We have a camel route that looks at a file and processes potentially hundreds of records on this file, almost like a batch routine (yet there will only be one message in camel). Thus the message will take potentially minutes or maybe hours to complete. We want to shut down the queue once this message (and any others waiting) are complete.
We have the following to consider:
The shutdown strategy defines the time to wait for a route to stop before a forced shutdown
<bean id="shutdown" class="org.apache.camel.impl.DefaultShutdownStrategy">
<property name="timeout" value="#[bpf.defaultShutdownStrategy.timeout]"/>
</bean>
The route has a parameter shutdownRunningTask="CompleteAllTasks" which should wait untill all messages processed.
Not sure which is going to take presidence as the timeout once exceeded is not graceful, it will force shutdown and for our scneario it is likely we will exceed a timeout, as we cannot predict how long processing will take.
Any ideas/considerations?
Thanks in advance.
You should look at the onCompletion functionality. It adds a new route in a separated thread when the Exchange is complete.
Here is some examples from the Camel documentation:
Java DSL
// define a global on completion that is invoked when the exchange is complete
onCompletion().to("log:global").to("mock:sync");
from("direct:start")
.process(new MyProcessor())
.to("mock:result");
XML DSL
<!-- this is a global onCompletion route that is invoke when any exchange is complete
as a kind of after callback -->
<onCompletion>
<to uri="log:global"/>
<to uri="mock:sync"/>
</onCompletion>
<route>
<from uri="direct:start"/>
<process ref="myProcessor"/>
<to uri="mock:result"/>
</route>
Then, here is documentation on how to stop a route in Camel.