I am bit confused with how exactly MDBs work with Transactions.
suppose we have a simple standalone java message producer which sends a message to a Queue. A MDB's onMessage() picks it up.
Let's say the MDB makes some updates to the database and then invokes a method on a stateless session bean which also updates a database.
By default the transaction attribute of the MDB and stateless session bean would be REQUIRED.
If the stateless session bean database update fails, I presume the MDB's database updates also get rolled back.
But, does the message get rolled back? If not when would the message be rolled back?
Does it make any difference if the MDB is a topic or a queue? Does it make any difference if the message producer is a standalone client or
a stateless session bean with it's own transactional behaviour?
it's not clear what you mentioned by "database updates will rollback, when database update fails". I don't think that data will just be rolled back if there is a update failure unless a system exception or an ApplicationException( with rollback=true) is thrown. I assume that you use CMT as you mentioned about REQUIRED Tx attribute.
It dosen't matter what the message producer is. Once the producer commits the message, it will appear on the queue.
In scenario that you described, as Aryan mentioned, all DB trasactions would be rolled back and the message would be redelivered. This is because global transaction is rolled back when database update fails and hence all the participating transactions rollback.
What you need to watch out is if everything goes fine and call to onMessage() method successfuly completed. Here you have two or more resources involved in this scenario (JMS/DB). At this point cointainer will start to commit transactions on each resource. If we have say two resources viz R1(JMS) and R2(DB), first container will commit resource R1 and then resource R2 (order is not garaunteed). Now if something goes wrong while container is performing commit on resource R2 then it will rollback, but resource R1 is already commited.
If you are using XA drivers for your transactions, only then will container take care of this scenario and gaurantee commit all or none for all the XA resource transactions that are participating containers global transaction.
For more info please read on 2-phase commit and XA transactions.