开发者

Transaction rollbacks, but a record is inserted

开发者 https://www.devze.com 2023-01-30 10:30 出处:网络
Hi all I have done an application configuration using jsf ,spring 3.0,hybernate + JPAand atomikos for XA transcation managementand mysql is my backend,here every thing is working fine however insert o

Hi all I have done an application configuration using jsf ,spring 3.0,hybernate + JPA and atomikos for XA transcation management and mysql is my backend,here every thing is working fine however insert operation, when exception is throwing the transcation should rollback,but it is not happening!! here is a small flow for our application i am using jsfmanagedbean to cal my servive,from my service class my transcation will start

TextileUIBean.java

package com.textile.web; public class TextileUIBean extends BaseManagedBean implements Serializable, { public insertPaymentDetails() { PaymentDetails PaymentDetails=new PaymentDetails(); // values are hard coded ans only two propereties only using PaymentDetails.setCustomerName("Manikandan"); PaymentDetails.setAmount(1000); getTextileManager().insertPaymentDetails(PaymentDetails); } public ITextileManager getTextileManager() { textileManager = (ITextileManager) getBean("textileManager"); return textileManager; } }

   service class


  package com.textile.web
       public interface ITextileManager 
       {
         public void insertPaymentDetails(PaymentDetails PaymentDetails);
       }
        package com.textile.web
        public class TextileManager implements ITextileManager 
            {
            ITextileBusiness  TextileBusiness ;

            public void setTextileBusiness(ITextileBusiness textileBusiness) {
           this.textileBusiness = textileBusiness;
             }
             void insertPaymentDetails(PaymentDetails PaymentDetails)
             {
              TextileBusiness.insertPaymentDetails(PaymentDetails);


             }

        and my business class is 


package com.textile.web

             public interface ITextileBusiness
             {
              public void insertPaymentDetails(PaymentDetails PaymentDetails);
             }

             package com.textile.web
             public class TextileBusiness implements ITextileBusiness 
             {
             ITextileDao  textileDao;

            public void setTextileDao(ITextileDao textileDao) {
           this.textileDao = textileDao;
             }
             void insertPaymentDetails(PaymentDetails ormPaymentTable)
             {

               OrmPaymentTable ormPaymentTable= OrmPaymentTable();
                ormPaymentTable.setCustomerName(PaymentDetails.getCustomerName());
           ormPaymentTable.setAmount(PaymentDetails.getAmount(););
              textileDao.insertPaymentDetails(ormPaymentTable);
                               int a=0;
                if(a==0)
                    throw new BusinessException("Transcation Rollback");            

             }
             }
         and my dao class is 


 package com.textile.web
             public interface IPaymentsDao {
              public void insertPaymentDetails(OrmPaymentTable ormPaymentTable);
              }
               package com.textile.web
               public class PaymentsDao implements IPaymentsDao
               {
               void insertPaymentDetails(OrmPaymentTable ormPaymentTable)
               {
               this.getJpaTemplate().persist(ormPaymentTable);
                  after this line the record is insertinf into table               
               }               
               }


           my FacesConfig.xml is 


   <application>
            <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
            <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>en</supported-locale>
            </locale-config>
            <message-bundle>Messages</message-bundle>
            </application>
            <managed-bean>          <managed-bean-name>textileUIBean</managed-bean-name>                                                    <managed-bean-class>com.textile.web.TextileUIBean</managed-bean-class>
    <managed-bean-scope>view</managed-bean-scope>
</managed-bean>

and my applicationConfig.xml file is

<beans:bean id="dataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean" >
        <beans: property name="jndiName">
            <beans: value>java:comp/env/jdbc/textWeb</beans:value>
        </beans: property> 
        <beans: property name="resourceRef">
            <beans:value>true</beans:value>
        </beans: property>
     </beans: bean>
        <beans: bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
        <beans: property name="entityManagerFactory">
            <beans: ref bean="entityManagerFactory" />
        </beans: property>
    </beans: bean>
    <beans: bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!-- hidden by shiju  because we need one datasource support its  in prsistence.xml !-->
        <beans: property name="dataSource">
            <beans: ref bean="dataSource" />
        </beans: property>
         <beans: property name="persistenceUnitName" value="payhub" />
        <beans: property name="jpaVendorAdapter">
            <beans:bean
                class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <beans: property name="generateDdl" value="false" />
                <beans: property name="showSql" value="true" />
                <beans: property name="databasePlatform" value="${database.target}" />
            </beans: bean>
        </beans: property>
        <beans: property name="persistenceXmlLocation">
            <beans: value>classpath:META-INF/persistence.xml</beans:value>
        </beans: property>
    </beans: bean>
<beans:bean id="textileManager"
        class=" com.textile.web.TextileManager">
        <beans: property name="textileBusiness" ref="textileBusiness" />
    </beans: bean>
    <beans: bean id="textileBusiness" class="com.textile.web.TextileBusiness">
        <beans: property name="textileDao" ref="textileDao" />       
    </beans: bean>
    <beans: bean id="textileDao" class="com.textile.web.textileDao">
        <beans: property name="jpaTemplate">
            <beans: ref bean="jpaTemplate"/>
        </beans: property>
    </beans: bean>

     <aop:config>
            <aop:pointcut id="fooServiceOperation"  expression="execution(* com.textile.web.*.*(..))"/>
             <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
             </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
     <tx:attributes>             
           <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

        <beans: bean id="atomikosTransactionManager"
        class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init"
        destroy-method="close">
        <beans: property name="forceShutdown" value="true" />
        <beans: property name="startupTransactionService" value="true" />
    </beans:bean>

    <beans:bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
        <beans: property name="transactionTimeout">
            <beans: value>3000</beans:value>
        </beans: property>
    </beans:bean>

    <beans: bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <beans: property name="transactionManager">
            <beans: ref bean="atomikosTransactionManager" />
        </beans: property>
        <beans: property name="userTransaction">
            <beans: ref bean="atomikosUserTransaction"/>
        </beans: property>
            <beans: property name="rollbackOnCommitFailure" value="true">
            </beans: property>
    </beans: bean>

 and orm.xml file is 




<entity class="OrmPaymentTable" name="OrmPaymentTable">
<table name="ta_payment" />
<attributes>
<id name="paymentId">
<column name="USER_ID" />
<generated-value strategy="AUTO" />
</id>
<basic name="customerName">
<column name="CUST_NAME" length="50" />
</basic>
<basic name="amount">
<column name="AMOUNT" length="50" />
</basic>
</attributes>
</entity> 

<persistence-unit name="payhub" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider> 
        <jta-data-source>java:comp/env/jdbc/textWeb</jta-data-source>
         <mapping-file>META-INF/orm.xml</mapping-file>
         <class>com.textile.web.OrmPaymentTable</class>
         <properties>
            <property name="hibernate.transaction.manager_lookup_class"
                value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"/>

             <property name="hibernate.transaction.factory_class"
                value="org.hibernate.transaction.JTATransactionFactory" />
 </properties>
    </persistence-unit>
</persistence>

and i configure jndi in meta-inf/context.xml

<Context>
         <Transaction factory="com.atomikos.icatch.jta.UserTransactionFactory"/> 
         <Resource name="jdbc/textWeb" auth="Container"
        driverClassName="com.mysql.jdbc.Driver" user="root" password="root"
        type="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" factory="com.mysql.jdbc.jdbc2.optional.MysqlDataSourceFactory"
        url="jdbc:mysql://localhost:3306/textWeb" explicitUrl="true"
        pinGlobalTxToPhysicalConnection="true">
    </Resource> 
    </Context>

web.xml 

         <resource-ref>
   <description>PaymentsDatabase</description>
   <res-ref-name>jdbc/textWeb</res-ref-name>
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Container</res-auth>
   <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

I trace the log.. see my transcation log details

 78 [main] INFO atomikos - USING core version: 3.6.4
78 [main] INFO atomikos - USING com.atomikos.icatch.console_file_name = tm.out
78 [main] INFO atomikos - USING com.atomikos.icatch.console_file_count = 1
78 [main] INFO at开发者_开发问答omikos - USING com.atomikos.icatch.automatic_resource_registration = true
78 [main] INFO atomikos - USING com.atomikos.icatch.client_demarcation = false
78 [main] INFO atomikos - USING com.atomikos.icatch.threaded_2pc = true
78 [main] INFO atomikos - USING com.atomikos.icatch.serial_jta_transactions = false
78 [main] INFO atomikos - USING com.atomikos.icatch.log_base_dir = .\
94 [main] INFO atomikos - USING com.atomikos.icatch.console_log_level = WARN
94 [main] INFO atomikos - USING com.atomikos.icatch.max_actives = 50
94 [main] INFO atomikos - USING com.atomikos.icatch.checkpoint_interval = 500
94 [main] INFO atomikos - USING com.atomikos.icatch.enable_logging = false
94 [main] INFO atomikos - USING com.atomikos.icatch.output_dir = .\
94 [main] INFO atomikos - USING com.atomikos.icatch.log_base_name = tmlog
94 [main] INFO atomikos - USING com.atomikos.icatch.console_file_limit = 0
94 [main] INFO atomikos - USING com.atomikos.icatch.max_timeout = 300000
94 [main] INFO atomikos - USING com.atomikos.icatch.tm_unique_name = PaymentsTransactions
94 [main] INFO atomikos - USING java.naming.factory.initial = com.sun.jndi.rmi.registry.RegistryContextFactory
94 [main] INFO atomikos - USING java.naming.provider.url = rmi://localhost:1099
94 [main] INFO atomikos - USING com.atomikos.icatch.service = com.atomikos.icatch.standalone.UserTransactionServiceFactory
94 [main] INFO atomikos - USING com.atomikos.icatch.force_shutdown_on_vm_exit = false
94 [main] INFO atomikos - USING com.atomikos.icatch.default_jta_timeout = 10000
INFO - JtaTransactionManager.checkUserTransactionAndTransactionManager(469) | Using JTA UserTransaction: com.atomikos.icatch.jta.UserTransactionImp@16a6027
INFO - JtaTransactionManager.checkUserTransactionAndTransactionManager(480) | Using JTA TransactionManager: com.atomikos.icatch.jta.UserTransactionManager@e68513
DEBUG - NameMatchTransactionAttributeSource.addTransactionalMethod(94) | Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT]
DEBUG - AbstractPlatformTransactionManager.getTransaction(365) | Creating new transaction with name [com.evolvus.payments.manager.IPaymentsManager.findColumnChartDisplayByGateWays]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
40500 [http-8080-Processor24] WARN atomikos - Attempt to create a transaction with a timeout that exceeds com.atomikos.icatch.max_timeout - truncating to: 300000
40641 [http-8080-Processor24] INFO atomikos - THREADS: using JDK thread pooling...
40703 [http-8080-Processor24] INFO atomikos - createCompositeTransaction ( 3000000 ): created new ROOT transaction with id PaymentsTransactions0000100688
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
DEBUG - AbstractPlatformTransactionManager.processRollback(850) | Participating transaction failed - marking existing transaction as rollback-only
DEBUG - JtaTransactionManager.doSetRollbackOnly(1060) | Setting JTA transaction rollback-only
49110 [http-8080-Processor24] INFO atomikos - setRollbackOnly() called for transaction PaymentsTransactions0000100688
DEBUG - AbstractPlatformTransactionManager.processRollback(843) | Initiating transaction rollback
49172 [http-8080-Processor24] INFO atomikos - afterCompletion ( STATUS_ROLLEDBACK ) called  on Synchronization: org.hibernate.transaction.CacheSynchronization
49172 [http-8080-Processor24] INFO atomikos - afterCompletion ( STATUS_ROLLEDBACK ) called  on Synchronization: org.hibernate.ejb.EntityManagerImpl$1@1f6e48a
49172 [http-8080-Processor24] INFO atomikos - rollback() done of transaction PaymentsTransactions0000100688

could you help me ?


Clearly your database insert is not happening within the scope of your transaction manager's current transaction.

A few ideas:

1) Maybe its just not in your posting, but I don't see the Spring @Transactional annotation on your service class. What is your strategy for controlling transaction boundaries?

2) Because you are using JNDI, we don't get to see your data source, but if you are using Atomikos, you should be using their XA aware pooling data source. Are you?

3) You should increase Atomikos normal logging to DEBUG to see exactly which SQL commands it is handling.

4) Atomikos keeps transaction logs that are outside your normal log files. These are used for recover and other purposes. You should also check these for clues.

Hope this helps.

Update:

MySQL has some limitations with XA transactions as you can here about here. Try this configuration out within your context.xml and at least see if it works. It uses an XA aware (but not XA capable) data source from Atomikos. If this works then you can go from there:

<Transaction factory="com.atomikos.icatch.jta.UserTransactionFactory" />

and the define the JNDI data source for injection into your entity manager:

<Resource name="jdbc/myDataSource" auth="Container"
factory="org.apache.naming.factory.BeanFactory"
type="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean"
uniqueResourceName="myMySqlDatabase" driverClassName="com.mysql.jdbc.Driver" url="......" user="....." password="...." maxPoolSize="20" reapTimeout="300" />

0

精彩评论

暂无评论...
验证码 换一张
取 消