JMS Transport Retry behaviour

View: New views
11 Messages — Rating Filter:   Alert me  

JMS Transport Retry behaviour

by Pete M :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,
  I have (rather stupidly) built a retry capability into my application. It looks like I could have used the JMS transport to do this (It has a retry counter and persistence).  When the jms retry counter expires is an exception generated and routed via the default exception handler path?

Thanks

Pete

Re: JMS Transport Retry behaviour

by UWD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

If you mean the maxRedelivery property yes. You can set an exception strategy on your JMS connector as well.

Ulf

Pete M wrote:
Hi,
  I have (rather stupidly) built a retry capability into my application. It looks like I could have used the JMS transport to do this (It has a retry counter and persistence).  When the jms retry counter expires is an exception generated and routed via the default exception handler path?

Thanks

Pete

Re: JMS Transport Retry behaviour

by Pete M :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


UWD wrote:
If you mean the maxRedelivery property yes. You can set an exception strategy on your JMS connector as well.

Ulf

Hi, thanks for the reply.  I have set this up now.  
As a foloow on question, is it possible to delay the retry?  A jms message can have delivery time properties set.  can I cause these properties to be set on the retries so the retry doesnt occur until say after 3 hours?

Thanks

Pete

Re: JMS Transport Retry behaviour

by UWD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I don't know, but maybe you can implement your own RedeliveryHandler and handle it yourself if it's not possible in any other way. Check out the docs for the JmsProvider.

Pete M wrote:
UWD wrote:
If you mean the maxRedelivery property yes. You can set an exception strategy on your JMS connector as well.

Ulf

Hi, thanks for the reply.  I have set this up now.  
As a foloow on question, is it possible to delay the retry?  A jms message can have delivery time properties set.  can I cause these properties to be set on the retries so the retry doesnt occur until say after 3 hours?

Thanks

Pete

Re: JMS Transport Retry behaviour

by Pete M :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,
  I've just tried the following but it isn't redelivering, just a single delivery attempt.  Is there an obvious problem with the queue?

    <jms:activemq-connector name="targetServiceConnector" maxRedelivery="3"  connectionFactory-ref="amqConnectionfactory" >
      <mule:default-connector-exception-strategy>
        <mule:outbound-endpoint ref="operation.error"/>
      </mule:default-connector-exception-strategy>
    </jms:activemq-connector>

     <spring:bean name="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
       <spring:property name="initialRedeliveryDelay" value="5000"/>
     </spring:bean>

     <spring:bean name="amqConnectionfactory" class="org.apache.activemq.ActiveMQConnectionFactory">
       <spring:property name="redeliveryPolicy" ref="redeliveryPolicy"/>
     </spring:bean>


UWD wrote:
I don't know, but maybe you can implement your own RedeliveryHandler and handle it yourself if it's not possible in any other way. Check out the docs for the JmsProvider.

Re: JMS Transport Retry behaviour

by UWD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Don't think it's possible to get redelivering functionality without transaction support.
When you do a rollback(for example throw an exception from code) the transaction will be rolled back, and then the redelivery will be done.


Hi,
  I've just tried the following but it isn't redelivering, just a single delivery attempt.  Is there an obvious problem with the queue?

    <jms:activemq-connector name="targetServiceConnector" maxRedelivery="3"  connectionFactory-ref="amqConnectionfactory" >
      <mule:default-connector-exception-strategy>
        <mule:outbound-endpoint ref="operation.error"/>
      </mule:default-connector-exception-strategy>
    </jms:activemq-connector>

     <spring:bean name="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
       <spring:property name="initialRedeliveryDelay" value="5000"/>
     </spring:bean>

     <spring:bean name="amqConnectionfactory" class="org.apache.activemq.ActiveMQConnectionFactory">
       <spring:property name="redeliveryPolicy" ref="redeliveryPolicy"/>
     </spring:bean>


UWD wrote:
I don't know, but maybe you can implement your own RedeliveryHandler and handle it yourself if it's not possible in any other way. Check out the docs for the JmsProvider.


Re: JMS Transport Retry behaviour

by Pete M :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks for the help, this is working now.

I made a change like :
     <spring:bean name="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
       <spring:property name="initialRedeliveryDelay" value="5000"/>
       <spring:property name="maximumRedeliveries" value="3"/>
     </spring:bean>

The max redeliveries on the AMQ connector didnt seem to work.  Plus added in the transaction on the endpoint.


UWD wrote:
Don't think it's possible to get redelivering functionality without transaction support.
When you do a rollback(for example throw an exception from code) the transaction will be rolled back, and then the redelivery will be done.

Re: JMS Transport Retry behaviour

by Pete M :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

My mistake - its not really working.  There is no notification message.  The retry works but the exception strategy fails.  After the set number of retries nothing happens.  The exception strategy on the base connector  is being set but never gets called.  The expected exception gets logged but I just can't get a message routed with the exception in it.

