1
votes

I am designing JMS application which receives the message from queue and updates the column in the database. I am using tomcat and message listener for listening of the messages (no MDB and no Spring MDP'S). I wanted the best possible, robust design in case exception handling and transaction so that messages are not lost.

Should i use jms session transaction mode and also jdbc transaction. Or just the jdbc transaction is sufficient (without jms session commit or rollback) as this is an database table update.

Thanks

1

1 Answers

1
votes

A JDBC transaction is not enough: If you have read a message, and the database operation fails, and tomcat is shutdown, the message is lost.


If each message triggers an insert/update in a database, you could use CLIENT_ACKNOWLEDGE mode:

    final boolean transacted = false;
    final int ackMode = Session.CLIENT_ACKNOWLEDGE;
    final QueueSession queueSession = queueConnection.createQueueSession(
            transacted, ackMode);

So you can read the message, and update the database. If the database update was successful, you can acknowledge the message using

    message.acknowledge();

Without acknowledge, the message will be redelivered: So after restarting tomcat, your message listener should see the message again. You can use queueSession.recover() to restart delivery programatically.

Since it is possible that tomcat is shutdown right between a successful DB update and the acknowledge, you should make sure to handle duplicate messages correctly.


A variation is to use a transacted session:

    final boolean transacted = true;
    // 2nd parameter is ignored if the session is transacted
    final QueueSession queueSession = queueConnection.createQueueSession(
            transacted, -1);

In this mode you can acknowledge multiple messages using a single commit:

        queueSession.commit();

You need this mode, if multiple messages result in a single database operation (you have to collect some messages, before you can update the database).