JMS local transaction attempts end after the fourth one

angel.p.arenas.gmail.com's picture
Hi, I´m working on a proxy service that listens from a jms queue, and sends the message to another service proxy.  The idea is to keep the message on the queue until the message gets successfuly delivered.  Following is my proxy service config, but only works for the first four attempts after which it ends consuming the message from the queue and losing the message altogether.  What I would like is: 1)  To be able to run this number of attempts for ever until the other end becomes available 2)  To have a minute lapse between attempts of delivery     <proxy xmlns="http://ws.apache.org/ns/synapse" name="TRANSACTED.TESTING.QUEUE" transports="jms" startOnLoad="true" trace="enable">         <target faultSequence="myFaultHandler">             <endpoint name="endpoint_urn_uuid_1DD59CE6F5497EC1964172978494106350142830204">                 <address uri="http://10.1.24.21:8283/services/TransactedProxy" optimize="mtom"/>             </endpoint>             <inSequence>                 <property name="OUT_ONLY" value="true"/>                 <send/>             </inSequence>             <outSequence>                 <send/>             </outSequence>         </target>         <parameter name="transport.jms.ContentType">             <rules>                 <jmsProperty>contentType</jmsProperty>                 <default>text/plain</default>             </rules>         </parameter>         <enableRM/>     </proxy>     <sequence xmlns="http://ws.apache.org/ns/synapse" name="myFaultHandler">         <makefault version="soap11">             <code xmlns:tns="http://www.w3.org/2003/05/soap-envelope" value="tns:Receiver"/>             <reason expression="get-property('ERROR_MESSAGE')"/>         </makefault>         <property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>     </sequence>   Thanks, Angel
indika's picture

Hi This may be related to

Hi This may be related to the redelivery policy of the JMS provider "As a message is rolled back it will be redelivered. Most good JMS providers, such as ActiveMQ will have a configurable maximum redelivery count - on which point it will be consumed from the queue and sent to a dead letter queue."[1] ActiveMq redelivery policy[2] Indika [1] http://www.theserverside.com/discussions/thread.tss?thread_id=35751#180662 [2] http://activemq.apache.org/redelivery-policy.html
werdex86.yahoo.com's picture

Hi! 1) Is it possible to get

Hi! 1) Is it possible to get in jms proxy current delivery attempt number?   2) I have read http://activemq.apache.org/redelivery-policy.html and tried to use initialRedeliveryDelay:                   <parameter name="myQueueTransactionFactory" locked="false">             <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>             <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>             <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>         <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter> <parameter name="transport.jms.SessionTransacted" locked="false">true</parameter> <parameter name="transport.Transactionality">local</parameter>                     <parameter name="initialRedeliveryDelay">5000</parameter>         </parameter> Http service which sends message is : <proxy name="DeliveryService" transports="http" startOnLoad="true" trace="enable"> <target>     <endpoint>         <address                 uri="jms:/DeliveryServiceJMS?transport.jms.DestinationType=queue&amp;transport.jms.ContentTypeProperty=Content-Type&amp;java.naming.provider.url=tcp://localhost:61616&amp;java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&amp;initialRedeliveryDelay=5000&amp;transport.jms.SessionTransacted=true&amp;transport.jms.ConnectionFactoryType=queue&amp;transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&amp;transport.Transactionality=local"/>     </endpoint> </target> </proxy> Here is JMS proxy: <proxy xmlns="http://ws.apache.org/ns/synapse" name="DeliveryServiceJMS" transports="jms" startOnLoad="true"        trace="enable">     <parameter name="transport.jms.ConnectionFactory">myQueueTransactionFactory</parameter>     <target>         <parameter name="transport.jms.ContentType">             <rules>                 <jmsProperty>contentType</jmsProperty>                 <default>text/plain</default>             </rules>         </parameter>         <inSequence>             <send>                 <endpoint>                     <address uri="http://localhost:8280/services/TestService"/>                 </endpoint>             </send>             <property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>         </inSequence>         <outSequence>             <send/>         </outSequence>     </target> </proxy>     But this property does not work. Message is redelivered immediatly several times without delay. Maybe i incorrectly passed parameter to connection factory? Thx!
werdex86.yahoo.com's picture

Need to use redeliveryPolicy

