1 2 Previous Next 24 Replies Latest reply on Mar 12, 2012 12:38 PM by Feng Jiang

    JTA UserTransaction for Multiple DS have a issue when rollback

    Feng Jiang Newbie

      Hi,

       

           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

        1 2 Previous Next