This content has been marked as final.
Show 3 replies
-
1. Re: Force Oracle to Rollback _after_ prepare phase?
weston.price May 8, 2007 6:01 PM (in response to ypsilon)This is a heuristic.
Technically once a resource agrees in the prepare phase, the commit must occur. Is the offensive resource throwing an Exception in your case? This should force the rollback of the other participant. When you say 'does not respond to the commit request' what do you mean? -
2. Re: Force Oracle to Rollback _after_ prepare phase?
ypsilon May 9, 2007 6:16 AM (in response to ypsilon)Hi Weston.
"weston.price@jboss.com" wrote:
This is a heuristic.
Technically once a resource agrees in the prepare phase, the commit must occur. Is the offensive resource throwing an Exception in your case? This should force the rollback of the other participant. When you say 'does not respond to the commit request' what do you mean?
The problem is that the resource seems to be no longer available. The TCP-Socket times out. This of course means that the commit request might have reached it's destination and thereby caused the commit to be executed, but from my experiences so far this did not happen.
Since all communication is done via HTTP and the ResourceManager itself is not java an Exception is not really possible. In case of a timeout the XAResource at the moment throws a XAException (RMERR).
If I however set up a test case and throw whatever exception in the XAResource the other participant is not being rolled back. Here is some sample code:The Method which does the work looks like this (called remotely): /** * @throws CreateException * @ejb.interface-method * @ejb.transaction type="Required" */ public void jtaTest() throws RemoteException, CreateException { ctx.lookup("java:/TransactionManager"); try { TransactionManager transactionManager = (TransactionManager)new InitialContext().lookup("java:/TransactionManager"); log.info(transactionManager.getClass()); transactionManager.getTransaction().enlistResource(new MyXAResource()); AddressValue addy2 = new AddressValue(); addy2.setCity("einestadt"); addy2.setId(new Long(System.currentTimeMillis())); addy2.setName("ich"); addy2.setStreet("am kamp 12"); AddressUtil.getLocalHome().create(addy2) ; } catch (Exception e) { e.printStackTrace(); ctx.setRollbackOnly(); } } And this is the enlisted XAResource: private static class MyXAResource implements XAResource { Xid managedXid = null; public void commit(Xid xid, boolean b) throws XAException { log.info("Nummer 1:commiting " + xid); int testFlag=0; switch (testFlag) { case 0: log.info("Nummer 1:Error during commit"); throw new XAException(XAException.XA_HEURRB); case 1: log.info("Nummer 1:Error during commit"); throw new RuntimeException("blabla"); case 2: log.info("Nummer 1:Error during commit"); throw new XAException(XAException.XAER_RMERR); } log.info("Nummer 1:done commiting"); } public void end(Xid xid, int i) throws XAException { log.info("Nummer 1:end transcation " + xid); } public void forget(Xid xid) throws XAException { log.info("Nummer 1:forget transcation " + xid); } public int getTransactionTimeout() throws XAException { return 5000; //To change body of implemented methods use File | Settings | File Templates. } public boolean isSameRM(XAResource xaResource) throws XAException { log.info("Nummer 1:isSameRM called"); return xaResource == this; } public int prepare(Xid xid) throws XAException { boolean flag = false; log.info("Nummer 1: prepare called."); if (flag) { throw new XAException(XAException.XA_RBCOMMFAIL ); } return XA_OK; //To change body of implemented methods use File | Settings | File Templates. } public Xid[] recover(int i) throws XAException { log.info("Nummer 1:recover called"); return new Xid[0]; //To change body of implemented methods use File | Settings | File Templates. } public void rollback(Xid xid) throws XAException { boolean flag = false; if (flag) { throw new XAException(XAException.XAER_RMERR ); } } public boolean setTransactionTimeout(int i) throws XAException { return false; //To change body of implemented methods use File | Settings | File Templates. } public void start(Xid xid, int flags) throws XAException { if (xid == null) throw new XAException(XAException.XAER_INVAL); if (managedXid != null) { throw new XAException(XAException.XAER_INVAL); } else { managedXid = xid; } log.info("Nummer 1:start called " + xid + " i " +flags); } }
as you can see in commit there is always an XAException being thrown.
here is some logging11:40:15,195 INFO [CMRTestFacadeBean] Nummer 1:Error during commit 11:40:15,196 WARN [TransactionImpl] XAException: tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=toaster/15, BranchQual=, localId=15] errorCode=XA_HEURRB javax.transaction.xa.XAException at eval.cmr.CMRTestFacadeBean$MyXAResource.commit(CMRTestFacadeBean.java:313)action.xa.XAException at org.jboss.tm.TransactionImpl$Resource.commit(TransactionImpl.java:2253) at org.jboss.tm.TransactionImpl.commitResources(TransactionImpl.java:1784) at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:358) ... "weston.price@jboss.com" wrote: This is a heuristic. Technically once a resource agrees in the prepare phase, the commit must occur. Is the offensive resource throwing an Exception in your case? This should force the rollback of the other participant. When you say 'does not respond to the commit request' what do you mean? The problem is that the resource seems to be no longer available. The TCP-Socket times out. This of course means that the commit request might have reached it's destination and thereby caused the commit to be executed, but from my experiences so far this did not happen. Since all communication is done via HTTP and the ResourceManager itself is not java an Exception is not really possible. If I however set up a test case and throw whatever exception in the XAResource the other participant is not being rolled back. Here is some sample code: The Method which does the work looks like this (called remotely): /** * @throws CreateException * @ejb.interface-method * @ejb.transaction type="Required" */ public void jtaTest() throws RemoteException, CreateException { ctx.lookup("java:/TransactionManager"); try { TransactionManager transactionManager = (TransactionManager)new InitialContext().lookup("java:/TransactionManager"); log.info(transactionManager.getClass()); transactionManager.getTransaction().enlistResource(new MyXAResource()); AddressValue addy2 = new AddressValue(); addy2.setCity("einestadt"); addy2.setId(new Long(System.currentTimeMillis())); addy2.setName("ich"); addy2.setStreet("am kamp 12"); // save the address to the DB AddressUtil.getLocalHome().create(addy2) ; } catch (Exception e) { e.printStackTrace(); ctx.setRollbackOnly(); } } And this is the enlisted XAResource: private static class MyXAResource implements XAResource { Xid managedXid = null; public void commit(Xid xid, boolean b) throws XAException { log.info("Nummer 1:commiting " + xid); int testFlag=0; switch (testFlag) { case 0: log.info("Nummer 1:Error during commit"); throw new XAException(XAException.XA_HEURRB); case 1: log.info("Nummer 1:Error during commit"); throw new RuntimeException("blabla"); case 2: log.info("Nummer 1:Error during commit"); throw new XAException(XAException.XAER_RMERR); } log.info("Nummer 1:done commiting"); } public void end(Xid xid, int i) throws XAException { log.info("Nummer 1:end transcation " + xid); } public void forget(Xid xid) throws XAException { log.info("Nummer 1:forget transcation " + xid); } public int getTransactionTimeout() throws XAException { return 5000; //To change body of implemented methods use File | Settings | File Templates. } public boolean isSameRM(XAResource xaResource) throws XAException { log.info("Nummer 1:isSameRM called"); return xaResource == this; } public int prepare(Xid xid) throws XAException { boolean flag = false; log.info("Nummer 1: prepare called."); if (flag) { throw new XAException(XAException.XA_RBCOMMFAIL ); } return XA_OK; //To change body of implemented methods use File | Settings | File Templates. } public Xid[] recover(int i) throws XAException { log.info("Nummer 1:recover called"); return new Xid[0]; //To change body of implemented methods use File | Settings | File Templates. } public void rollback(Xid xid) throws XAException { boolean flag = false; if (flag) { throw new XAException(XAException.XAER_RMERR ); } } public boolean setTransactionTimeout(int i) throws XAException { return false; //To change body of implemented methods use File | Settings | File Templates. } public void start(Xid xid, int flags) throws XAException { if (xid == null) throw new XAException(XAException.XAER_INVAL); if (managedXid != null) { throw new XAException(XAException.XAER_INVAL); } else { managedXid = xid; } log.info("Nummer 1:start called " + xid + " i " +flags); } } as you can see in commit there is always an XAException being thrown. here is some logging 11:40:15,195 INFO [CMRTestFacadeBean] Nummer 1:Error during commit 11:40:15,196 WARN [TransactionImpl] XAException: tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=toaster/15, BranchQual=, localId=15] errorCode=XA_HEURRB javax.transaction.xa.XAException at eval.cmr.CMRTestFacadeBean$MyXAResource.commit(CMRTestFacadeBean.java:313)action.xa.XAException at org.jboss.tm.TransactionImpl$Resource.commit(TransactionImpl.java:2253) at org.jboss.tm.TransactionImpl.commitResources(TransactionImpl.java:1784) at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:358) ... 11:40:15,209 INFO [CMRTestFacadeBean] Nummer 1:forget transcation XidImpl[FormatId=257, GlobalId=toaster/15, BranchQual=1, localId=15] 11:40:15,242 ERROR [LogInterceptor] TransactionRolledbackException in method: public abstract void eval.cmr.CMRTestFacade.jtaTest() throws javax.ejb.CreateException,java.rmi.RemoteException, causedBy: javax.transaction.HeuristicRollbackException at org.jboss.tm.TransactionImpl.checkHeuristics(TransactionImpl.java:1610) at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:378) at org.jboss.ejb.plugins.TxInterceptorCMT.endTransaction(TxInterceptorCMT.java:501) at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:361) at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:181) at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:168) The address which is created is however being written to the Database. Is that normal? Thanks in advance Greetings PeeR
-
3. Re: Force Oracle to Rollback _after_ prepare phase?
adrian.brock May 16, 2007 11:47 AM (in response to ypsilon)"ypsilon" wrote:
The address which is created is however being written to the Database.
Is that normal?
Yes that is normal. Heuristics are bad. It means you have an inconsistent commit.
To fix this problem (commit phase fails after prepare)
you need a recovering TM, NOT heuristics, that will
remember the failed commit phase and try the request again "later"
when it has re-established the connectivity.
http://labs.jboss.com/jbosstm/