6 Replies Latest reply on Jun 28, 2010 7:17 PM by obfuscator

    XA Transaction & Two phase commit

    qwerty2

      Hello !


      I have two datasources MySql 5.1 and Postgres 8.0  and I'm trying to implement a standard bank example with XA Transaction and 2 phase commit. Unfortunately, I have a problem that I can't resolve.
      Please help me !


      This is my configurations:


      persistance.xml


      <persistence-unit name="mybank">
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <jta-data-source>java:/mysqlXADatasource</jta-data-source>
            <properties>
               <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
               <property name="hibernate.hbm2ddl.auto" value="update"/>
               <property name="hibernate.show_sql" value="true"/>
               <property name="hibernate.format_sql" value="true"/>
               <property name="jboss.entity.manager.factory.jndi.name" value="java:/mybankEntityManagerFactory"/>
            </properties>
         </persistence-unit>
         <persistence-unit name="pgbank">
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <jta-data-source>java:/pgbankDatasource</jta-data-source>
            <properties>
               <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
               <property name="hibernate.hbm2ddl.auto" value="update"/>
               <property name="hibernate.show_sql" value="true"/>
               <property name="hibernate.format_sql" value="true"/>
               <property name="jboss.entity.manager.factory.jndi.name" value="java:/pgbankEntityManagerFactory"/>         
            </properties>
         </persistence-unit>



      seamxa-ds.xml



      <datasources>
         
         <xa-datasource>
              <jndi-name>mysqlXADatasource</jndi-name>
              
              <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
              <xa-datasource-property name="ServerName">localhost</xa-datasource-property>
                  <xa-datasource-property name="PortNumber">3306</xa-datasource-property>
              
                  <xa-datasource-property name="DatabaseName">mybank</xa-datasource-property>
                  <xa-datasource-property name="User">root</xa-datasource-property>
                  <xa-datasource-property name="Password">mysql</xa-datasource-property>
                  
                  <track-connection-by-tx></track-connection-by-tx>
             
          </xa-datasource>
          <xa-datasource>
                   <jndi-name>pgbankDatasource</jndi-name>
              
                   <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
                   <xa-datasource-property name="ServerName">localhost</xa-datasource-property>
                   <xa-datasource-property name="PortNumber">5432</xa-datasource-property>
              
                   <xa-datasource-property name="DatabaseName">pgbank</xa-datasource-property>
                   <xa-datasource-property name="User">postgres</xa-datasource-property>
                   <xa-datasource-property name="Password">postgres</xa-datasource-property>
              
                   <track-connection-by-tx></track-connection-by-tx>
          </xa-datasource>
      </datasources>



      components.xml



       <core:init debug="@debug@" jndi-pattern="@jndiPattern@"/>
           
         <core:manager concurrent-request-timeout="500" 
                       conversation-timeout="120000" 
                       conversation-id-parameter="cid"
                       parent-conversation-id-parameter="pid"/>
          
         <persistence:managed-persistence-context name="entityManager"
                                           auto-create="true"
                            persistence-unit-jndi-name="java:/seamxaEntityManagerFactory"/>                          
      
         <drools:rule-base name="securityRules">
            <drools:rule-files>
               <value>/security.drl</value>
            </drools:rule-files>
         </drools:rule-base>
      
         <security:rule-based-permission-resolver security-rules="#{securityRules}"/> 
         
         <security:identity authenticate-method="#{authenticator.authenticate}" remember-me="true"/>
         
         <event type="org.jboss.seam.security.notLoggedIn">
            <action execute="#{redirect.captureCurrentView}"/>
         </event>
         <event type="org.jboss.seam.security.loginSuccessful">
            <action execute="#{redirect.returnToCapturedView}"/>
         </event>
         
         <mail:mail-session host="localhost" port="2525" username="test" password="test" />



      Test.java



      @Stateless
      @Name("testy")
      @Transactional
      public class Test implements TestI {
      
              @PersistenceContext(unitName="pgbank") 
              private EntityManager entityManager;
              
              @PersistenceContext(unitName="mybank") 
              private EntityManager em;
              
              @Transactional(TransactionPropagationType.REQUIRED)
              public void start() {
                      int error = 0;
                      em.createQuery("update Account a set balance = 33000 where id = 1").executeUpdate();
                      if (error != 0)
                       throw new EJBException("ERROR !!");
                      entityManager.createQuery("update Account a set balance = 33000 where id = 1").executeUpdate();
              }
      }



      JBoss 4.2.3 Log



      13:21:46,625 INFO  [STDOUT] Hibernate: 
          update
              account 
          set
              balance=33000 
          where
              id=1
      13:21:46,656 INFO  [STDOUT] Hibernate: 
          update
              account 
          set
              balance=33000 
          where
              id=1
      13:21:46,781 WARN  [loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] XAResourceRecord.prepare - prepare failed with exception XAException.XAER_RMERR
      13:21:46,781 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_50] - Prepare phase of action a01040f:1162:49ec5a80:37 received heuristic decision: TwoPhaseOutcome.HEURISTIC_HAZARD
      13:21:46,781 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_36] - BasicAction.End() - prepare phase of action-id a01040f:1162:49ec5a80:37 failed.
      13:21:46,781 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_37] - Received heuristic: TwoPhaseOutcome.HEURISTIC_HAZARD .
      13:21:46,781 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_38] - Action Aborting
      13:21:46,812 WARN  [SeamPhaseListener] uncaught exception, passing to exception handler
      java.lang.IllegalStateException: Could not commit transaction
           at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:626)
           at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:605)
           at org.jboss.seam.jsf.SeamPhaseListener.handleTransactionsAfterPhase(SeamPhaseListener.java:343)
           at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:243)
           at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:194)
           at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)
           at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)
           at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
           at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
           at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
           at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
           at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:38)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:150)
           at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
           at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:379)
           at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:506)
           at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:44)
           at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
           at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
           at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
           at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
           at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
           at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
           at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
           at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
           at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
           at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
           at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
           at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
           at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
           at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
           at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
           at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
           at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
           at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
           at java.lang.Thread.run(Unknown Source)
      Caused by: javax.transaction.HeuristicMixedException
           at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1397)
           at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
           at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
           at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:140)
           at org.jboss.seam.transaction.UTTransaction.commit(UTTransaction.java:52)
           at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:614)
           ... 49 more





      What's wrong with my code ?


        • 1. Re: XA Transaction & Two phase commit
          javacoryd

          By the looks of it you want to control your own transactions so you need to put this in your components.xml:


          <core:init transaction-management-enabled="false"/>

          <transaction:no-transaction />


          Cory.

          • 2. Re: XA Transaction & Two phase commit
            swd847

            Postgres 8.0 does not support two phase commit, you need 8.1 or better. I would say that is the root cause of your problem.

            • 3. Re: XA Transaction & Two phase commit
              qwerty2

              Oh yes you were right Stuart now everything is working fine ... Thank you !


              But I have another question ...


              Like I understand in my implementation the transaction menager was an application server (JBoss) and he perform all the work associated with two phase commit.


              And how can I define my own transaction menager (is it possible ?) to control the transaction status step by step ? I can't find any source code example with seam and ejb3, I find only theories how does 2PC work :(


              How to do implementation ... ? Each tip will be a valuable.



              Paweł.

              • 4. Re: XA Transaction & Two phase commit
                swd847

                If you have two or more underlying transactional resources that do not support TPC then there is nothing you can do. If you only have 1 transactional resource it can still participate in two phase commit by commiting the 1st phase in all resources that support TPC, commiting the resource that does not support TPC and then commiting the second phase for the TPC resources. Anunta should support this out of the box, I am sure I have seen a wiki page on jboss.org with how to do this.

                • 5. Re: XA Transaction & Two phase commit
                  sczerwinski

                  I use PostgreSQL 8.4 and I had the same problem. It looks like max_prepared_transactions parameter is not set in postgresql.conf by default, so there are no XA transactions available. When I set this value to 5, it just works correctly.


                  According to this page, max_prepared_transactions should be twice as much as max-pool-size of the xa-datasource.

                  • 6. Re: XA Transaction & Two phase commit
                    obfuscator

                    Thanks for this one. As a side note, the default max-pool-size of JBoss is 20 (according to configdatasources), so a reasonable size would be 40. Don't try too high, since PostgreSQL allocates shared memory segments for the connections as per the comments in postgresql.conf, and it runs out of this mem quite quickly.


                    The error you get from arjuna if you don't increase this value above 0 is the same if you try to use multiple 1-phase resources:


                    23:54:02,180 WARN  [loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] XAResourceRecord.prepare - prepare failed with exception XAException.XAER_RMERR
                    23:54:02,182 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_50] - Prepare phase of action 7f000101:db31:4c29198f:152 received heuristic decision: TwoPhaseOutcome.HEURISTIC_HAZARD
                    23:54:02,182 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_36] - BasicAction.End() - prepare phase of action-id 7f000101:db31:4c29198f:152 failed.
                    23:54:02,182 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_37] - Received heuristic: TwoPhaseOutcome.HEURISTIC_HAZARD .
                    23:54:02,182 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_38] - Action Aborting