Need to use redeliveryPolicy prefix: `                       <parameter name="redeliveryPolicy.redeliveryDelay">5000</parameter>                     <parameter name="redeliveryPolicy.initialRedeliveryDelay">5000</parameter>                     <parameter name="redeliveryPolicy.maximumRedeliveries">60</parameter> But only maximumRedeliveries works,redeliveryDelay and initialRedeliveryDelay are ignored. I have written stand alone JMS producer/consumer and redeliveryPolicy.initialRedeliveryDelay and redeliveryPolicy.redeliveryDelay works fine, but ignored for some reason at esb.
werdex86.yahoo.com's picture

Any suggestions why only

Any suggestions why only maximumRedeliveries works? Maybe Axis2 JMS overrides or ignores this settings? Where i can start to debug JMS in ESB? Thx
werdex86.yahoo.com's picture

I tested redeliveryDelay

I tested redeliveryDelay using InitialContext and properties are filled properly, so axis2 should construct properly configured connection factory:   Properties properties = new Properties();         properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");         properties.put(Context.PROVIDER_URL, "tcp://proj-jakimovp:61616");         properties.put("redeliveryPolicy.maximumRedeliveries", "15");         properties.put("redeliveryPolicy.initialRedeliveryDelay", "5000");         properties.put("redeliveryPolicy.redeliveryDelay", "6000");         InitialContext context = new InitialContext(properties);         ActiveMQConnectionFactory connectionFactory = (ActiveMQConnectionFactory) context.lookup("ConnectionFactory");         System.out.println(connectionFactory.getRedeliveryPolicy().getMaximumRedeliveries());         System.out.println(connectionFactory.getRedeliveryPolicy().getRedeliveryDelay());         System.out.println(connectionFactory.getRedeliveryPolicy().getInitialRedeliveryDelay());  
werdex86.yahoo.com's picture

Ok, i think that problem is

Ok, i think that problem is that activemq 5.3 ships with esb. I use activemq 5.4 and redelivery property does not exist in activemq 5.3 . I will try to replace it with 5.4
indika's picture

Hi I am very sorry as I do

Hi I am very sorry as I do not have to time for debugging the JMS transport my self. I appreciate your work. You can be a developer of WSO2 and Apache open source projects. Thanks Indika
werdex86.yahoo.com's picture

Thx, Indika! So the problem

Thx, Indika! So the problem is in the following: In ActiveMQ  RedeliveryPolicy is dictated by CONSUMER, not producer. When transaction rollbacks activemq consumer goes to sleep using org.apache.activemq.thread.Scheduler which consist of java.util.TimerTask. So thread at consumer side waits for redelivery timeout. When consumer is closed then timetask is cancelled. When consumer is created again then it tries to retrieve message immediately. Only delivery number survives in message. That is why max delivery works. In org.apache.axis2.transport.jms.ServiceTaskManager(Axis2 class) consumer is created an closed every time when message arrives (see run method). So the general flow is: createConnection(); createConsumer(); receiveMessage(); closeConsumer(); closeConnection(); rescheduleTaskAgain(); I don't why it is implemented this way(connection is created and closed every message), but this is the problem why redelivery delay does not work. Consumer simply is closed and timeout thread is cancelled. One solution was to use activeMQ PooledConnectionFactory. But according to javadoc:  Connections, sessions and producers are returned to a pool after use so that they can be reused later without having to undergo the cost of creating them again. b>NOTE: while this implementation does allow the creation of a collection of active consumers, it does not 'pool' consumers. Pooling makes sense for connections, sessions and producers, which are expensive to create and can remain idle a minimal cost. Consumers, on the other hand, are usually just created at startup and left active, handling incoming messages as they come. When a consumer is complete, it is best to close it rather than return it to a pool for later reuse. So simply there is no way to pool consumers. Only solution which i see is just check delivery number by hand and force thread sleep. So i have two questions: 1) How to access Message in JMS proxy?  Smth like that: ActiveMQMessage message = ...; int delivery=message.getRedeliveryCounter(); 2) Is there smth similar to sleep mediator? If no what is the best way to delay sequence processing? if (delivery>1) { //what to call here? Is there smth better than Thread.sleep? } Thx!
indika's picture

Hi There is a way to enforce

Hi There is a way to enforce caching resources such as JMS session, connection, consumer,etc.  You can use the following parameter (axis.xml - jms transport). <parameter name="transport.jms.CacheLevel">producer</parameter> Please have a look at 'ServiceTaskManager' and 'ServiceTaskManagerFactory'. Thanks Indika  
werdex86.yahoo.com's picture

Hi! Thx again! Caching

Hi! Thx again! Caching consumers solved the problem!!! Here is configuration for JMSListener:  <transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener"> .. <parameter name="myQueueTransactionFactory" locked="false">     <parameter name="java.naming.factory.initial" locked="false">         org.apache.activemq.jndi.ActiveMQInitialContextFactory     </parameter>     <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>     <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>     <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>     <parameter name="transport.jms.SessionTransacted" locked="false">true</parameter>     <parameter name="transport.Transactionality">local</parameter>     `     <parameter name="redeliveryPolicy.redeliveryDelay" locked="true">5000</parameter>     <parameter name="redeliveryPolicy.initialRedeliveryDelay" locked="true">5000</parameter>     <parameter name="redeliveryPolicy.maximumRedeliveries" locked="true">7</parameter>     <parameter name="transport.jms.CacheLevel">consumer</parameter> </parameter> </transportReceiver>   JMS Proxy: <proxy xmlns="http://ws.apache.org/ns/synapse" name="DeliveryJMSService" transports="jms" startOnLoad="true"        trace="enable">     <parameter name="transport.jms.ConnectionFactory">myQueueTransactionFactory</parameter> .... </proxy> P.S Please note that there is no deliveryDelay property as decribed at http://activemq.apache.org/redelivery-policy.html, need to use redeliveryDelay. It's a small bug in doc. For available properties please refer to RedeliveryPolicy class source in activeMQ 5.4.
indika's picture

Nice to here that you got it

Nice to here that you got it worked. This will be a good FAQ entry for the ESB. Thanks Indika
library project main code
Learn Cloud
Learn
Cloud

The WSO2 Application Server is a reliable application server that can host your enterprise web applications. The WSO2 Application Server as a Service is offered in StratosLive, the WSO2 Platform as a Service. This article explains how a simple web application can be developed and deployed from Carbon Studio to the WSO2 Application Server...

Latest Webinar
KeellsSuper is a leading supermarket chain with 50-plus outlets in Sri Lanka, and it offers the only online supermarket in the country. In 2005, JKH implemented SAP ERP across it’s 70 subsidiaries...
Thursday, February 16th 2012, 09.00 AM (PST)

Thursday, February 16th 2012, 10.00 AM (GMT)