"felipeal" wrote :
| Forgive my ignorance (on the JBoss internals - I'm not really thaaat stupid when
it comes to Java EE/XA/JTA,etc... :-), but how to achieve 2PC commit then? I mean, suppose
I'm using a XADatasource for both my app's DB and my JBossMQ DB, add 100 messages
in the queue, try to update the DB, get an exception and set the transaction for rollback.
According to the 2PC/DTP land, the JBossMQ transaction should rollback as well. Of course,
what must be rolled back is the transaction of the JBossMQ resource, not necessary its
underlying database. But if the resource suspended my global-tx and started a new local-tx
one, once I finished posting the 100 messages, that new tx would be committed (and ready
to be consumed), right? Or am I missing something (I hope so...)?
|
Ok, so in a nutshell this is what happens when use a JBoss Messaging (you meant JBoss
Messaging not JBoss MQ, right?) XAConnection in a global tx.
Let's say you are in an ejb method and either using a UserTransaction directly or
letting the ejb container demarcate transaction boundaries for that method.
You are using the JBoss JCA resource adaptor
(
http://wiki.jboss.org/wiki/Wiki.jsp?page=JBossJMSRA) to send JMS messages, and you are
using an JCA XA datasource (this one *does* need to do be XA since you are using the XA
capabilities of your database - make sure your db does have XA capabilities! Some
don't) for your direct data access, and you are using a local tx datasource for the
datasource used by JBM for its internal data access.
Either way, the application server (the JCA layer) will have managed to get two
XAResources: XAResource1 obtained from XASession.getXAResource() which is an XAResource
for your JMS session, and XAResource2 which is an XAResource obtained from the database
you're doing direct access with.
A global tx will be started for the UserTransaction and the app server will enlist the two
XAResources in the global tx. (Assuming you're using UT)
You then send a message (using XAResource1) and insert a row in your db (using
XAResource2)
You then commit the UT. (Or let the app server do it for you)
(I'm going to simplify the following a little, but the basics are correct - I
don't want to go through the logging the transaction manager will do (if you are using
JBoss TS) - since it's not relevant to the question.)
The transaction manager calls "prepare" on XAResource1. This tells the
XAResource that it must log the work done in the tx, so it can be recovered in case of
failure after the prepare.
Currently JBM uses the database to log at the prepare stage - so we write the message into
the database with state "prepared" - this is done with a single JDBC transaction
(if there were more than one messages sent in the same tx - they would all be written in
the same JDBC tx). XAResource1 returns "OK"
(Eventually we will log using JBoss TS - but that is a different story).
The app server then calls prepare on XAResource2 - what happens now depends on the
implementation of your database. But assuming it supports XA properly, then *somehow* it
will write and sync *something* to disc that enables it to redo the operation at a later
state. XAResource2 returns "OK"
Since both resources have returned OK, the app server will go to the commit phase.
First it calls "commit" on XAResource1. JBM already has the data for the message
send in the database, so we just update it's status to "committed". This
happens in a single JDBC transaction - note we do not need an XA capable database to do
this - it's a straightforward non XA database update.
Next, "commit" is called onn XAResource2. The database doesn't something
internal to its implementation that results in the data ending up in the committed state.
So as you can see there is no need for JBM to need an XA capable database in order to
provide a fully functioning XAResource.
This is by design:
a) We can't assume the user has an XA capable database
b) Eventually we can't assume they have a database at all (think file based persistent
stores)
c) We don't want to rely on the (often ropy) xa implementation of another product over
which we have no control to provide such a critical feature.
"felipeal" wrote :
| That's what I did initially, and I thought JBoss would (by default) manage to
enroll the 2 local transactions (DB and JMS) in a global/XA transaction. But once I
deployed the application, the MDBs started to consume the messages before the global tx
committed, so I realized something was not set correctly...
|
It definitely should work. If it doesn't please file a bug report.
"felipeal" wrote :
| Thanks again for you help (and patience :-)
|
No problem
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3968008#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...