Andreas Dolk
Andreas Dolk

Reputation: 114797

How to acknowledge JMS messages with JTA on commit?

I struggeling with JTA, two-phase-commit, JMS- and JDBC-transactions. The idea is (in short) to

  1. receive a message on a queue
  2. perform some database operations
  3. acknowledge the message, when the db operations have been successful

So I got the XAQueueConnectionFactory, create the XAQueueSession, create a receiver from the session and set a message listener.

Inside the listener, in the onMessage method, I begin my user transaction, do the jdbc stuff and commit the transaction or do a rollback, if something went wrong. Now I expected (aka "hoped") that the message would be acknowledged, when the user transaction commits.

But that doesn't happen, the messages are still on the queue and get redelivered again and again.

What am I missing? I double-checked the session and the acknowledge mode really is "SESSION_TRANSACTED" and getTransacted returns true.

I don't have a Java EE container, no spring, no message driven beans. I use the standalone JTA bitronix.

Upvotes: 2

Views: 2062

Answers (3)

smolarek999
smolarek999

Reputation: 519

I think with XA you shoulndn't use transacted session.

Upvotes: 0

michael
michael

Reputation: 9799

You don't really need XA for this. Just following your algorithm: receive the message, perform the DB operations, then acknowledge the message... Literally, that's the solution. (And instead a transacted session, you probably would just choose explicit CLIENT_ACKNOWLEDGE.) If your application should fail while performing the DB operations, don't ack the JMS msg and it will be redelivered. If your app fails after the DB txn and before the ack, then the message will be redelivered -- but you can detected this (redelivered flag will be set to true on the message), and you can decide to reprocess the message or not, based on the state of the database.

Upvotes: 2

Christian
Christian

Reputation: 1

When you say that inside the listener, you begin your user transaction, this seems to hint that you are using Bean Managed Transaction (BMT). Is there a good reason for doing so?

If you used Container Managed Transaction (CMT), what you want would come for free.

As far as I remember, it is not possible with BMT, since the UserTransaction will not participate and will not be able to participate in the transaction created for the message. But you might want to double check with the Java EE spec.

Edit: Sorry, I realized too late that you are not using a Java EE container.

Are you sure that the user transaction that you start inside the listener is part of the transaction started for the message? It seems that you start an independent transaction for the db work.

If you use no container, who provides the JMS implementation, i.e. XAQueueConnectionFactory etc?

Upvotes: 0

Related Questions