Announcement Announcement Module
No announcement yet.
JMS DefaultMessageListenerContainer and JDBC batch commit in a single Transaction Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • JMS DefaultMessageListenerContainer and JDBC batch commit in a single Transaction


    I have a design question on the spring JMS processing with DefaultMessageListenerContainer.

    I have gone through the forums/internet and could not find any solutions.

    I am using tibco ems queues and spring DefaultMessageListenerContainer to receive messages and I want to commit the message in batches to database and at the same time I want to keep the messages in memory for lookup purposes.
    I am wondering how we can do a batch commit of messages using DefaultMessageListenerContainer.
    As per the spring manuals(correct me if I am wrong) ,everytime the listener method handleMessage() is called by the defaultmessagecontainer, a new JMS transaction is started and the transaction is commited and ended automatically as soon as the listener method returns.
    That effectively indicates that the message passed to the listener method need to be persisted to a persistent device (like database) before the listener method returns.
    If we dont store the message in a persistent device before the listener method returns , there is a chance that the message could be lost if the process crashes before
    committing to db or if the commmit to db itself fails.
    At the same time , I dont want to persist the message in the listener method as single commit to database will be a very expensive operation .
    I wanted to go for a batch commit to db with the gurantee that if the commit to db fails or if the process crashes before I commit I should be able to recover the messages when the process comes up next time.

    I don't want to use XA transactions amd I am ready to handle the duplicate message problem in scenaros where the jdbc commit succeeds but spring JMS transaction fails.

    Any light on this topic will greatly help me.

    Last edited by dhimansu; May 26th, 2011, 09:00 PM.

  • #2
    On the top of my head, I guess you could use the CLIENT_ACKNOWLEDGE mode and override the DefaultMessageListenerContainer's method

    protected void commitIfNecessary(Session session, Message message) throws JMSException
    and call the message.acknowledge() method when you feel you have inserted enough messages in the DB ? I guess you would also have to make sure you are using the CachingConnectionFactory with only one session...

    Maybe Spring integration supports this scenario, but I'm not enough familiar with it to tell.

    Hope this helps...


    • #3
      Hi BeauPral,

      Thanks for the quick reply.

      The spring javadocs says:
      sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
      Does that mean I am going to loose messages if I get exceptions while processing the messages ?
      I have multiple concurrent listeners running on the single queue and for each thread there will be separate session .
      Is it possible to implement the batching strategy using TRANSACTED sessions and calling commit() on the session inside the commitIfNecessary() method instead of a CLIENT_ACKNOWLEDGE ?
      Are these two modes TRANSACTED and CLIENT_ACKNOWLEDGE have the similar functionality (except the distributed transaction scenario) ?
      Also if my batchsize is set to 100 and there are only 90 messages in the queue then after I consume all 90 messages, the commitIfNecessary() method will NOT be called at all; how should I commit those 90 messages without waiting
      for the next 10 messages.

      Please clarify .

      Last edited by dhimansu; May 28th, 2011, 11:43 PM.


      • #4
        I don't consider myselft as a Spring JMS expert, but yes, I think you can use the TRANSACTED mode and call the session.commit() in the commitIfNecessary().

        As for the remaining 90 messages, again from the top of my head I guess you could override the following method...

        protected void noMessageReceived(Object invoker, Session session)