Why would you want to do that? If you are using 2PC, and you have multiple resources registered in a transaction and one fails, by definition you want them all to rollback right? The whole purpose of this XA/2PC stuff is to NOT have it rollback one but commit another I thought. That would put it in a bad state.

If you really want them to be isolated from each other, just put them in different transactions. From a stateless session bean, the typical way to do this kind of thing is to utilize the REQUIRES_NEW transaction flag (perhaps in conjunction with NEVER).

When you have a 2PC you MUST allow the db2 failure to rollback the db1 update. That's the A in ACID. But it seems you're not trying to build a 2PC transaction, you're trying to use a 2PC transaction manager to build an extended transaction. That's hard, because they are not intended to do that. Arguably they're intended explicitly NOT to do it. Any solution you build is going to have to deal with one of two corner cases: you've already committed the critical db1 update and then the non-critical db2 updates fails. How do you detect this and use the data in db1 to update db2 to bring them back into sync at a later time, or allow your system to continue to tolerate the inconsistency indefinitely? Or, you've already updated db2 and then the critical db1 update fails. How do you detect this and remove the entry in db2? Now make your solution work even if the system crashes at the worst possible moment. Still think you've found a solution? I bet it involves writing a lot of custom business logic for data reconciliation or tolerating inconsistent data.

But imagine yo have two database sources, one with critical data (db1), and all of the redundance and security involved, and another (db2) for statistics and other data not so critical.

When you do a two phasis commit, you can not allow that db2 failure causa a db1 failure to commit.

No,in 100% of cases he is right.

If you are willing to allow the data in db2 to be out of synch with the data in db1 (i.e.roll forward db1 but roll back db2) then there is no reason to run them in the same transaction. Make all your changes to db1 and commit them then make all the changes to db2 and commit them.

If it is important that the two databases remain in synch then you either want them both to be updated or both to fail otherwise they will contain inconsistent information. That's what a common transactionand 2 phase commit gives you,either all changes are amdero none. In this case making the claim that the data in db1 is critical and the data in db2 is not is an inconsistent position. Either you have your cake or you eat it but not both.

If you cannot see why this is so then you need to go back to basics and read a good book on transactions (I suggest you try the one written by Mark Little :-)

I may be wrong, but it sounds a little bit like you are saying the data in DB2 is non critical and it doesn't matter to you whether or not (in your example) data2 is persisted? In which case, maybe you don't want to use XA for DB2?

OK, here is how you do it correctly (note: I am assuming I understand you as saying you explicitly will allow db2 to fail and not affect the commit of db1).

Just annotate "mergeBoth" with "@TransactionAttribute(TransactionAttributeType.NEVER)"

Thus, when mergeBoth is called, there is no transaction created yet.

Now, your Bean2 and Bean3 merge methods must be annotated with REQUIRES_NEW.

And Ta-DA! You got what you want. I do this kind of thing all the time. Now what happens is, if that first call to db1 fails, you don't do db2 (which again is what I assume you want). That's because the exception bubbles out and you never even do the db2 call. If the first call to db1 succeeds, it doesn't matter what db2 does, that REQUIRES_NEW method has ended, the transaction has been committed, and it is done.

This is what I meant earlier when I said you probably want to use REQUIRES_NEW in conjunction with NEVER. In this case, you never even ENLIST 2PC here! Which makes it, presumably, faster too, since you never have to worry about all the additional phases (since you are only ever enlisting a single resource at any one time here)

That's a seductively simple solution, but actually only correct if the business requirements allow for it. If the update of the non critical db fails, the implications and necessary compensation steps are business case specific. If it can be allowed to remain out of sync with db1 indefinitely, then the simple solution is adequate. If not, you need to consider how it's going to be resynced, as you don't have an automatic tx recovery system to help you with that.