aspose file tools*
The moose likes EJB and other Java EE Technologies and the fly likes Container Managed Transactions with an MDB Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » EJB and other Java EE Technologies
Bookmark "Container Managed Transactions with an MDB" Watch "Container Managed Transactions with an MDB" New topic
Author

Container Managed Transactions with an MDB

David Larson
Greenhorn

Joined: Dec 03, 2003
Posts: 9
I'm using an MDB with Container Managed Transactions.
In my MDB, I receive a message from one Queue and send it into another. I need to guarantee that the message is in only one Queue or ther other, so I'm using the XA classes (XAQueueConnectionFactory, XAQueueSession, etc.) to move the message.
This is a basic breakdown of my code:
TransactionManager transactionManager = (TransactionManager)context.lookup("javax.transaction.TransactionManager");
Transaction transaction = transactionManager.getTransaction();
XAResource xaResource = [get XAResource for sending the message into the other Queue];
transaction.enlistResource(xaResource);
.
.
[ send the message into the other Queue ]
.
.
[ if there's a problem, transaction.setRollbackOnly(); ]
.
.
if(transaction.getStatus() == Status.STATUS_MARKED_ROLLBACK)
{
transaction.rollback();
}
else if(transaction.getStatus() == Status.STATUS_ACTIVE)
{
transaction.commit();
}

From my ejb-jar.xml:
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>myMDB</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
In most cases, everything works fine. But if I kill the application server while processing a bunch of messages, sometimes I will lose a message.
Any idea what I'm missing?
Kyle Brown
author
Ranch Hand

Joined: Aug 10, 2001
Posts: 3879
Why are you doing all the transaction management that way? The container will do all of this for you! All you have to do is to make sure you're using an XA JMS provider and declare the MDB to use CMT in the deployment descriptor (as you've done), then put the message in the second queue inside the onMessage() method... If anything happens in placing it on the second queue it will automatically roll back the transaction and add the message back to the first queue.
Kyle


Kyle Brown, Author of Persistence in the Enterprise and Enterprise Java Programming with IBM Websphere, 2nd Edition
See my homepage at http://www.kyle-brown.com/ for other WebSphere information.
David Larson
Greenhorn

Joined: Dec 03, 2003
Posts: 9
The main reason is that I need to be able to retry if the first attempt to move the message fails.
This is the basic logic.
1. onMessage() is called
2. Loop:
a. Move the message into another Queue
b. If step #2 throws an exception, try again (for a max of n attempts)
3. [other processing...]
4. If message was successfully moved, commit everything. Otherwise, rollback
If moving the message fails at first, I have to catch the exception and retry. Catching the exception and retrying means I can't rely on throwing a RuntimeException to rollback the transaction.
Kyle Brown
author
Ranch Hand

Joined: Aug 10, 2001
Posts: 3879
But the container will automatically retry if the first attempt fails. All the containers (and/or their respective underlying JMS transports like WebSphere MQ) will have a "retry count" that tells how many times to attempt to reprocess the message before declaring it unprocessable. For instance, in WAS and WebSphere MQ, this default is 5 times...
Kyle
David Larson
Greenhorn

Joined: Dec 03, 2003
Posts: 9
Yes, you're right. Unfortunately, the requirement is that the MDB retry a message n number of times (and then sleep if unsuccessful). So the MDB must hold the message and retry in a loop within the onMessage() method. If an exception is thrown while moving the message, the MDB must catch the exception and retry (a certain number of times). Catching the exception and retrying means I can't rely on throwing a RuntimeException to rollback the transaction.
Kyle Brown
author
Ranch Hand

Joined: Aug 10, 2001
Posts: 3879
So I'm still not understanding this. Must "N" be a parameter that's set by the application? Is there some problem with setting it at the application server level?
Kyle
David Larson
Greenhorn

Joined: Dec 03, 2003
Posts: 9
"N" is configurable, but it' usually set to 3. So when the MDB receives a message, it will try three times to it into a Queue. If any exceptions occur during those 3 attempts, the MDB must catch them. If it's still unsuccessful after the 3 attempts, it must rollback the transaction and sleep.
Kyle Brown
author
Ranch Hand

Joined: Aug 10, 2001
Posts: 3879
Hold on -- roll back the transaction and sleep -- as in using the sleep() method of Thread? That's prohibited in an EJB -- you can't do that...
I'm still wondering exactly what is creating these requirements -- what's the business reason why this is necessary? These just seem astonishingly arbitrary...
Kyle
David Larson
Greenhorn

Joined: Dec 03, 2003
Posts: 9
A custom Java app is being ported to an MDB. Good catch on the sleep, I missed that.....that changes things.
Thanks for the help.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Container Managed Transactions with an MDB
 
Similar Threads
Message lost or are not pulled by MDB
container-transaction Tag - Who is Responsible?
How to form a MDB with the topic?
transaction in mdb
I get message to queue, but not to MDB Bean. So close yet so far!