Thursday, May 21, 2015

Apache Camel Redelivery Policy

Problem Statement

Continuing on the problem described in my previous post I wanted that once an exception occurs in my route, instead of trying to poll the request again, the route should sleep for a while say half an hour. This would give sufficient time for servers to stabalize and avoid unnecessary polling.

Issue
I used camel redeliveryPolicy to do this. Since i wanted that the request be polled until it was successfully process and not for some predefined max retries, I specified only redeliveryDelay.
   <camel:onException>
        <camel:exception>java.lang.Exception</camel:exception>
        <camel:redeliveryPolicy redeliveryDelay="50000" />
        <camel:log message="Default error handler was called"></camel:log>
    </camel:onException>


Even though onException was getting invoked delay was not taking effect.

Solution
On my colleague's advice i added maximumRedeliveries tag as well and finally delay took effect. Code snapshot that worked below:
 <camel:onException>
  <camel:exception>java.lang.Exception</camel:exception>
  <camel:redeliveryPolicy maximumRedeliveries="1" redeliveryDelay="50000" />
  <camel:log message="Default error handler was called"></camel:log>
 </camel:onException>


So seems like in redeliveryPolicy, maximumRedeliveries and redeliveryDelay go hand in hand.

Wednesday, April 22, 2015

Apache Camel - Read file recursively instead of moving it to .camel folder

Problem Statement

Read a file from input folder, check memory consumption on server and process it only if its below threshold limit else let the request remain in input folder.

Issue

Request was getting moved to .camel folder after camel route read it as a result it was not being picked up recursively for processing.

Solution

In your camel route add a processor that checks memory consumption. If its above limit the processor should throw an exception. This will mark message as failed and file consumer wont put it in .camel folder. Instead it will be picked up for processing again.
Sample Spring DSL below:
<camel:camelContext xmlns="http://camel.apache.org/schema/spring">
<camel:route>
<!-- 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"/>
<to uri="<jms queue"
pattern="InOut" />
</camel:route>
</camel:camelContext>

If you look above code snippet closely, you will that I am using convertBodyTo tag of Camel. This is being used because when reading request xml from folder and directly putting it on JMS queue I was getting below error:
org.apache.activemq.command.ActiveMQBytesMessage cannot be cast to javax.jms.TextMessage
java.lang.ClassCastException: org.apache.activemq.command.ActiveMQBytesMessage cannot be cast to javax.jms.TextMessage
        at com.qwest.mdw.listener.jms.JmsListener.start_in_thread(JmsListener.java:116)

        at com.qwest.mdw.listener.jms.JmsListener$1.run(JmsListener.java:158)