Hi Faizal, Philippe, Rohini and Alexandre, I've investigated about the following trace: Cannot enlist XAResource: javax.transaction.SystemException: Cannot send XA start: javax.transaction.xa.XAException: mixed transactions Unexpected Exception on commit_one_phase: java.rmi.RemoteException: XAException: javax.transaction.xa.XAException: Cannot mix transactions To make thing clearer, I created some small example. (The source and deployment descriptor are attached to this mail.) This example consists of: jun12x.test.jonas.TxClient jun12x.test.jonas.TxCallerSessionBean jun12x.test.jonas.TxCalledSessionBean and the required interfaces. The transaction is managed by the container and the transaction attributes for all the methods are 'Required'. The methods are invoked in the following order: Client --> Caller(Bean) --> Called(Bean) After the beans are activated in JOnAS, run the client program. It invokes the two methods on the bean according to the option. 1. java jun12x.test.jonas.TxClient -a <para_1> <para_2> This invokes insertOnSessionAfterClosed(String, String) on TxCallerSession, which invokes TxCalledSession.insert(String) after Connection.close(). 2. java jun12x.test.jonas.TxClient -b <para_1> <para_2> This invokes insertOnSessionBeforeClosed(String, String) on TxCallerSession, which invokes TxCalledSession.insert(String) without Connection.close(). While repeating 1 again and again results in no problem, we will encounter the problem on the seconds,fourth and sixth execution of 2. The source fragment of TxCallerSessionBean.insertOnSessionBeforeClosed(String, String) is: public void insertOnSessionBeforeClosed(String p_1, String p_2){ try{ System.out.println("Caller.insertOnSessionBeforeClosed()"); DataSource ds=(DataSource)env.lookup("jdbc/TxTest"); Connection con=ds.getConnection(); PreparedStatement stmt=con.prepareStatement("insert into tx_test (p_1,p_2) values(?,\"no value\")"); stmt.setString(1,p_1); stmt.executeUpdate(); stmt.close(); called.insert(p_2); } catch(Exception ex){ s_ctx.setRollbackOnly(); System.out.println(ex.toString()); throw (new EJBException(ex)); } } where 'called' is the remote reference of 'TxCalledSession'. And that of TxCalledSessionBean.insert(String) is: public void insert(String p){ try{ System.out.println("Called.insert()"); DataSource ds=(DataSource)env.lookup("jdbc/TxTest"); Connection con=ds.getConnection(); PreparedStatement stmt=con.prepareStatement("insert into tx_test (p_1,p_2) values(\"no value\",?)"); stmt.setString(1,p); stmt.executeUpdate(); stmt.close(); con.close(); } catch(Exception ex){ s_ctx.setRollbackOnly(); System.out.println(ex.toString()); throw (new EJBException(ex)); } } NOTE The difference between 1 and 2 is: As for 1, TxCallerSessionBean.insertOnSessionAfterClosed(String, String) invokes Connection.close() before TxCalledSessionBean.insert(String). And TxCalledSessionBean.insert(String) invokes Connection.close() again. As for 2, during TxCallerSessionBean.insertOnSessionBeforeClosed(String,String), Connection.close() is NOT invoked. Connection.close() is called only once in TxCalledSessionBean.insert(String). On other words: In case of 1, Connection.close() is invoked between the two DataSource.getConnection(). But in case of 2, the seconds DataSource.getConnection() is invoked without Connection.close() after the first DataSource.getConnection(). Now let's see what happens during the repetition of 2. 1. When the first execution of 2, DataSource.getConnection() in TxCallerSessionBean.insertOnSessionBeforeClosed(String,String) increments the value of PoolItem.open.(At this time PoolItem.open==1.) Transaction.enlistResource(XAResource) is invoked. 2. And DataSource.getConnection() in TxCalledSessionBean.insert(String) increments the value of PoolItem.open again. 3. So, at the time when Connection.close() (which invokes ConnectionManager.connectionClosed()) is invoked in TxCalledSessionBean.insert(String), the value of PoolItem.open is set to 2. During ConnectionManager.connectionClosed(), Pool.closeConnection(XAConnection) is called at first and Pool.closeConnection(XAConnection) decrements the value of PoolItem.open. Now the value of PoolItem.open is 1. Within ConnectionManager.connectionClosed(), only if PoolItem.open<1 is true, Transaction.delistResource(XAResource,int) is invoked. This means Transaction.delistResource(XAResource,int) is NOT invoked by Connection.close(). 4. Transaction.delistResource(XAResource,int) invokes XAResource.end(Xid,int) and this set the boolean value of XAResource.xa_started to false. But as long as Connection.close() does not invoke Transaction.delistResource(XAResource,int), the boolean value of XAResource.xa_started remains true. 5. After TxCalledSessionBean.insert(String) is finished, Current.commit() is invoked by the container. Then XAResource.commit(Xid,boolean) is invoked. At this point, XAResource.commit(Xid,boolean) on the instance of XAResource whose 'xa_started' is true does not cause the serious problem. We will just see the following message: ### commit: XA START without XA END ### Except this message, our first execution seems to finished successfully. 6. The instance of XAConnection is put into the pool of the re-usable XAConnection. But the instance of XAResource which is attached to such a pooled XAConnection remains as 'started'. 7. And now let's start the second execution. Again, DataSource.getConnection() in TxCallerSessionBean.insertOnSessionBeforeClosed(String,String) increments the value of PoolItem.open. Because PoolItem.open==1 is true at this time, Transaction.enlistResource(XAResource) is invoked. This invokes XAResource.start(Xid,int), but in this second execution, XAResource is the one retrieved from the pool. This means the boolean value of XAResource.xa_started is true and XAResource.start(Xid,int) throws the exception. The failure of XAResource.start(Xid,int) also means that the value of XAResource.currXid remains unchanged. 8. Regardless of the failure of XAResource.start(Xid,int), we can continue our procedure. And when TxCalledSessionBean.insert(String) is finished, Current.commit() is invoked by the container. Then XAResource.commit(Xid,boolean) is invoked. But this throws the exception again, because the value of XAResource.currXid does not equal to the given Xid. The 1-8 above also applies to the 3rd and 4th execution. As a result, we can say: In case that Connection.close() is called before the second DataSource.getConnection(), there may be no problem. But if Connection.close() is not invoked between the two DataSource.getConnection(), we encounter the exception. I don't know whether this restriction should be un-locked. But to unlock this, there may be the 2 solution. Solution 1 Both of ConnectionManager.getConnection() ConnectionManager.connectionClosed() depends on the value of PoolItem.open to determine whether to invoke Transaction.enlistResource(XAResource) Transaction.delistResource(XAResource,int) or not. And this results in the problem. Instead of the value of PoolItem.open, we should use another flag which represents whether XAResource.start(Xid,int) is invoked or not. Solution 2 In any case, after Current.commit() is invoked, the instance of XAResource which participated in the transaction should be marked as 'ended'. This can be done by: if (xa_started) { xa_started=false; } within XAResource.commit(Xid,boolean) . Which do you like? Or any of them will cause the other problem? Any questions and comments are welcome. PS: I've just joined into this mailing list. So, from now on, posting to the list is enough. -- Happy Java programming! Jun Inamori E-mail: [EMAIL PROTECTED] URL: http://www.oop-reserch.com Mohd Faizal bin Yusof wrote: > > Dear all, > > Help please... > > I still get the following error message after I use the latest source from > cvs and I also tried the patch sent by Jun Inamori but no luck. Can you help > me interprete the error message please. The DBHelper.getConnection is just a > static method inside a helper class that return a connection from > datasource. Thank you in advance > > DBHelper.getConenction is called > WARNING: Connection was not always closed correctly ! > DBHelper.getConenction is called > Cannot enlist XAResource:javax.transaction.SystemException: Cannot send XA > start > :javax.transaction.xa.XAException: mixed transactions > Exception in connectionClosed:javax.transaction.SystemException: Cannot send > XA > end:javax.transaction.xa.XAException > DBHelper.getConenction is called > Cannot enlist XAResource:javax.transaction.SystemException: Cannot send XA > start > :javax.transaction.xa.XAException: mixed transactions > Exception in connectionClosed:javax.transaction.SystemException: Cannot send > XA > end:javax.transaction.xa.XAException > Unexpected Exception on commit_one_phase:java.rmi.RemoteException: > XAException:j > avax.transaction.xa.XAException: Cannot mix transactions > doPostInvoke: javax.transaction.SystemException: Unexpected Exception on > commit_ > one_phase > > Faizal Yusof > Systems Developer > Sufficient Systems Malaysia Sdn Bhd > Email: [EMAIL PROTECTED] > Phone: 03-21669226 > > -----Original Message----- > From: Philippe Durieux [mailto:[EMAIL PROTECTED]] > Sent: Wednesday, May 17, 2000 4:34 PM > To: [EMAIL PROTECTED] > Cc: [EMAIL PROTECTED] > Subject: Re: URGENT: transaction management problem > > Alexandre Lefebvre wrote: > > > > (repost) > > > > From: [EMAIL PROTECTED] > > Date: Thu, 11 May 2000 16:53:35 +0530 > > > > Hi, > > We are facing a serious problem regarding transaction management in > > JOnAS2.0. It is really crucial to the completion of the project now. > > > > The existing application was working perfectly in J2EE. It is only after > the > > shift to JOnAS 2.0 that we faced this problem. > > > > We are using Session Beans with Transaction managed by Containers. In some > > methods of these Beans , there is inter Bean reference, where the method > of > > another bean is being invoked. The invoked method of the referenced bean > , > > as well as the calling method of the Calling bean have the Transaction > > Attribute set to TX_REQUIRED. > > If both the substituent methods are executed successfully, the data goes > > correctly into the database, however the EJB Server still throws an > > exception - commit_one_phase exception. As a result of which, we are not > > able to detect the success/failure of the transaction. > > > > Is there a way to execute the above scenario using Bean Managed > > Transaction(by Coding for the Transaction in the bean) ? > > > > Thanx! > > Rohini > I think this question has already been replied a few days ago, but maybe > not in this list... > A bug has been fixed in jonas 2.0 concerning the jdbc connections that > were not closed by the user. In that case, you sometimes got a > "commit_one_phase exception". Try the new JOnAS version on the cvs tree > to see if this fix your problem. > Another solution is to always close connections before leaving a method, > since there is a pool of connections that is managed by the JOnAS server > that insure that connections can be reused, i.e. the physical jdbc > connection > is never closed really. > > Philippe > -- > Philippe Durieux ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > Bull S.A - 1 rue de Provence - 38432 Echirolles Cedex France > [EMAIL PROTECTED] http://www-frec.bull.com > -> Download our EJBServer at http://www.bullsoft.com/ejb <- > ---- > This list is cross-posted to two mail lists. To unsubscribe, > follow the instructions below for the list you subscribed to. > For objectweb.org: send email to [EMAIL PROTECTED] and > include in the body of the message "unsubscribe ejb-container-group". > For enhydra.org: send email to [EMAIL PROTECTED] and include > in the body of the message "unsubscribe ejb-container-group".

S/MIME Cryptographic Signature

Reply via email to