Results 1 to 4 of 4

Thread: JmsTemplate and Acknowledge

  1. #1
    Join Date
    Oct 2004
    Posts
    5

    Default JmsTemplate and Acknowledge

    Hey Spring Team first just want to say Spring really ROCKS!
    I am working on it with my first project and it really makes wiring up an application & testing easy...

    But now a question (potential enhancement) for JmsTemplate.
    Scenario:
    I have an application that uses JMS to manage a message as it is processed by various agents. An agent within the application needs to read a message off Q1, do some processing, write the message to Q2, then acknowledge the message from Q1.

    While I know that the resources for the JMS session are locked until the ack is sent (and the time here is dependent on the processing we do) this application needs to make sure that messages are not lost as they move from one Q to another. If the system were to have any issues/crash during processing we would lose the message since it was not on any of the Qs.

    JmsTemplate:
    I started looking at using Spring's JmsTemplate to handle our JMS needs. I noticed however that this class does not provide any public methods to acknowledge (or commit/rollback) a message even though the user of the class can call setSessionTransacted or setSessionAcknowledgeMode.

    When I looked at the source code for JmsTemplate I noticed that the variable used by setSessionAcknowledgeMode (sessionAcknowledgeMode) is not used to determine when or if to call the Message.acknowledge method. Instead the doReceive method of JmsTemplate calls the Message.acknowledge after a successful consumer.receive() call.

    In our scenario above the message would be acknowledged off Q1 before being processed or written to Q2 (even when setting CLIENT_ACKNOWLEDGE) and would leave the potential of losing the message in our given scenario.

    I think that this topic in the Spring forums started to address this problem, seems that sessionAcknowledgeMode was going to be checked and the call to Message.acknowledge() was going to be called when set to CLIENT_ACKNOWLEDGE to bypass a problem calling acknowledge when setting mode to AUTO_ACKNOWLEDGE in WebSphereMQ.
    http://forum.springframework.org/vie...ht=acknowledge

    However I think that if sessionAcknowledgeMode is set to CLIENT_ACKNOWLEDGE then the JmsTemplate should not call message.acknowledge at all but provide the capability of the user of JmsTemplate to call a public method that does this.

    What do you think?

    Thanks,
    Mike

  2. #2
    Join Date
    Oct 2005
    Posts
    1

    Default

    I have a similar scenario and would like to find a solution in Spring. How can I make it work with current Spring JMS support? Or I have to go back to traditional JMS.

    Thanks,
    Missy

  3. #3
    Join Date
    Aug 2004
    Location
    London
    Posts
    164

    Default consuming and publishing with Spring

    I'd recommend you use Jencks with Spring

    http://jencks.org/

    You can then setup Jencks to do the inbound message consumption for you...

    http://jencks.org/Message+Driven+POJOs

    which has the added benefit of performing connection, session & thread pooling, handling concurrent processing and exception handling and it can work with regular JMS transactions or with full XA if you need it.

    Then use the outbound pooling of Jencks...
    http://jencks.org/Outbound+JMS

    along with, if you wish, the JmsTemplate helper class. Then you can get inbound & outbound messaging all in a single JMS transaction done for you declaratively - or you can move to full XA if you need it (e.g. if you are using 2 different JMS providers or you want to include some JDBC operations in the XA).
    James Strachan
    ------------------
    Open Source Integration
    Iona

  4. #4
    Join Date
    Nov 2005
    Location
    Sydney, Australia
    Posts
    1

    Default use JmsTransactionManager

    Hi,

    I had a similar problem, but figured out that jmsTemplate.receive() was opening and closing the session for me.

    once the session is closed, you can't message.acknowledge(), it's too late.

    you have 2 options:
    • write your own SessionCallback implementation (look in jmsTemplate for examples) and insert your code and your msg.acknowledge() before returning from your SessionCallback.doInJms() implementation
    • use JmsTransactionManager


      Code:
      <!-- for a queueConnectionFactory with jms 1.0 -->
      <bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager102">
      		<property name="connectionFactory">
      			<ref bean="jmsQueueConnectionFactory"/>
      		</property>
      		<property name="pubSubDomain">
      			<value>false</value>
      		</property>
      	</bean>

      Code:
      JmsTransactionManager transactionManager = (JmsTransactionManager ) appContext.getBean("jmsTransactionManager");
      
      TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        Message msg = jmsTemplate.receive(queueName);
        if (msg != null) {
          // do stuff...
          msg.acknowledge(); //session is still open within the transaction
        }
      transactionManager.commit(status);


    Personnaly I prefer the transactionManager approach

    cheers,

    Patrick

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •