JTA UserTransaction for Multiple DS have a issue when rollback
jf321023 Mar 12, 2012 7:02 AMHi,
I am trying using JTA transaction support for multiple datasource. But i failed in my application which build with Weld + Jsf2 +Jboss as 7.1.0.Final .
The issue is that when i insert data into the two different database in my one method. when one of them failed , the transation will rollback and the other one insert method will rollback ,too. But it isn't!
So i just use the JDBC and UserTransaction . But it failed,too.
@Named("jeejtatest") @RequestScoped public class JEE_JTA_Test { private static String url1 = "jdbc:mysql://localhost:3306/jweb"; private static String url2 = "jdbc:mysql://localhost:3306/mytest"; private static String username1 = "root"; private static String username2 = "root"; private static String password1 = "11111"; private static String password2 = "11111"; private static String testSql1 = "insert into test values('11')"; private static String testSql2 = "insert into test values('11')"; @Inject private UserTransaction transaction; public void test1() throws NamingException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException { Connection mysqlCn = null; Connection mysqlCn2 = null; MysqlXADataSource mysqlDs = null; MysqlXADataSource mysqlDs2 = null; XAConnection xamysqlCn = null; XAConnection xamysqlCn2 = null; Statement mysqlpst = null; Statement mysqlpst2 = null; try { // UserTransaction begin. transaction.begin(); // Get Xa-DataSource mysqlDs = new MysqlXADataSource(); mysqlDs.setURL(url1); mysqlDs2 = new MysqlXADataSource(); mysqlDs2.setURL(url2); // Get Xa-Connection xamysqlCn = mysqlDs.getXAConnection(username1, password1); System.out.println("xamysqlCn: " + xamysqlCn); xamysqlCn2 = mysqlDs2.getXAConnection(username2, password2); System.out.println("xamysqlCn2: " + xamysqlCn2); // Get Jdbc Connection mysqlCn = xamysqlCn.getConnection(); mysqlCn2 = xamysqlCn2.getConnection(); mysqlpst = mysqlCn.createStatement(); mysqlpst2 = mysqlCn2.createStatement(); // Insert into database , I make the seconed mothed has data clash. // And The exception will be throwed here. I think here the UserTransaction finished the first commit for JTA. mysqlpst.executeUpdate(testSql1); mysqlpst2.executeUpdate(testSql2); // Transaction commit . transaction.commit(); } catch (SQLException ex) { Logger.getLogger(JEE_JTA_Test.class.getName()).log(Level.SEVERE, null, ex); System.out.println(transaction.getStatus()); transaction.setRollbackOnly(); transaction.rollback(); } finally { try { // close mysqlpst.close(); mysqlCn.close(); xamysqlCn.close(); mysqlpst2.close(); mysqlCn2.close(); xamysqlCn2.close(); } catch (SQLException ex) { } } } }
-------------------------------------------------------------------------------- The uper test has failed --------------------------------------------------------------------------------------------------
--------------------------------------------- So I try use the XASource and Xid to implement the JTA twice commit by myself -------------------------------------------------
private static String url1 = "jdbc:mysql://localhost:3306/jweb"; private static String url2 = "jdbc:mysql://localhost:3306/mytest"; private static String username1 = "root"; private static String username2 = "root"; private static String password1 = "11111"; private static String password2 = "11111"; private static String testSql1 = "insert into test values('11')"; private static String testSql2 = "insert into test values('11')"; class MyXid implements Xid { int formatId; byte globalTransactionId[]; byte branchQualifier[]; public MyXid() { } public MyXid(int formatId, byte[] globalTransactionId, byte[] branchQualifier) { this.formatId = formatId; this.globalTransactionId = globalTransactionId; this.branchQualifier = branchQualifier; } public int getFormatId() { return this.formatId; } public void setFormatId(int formatId) { this.formatId = formatId; } public byte[] getGlobalTransactionId() { return this.globalTransactionId; } public void setGlobalTransactionId(byte[] globalTransactionId) { this.globalTransactionId = globalTransactionId; } public byte[] getBranchQualifier() { return this.branchQualifier; } public void setBranchQualifier(byte[] branchQualifier) { this.branchQualifier = branchQualifier; } } public void test1() { Connection mysqlCn = null; Connection mysqlCn2 = null; MysqlXADataSource mysqlDs = null; MysqlXADataSource mysqlDs2 = null; XAConnection xamysqlCn = null; XAConnection xamysqlCn2 = null; XAResource xamysqlRes = null; XAResource xamysqlRes2 = null; Xid mysqlXid = null; Xid mysqlXid2 = null; Statement mysqlpst = null; Statement mysqlpst2 = null; try { mysqlDs = new MysqlXADataSource(); mysqlDs.setURL(url1); mysqlDs2 = new MysqlXADataSource(); mysqlDs2.setURL(url2); xamysqlCn = mysqlDs.getXAConnection(username1, password1); System.out.println("xamysqlCn: " + xamysqlCn); xamysqlCn2 = mysqlDs2.getXAConnection(username2, password2); System.out.println("xamysqlCn2: " + xamysqlCn2); mysqlCn = xamysqlCn.getConnection(); mysqlCn2 = xamysqlCn2.getConnection(); mysqlpst = mysqlCn.createStatement(); mysqlpst2 = mysqlCn2.createStatement(); xamysqlRes = xamysqlCn.getXAResource(); xamysqlRes2 = xamysqlCn2.getXAResource(); mysqlXid = new MyXid(0, new byte[] { 0x01 }, new byte[] { 0x02 }); mysqlXid2 = new MyXid(0, new byte[] { 0x01 }, new byte[] { 0x04 }); // JTA transaction first commit . If commit failed, the transaction will rollback. xamysqlRes.start(mysqlXid, XAResource.TMNOFLAGS); xamysqlRes2.start(mysqlXid2, XAResource.TMNOFLAGS); mysqlpst.executeUpdate(testSql1); mysqlpst2.executeUpdate(testSql2); xamysqlRes.end(mysqlXid, XAResource.TMSUCCESS); xamysqlRes2.end(mysqlXid2, XAResource.TMSUCCESS); // Get the status of the database , if Ok, lock the database. int mysqlRea = xamysqlRes.prepare(mysqlXid); int mysqlRea2 = xamysqlRes2.prepare(mysqlXid2); // JTA transaction second commit if (mysqlRea == xamysqlRes.XA_OK && mysqlRea2 == xamysqlRes.XA_OK) { xamysqlRes.commit(mysqlXid, false); System.out.println("Mysql 事务提交成功!"); xamysqlRes2.commit(mysqlXid2, false); System.out.println("Mysql2 事务提交成功!"); } else { xamysqlRes.rollback(mysqlXid); xamysqlRes2.rollback(mysqlXid2); } } catch (SQLException ex) { } catch (XAException ex) { Logger.getLogger(Mutil_DataSource_Test.class.getName()).log( Level.SEVERE, null, ex); } finally { try { // 关闭 mysqlpst.close(); mysqlCn.close(); xamysqlCn.close(); mysqlpst2.close(); mysqlCn2.close(); xamysqlCn2.close(); } catch (SQLException ex) { } } }
----------------------------------------------------------------- The second test is success ---------------------------------------------------------------
But as i know , The JTA Transaction has implemented the Xid and XASource in JEE which is the UserTransaction. But why the first test failed , and the second is OK. I also tryed with JPA , but also has the issue.
Is there a bug in weld and JTA or some misstakes i has?
Who has a success try with the multiple datasource with JTA UserTransaction ? Please give me some suggestions or give me a successful project as better. Think you very much. My e-mail is for1988@126.com