It looks like I should have stuck to hand coded retries.


Thanks for the help, this is working now.

I made a change like :
     <spring:bean name="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
       <spring:property name="initialRedeliveryDelay" value="5000"/>
       <spring:property name="maximumRedeliveries" value="3"/>
     </spring:bean>

The max redeliveries on the AMQ connector didnt seem to work.  Plus added in the transaction on the endpoint.


UWD wrote:
Don't think it's possible to get redelivering functionality without transaction support.
When you do a rollback(for example throw an exception from code) the transaction will be rolled back, and then the redelivery will be done.


Re: JMS Transport Retry behaviour

by UWD :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hmmmm, We're using an older Mule version and this is how we've set it up:

On the JMS connector:
        <exception-strategy className="org.mule.impl.DefaultExceptionStrategy">
           <endpoint address="file://errorjms" connector="FileLogJMSConnector">
           </endpoint>
        </exception-strategy>

If a JMS message is received that has a format-error for example, our component will throw an exception, and after 2 redeliveries this happens:

15:17:28,069 ERROR org.mule.impl.DefaultExceptionStrategy [jmsConnector.Subscription.receiver.3] -
********************************************************************************
Message               : "Message with id "ID:427647BDB7AF23D764:1" has been redelivered "2" times, which exceeds the maxRedelivery setting on the connector. Message with id "ID:427647BDB7AF23D764:1" has been marked for redelivery, this usually happens after a transaction rollback. Message payload is of type: com.tibco.tibjms.TibjmsTextMessage

15:17:29,321  INFO org.mule.providers.file.FileMessageDispatcher [jmsConnector.Subscription.receiver.3] - Successfully connected to: file://errorjms

15:17:29,331  INFO org.mule.providers.file.FileMessageDispatcher [jmsConnector.Subscription.receiver.3] - Writing file to: errorjms\Error_JMS_2008-08-29.xml

The Error log contains the JMS Message and a message that the exception is an org.mule.providers.jms.MessageRedeliveredException, so it's not actually the exception that was thrown from our component.

My advice is to set an exception-strategy for the component(mule-descriptor) and model as well, and maybe see if anyone of them gets called instead...

Pete M wrote:
My mistake - its not really working.  There is no notification message.  The retry works but the exception strategy fails.  After the set number of retries nothing happens.  The exception strategy on the base connector  is being set but never gets called.  The expected exception gets logged but I just can't get a message routed with the exception in it.

It looks like I should have stuck to hand coded retries.

Re: JMS Transport Retry behaviour

by Andrew Perepelytsya :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This could be the difference between Tibco EMS and ActiveMQ. The latter had it's own redelivery system beyond jms redeliveries, and many people have found it confusing and often not working as expected.

Not helping, but could save some time maybe...

Andrew

Re: JMS Transport Retry behaviour

by Pete M :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Here is my solution - its not pretty.
I need the ActiveMQ transport to retry a configurable number of times then give up and tell me with an exception I can catch in an exception strategy.

Created a custom exception handler that overrides :
public void handleTransaction(Throwable t) and does nothing, and
public void handleMessagingException(MuleMessage message, Throwable t)

Mule seems to call handleTransaction first then handleMessagingException.

I do the work of handle transaction in the handleMessageException method.

ActiveMQ causes the handleMessageException  to be called on each retry.  I configure the exception strategy  with the same retry count as AMQ, and examine the current retry value on the AMQ message.            
  If there try count is not expired I just pass the exception on up to the super class.  If the has expired I replace the exception with a synthetic one indicating a retry failure.  ie I replace t with a new different exception.  


        if (retryCounter >= (maxRetries - 1)) {
            super.handleTransaction(t1);
            super.handleMessagingException(message, t1);
        } else {
            super.handleTransaction(t);
            super.handleMessagingException(message, t);
        }
In the strategy configuration I control the transaction roll back and commit like :


          <mule:custom-exception-strategy  class="failurerecovery.CustomExceptionStrategy">

            <mule:commit-transaction exception-pattern="failurerecovery.CommitException"/>
            <mule:rollback-transaction exception-pattern="target.TargetServiceException"/>
           
            <spring:property name="maxRetries" value="${service.maxretries}"/>
             
            <spring:property name="endpoints">
              <spring:list>
                <spring:ref bean="my.errorhandler"/>
              </spring:list>
            </spring:property>            
                       
          </mule:custom-exception-strategy>

This does what I need it to do.

Pete



Andrew Perepelytsya wrote:
This could be the difference between Tibco EMS and ActiveMQ. The latter had
it's own redelivery system beyond jms redeliveries, and many people have
found it confusing and often not working as expected.

Not helping, but could save some time maybe...

Andrew