-
1. Re: <xa-datasource>
tomjenkinson Sep 29, 2011 6:54 AM (in response to asimoes)Hi André,
Its not entirely clear to me what you are trying to achieve here sorry! Perhaps you want two transactions for the separate database updates?
Tom
-
2. Re: <xa-datasource>
tomjenkinson Sep 29, 2011 7:12 AM (in response to tomjenkinson)It could also be that you need nested transactions, which JBossTS does support but the JTA API doesn't so that could be an option but it would probably require a bit of coding on your part: http://docs.jboss.org/jbosstm/5.0.0.M1/guides/arjunacore-development_guide/ch04.html#d0e1845
For instance you would not be able to do this through UserTransaction
-
3. Re: <xa-datasource>
asimoes Sep 29, 2011 9:40 AM (in response to tomjenkinson)Hi.
I already found the solution, but the problem was:
If I have a two-phases commit transaction, by default, if one of then fail, we got a full rollback.
but how to just rollback the invalid commit?
I managed to control this situation with the following procedure
@Resource private UserTransaction userTransaction; ...... try { userTransaction.begin(); ................. userTransaction.commit(); } catch (Exception e) { try { userTransaction.rollback(); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }
Maybe I forgot to say that I'm making the transaction inside a stateless ejb and calling a second stateless ejb to make the second transaction.
-
4. Re: <xa-datasource>
mazz Sep 29, 2011 10:17 AM (in response to asimoes)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).
-
5. Re: <xa-datasource>
asimoes Sep 29, 2011 10:27 AM (in response to mazz)In 90% of the cases you are right.
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.
I had tried
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
but with no success...
-
6. Re: <xa-datasource>
jhalliday Sep 29, 2011 10:40 AM (in response to asimoes)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.
-
7. Re: <xa-datasource>
marklittle Sep 29, 2011 10:50 AM (in response to asimoes)Look at XTS then, because what you are after is not an ACID transaction.
-
8. Re: <xa-datasource>
asimoes Sep 29, 2011 10:57 AM (in response to jhalliday)Ok, maybe i'm not explaining myself very well.
This is an possible example of an applications what shows what i'm trying to do.
An remote app calls mergeBoth(data) from the remote interface of Bean1.
@Stateless(name = "Bean" mappedName = "a-Bean") public class Bean1 impements Bean{ @EJB(mappedName = Bean2/local") private Bean2 beanDbCritLocal; @EJB(mappedName = Bean3/local") private Bean3 beanDbNotCritLocal; @Override public void mergeBoth(SomeData data){ DataForDB1 data1 = new DataForDB1(); DataForDB2 data2 = new DataForDB2(); data1.setparms(data.getparams()); //different params data2.setparams(data.getparams()); //different params beanDbCritLocal.merge(data1); beanDbNotCritLocal.merge(data2); } }
Example of data:
Db1 are in a private network and have minute log of temperature
Db2 are for public acess and have current temperature.
-
9. Re: <xa-datasource>
adinn Sep 29, 2011 10:58 AM (in response to asimoes)André Simões wrote:
In 90% of the cases you are right.
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 :-)
-
10. Re: <xa-datasource>
tomjenkinson Sep 29, 2011 11:00 AM (in response to asimoes)1 of 1 people found this helpfulI 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?
-
11. Re: <xa-datasource>
asimoes Sep 29, 2011 11:12 AM (in response to tomjenkinson)That's it!
Maybe the 2pc is not what i'm looking for.
I had tryed to use also <local-tx-datasource> but a rollback on db2 continues to causa a rollback on db1.
Remember that the solution that i show in my second post solve my problem.
I'm not a database expert and i just want to commit data to two different db in the fastest way...
-
12. Re: <xa-datasource>
mazz Sep 29, 2011 11:14 AM (in response to asimoes)1 of 1 people found this helpfulOK, 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)
-
13. Re: <xa-datasource>
asimoes Sep 29, 2011 11:17 AM (in response to mazz)This is what i want to do!
I will try again REQUIRES_NEW but with "@TransactionAttribute(TransactionAttributeType.NEVER)" and will give some feedback.
-
14. Re: <xa-datasource>
jhalliday Sep 29, 2011 11:19 AM (in response to mazz)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.