Atomikos Forum |
|
We have had some problems with Atomikos in combination with the 3.00.JC3 driver of Informix (the recommended version!). To provide the necessary context:
- our database restarts every night - we add dynamically datasources (even during a transaction) - xares_.isSameRM ( xares_ ) doesn't throw any Exception on a 'corrupt' XAResource - Atomikos starts a recovery scan each time a new datasource is initialized Given this we get troubles "caused" by line 784 XATransactionalResource#recover(Participant participant) if ( recovered || getName().equals ( xarestx.resourcename_ ) ) xarestx.setRecoveredXAResource ( getXAResource () ); getXAResource() doesn't detect the corrupt state of the XAResource and so a corrupt XAResource enters into the tranaction. This gives us following errors: javax.transaction.RollbackException: Prepare: NO vote at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:311) at com.atomikos.icatch.jta.TransactionManagerImp.commit(TransactionManagerImp.java:608) at com.atomikos.icatch.jta.UserTransactionImp.commit(UserTransactionImp.java:168) at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1028) ... 69 more and... javax.transaction.xa.XAException: java.sql.SQLException: System or internal error java.net.SocketException: Broken pipe at com.informix.jdbcx.IfxXAResource.prepare(IfxXAResource.java:248) at com.atomikos.datasource.xa.XAResourceTransaction.prepare(XAResourceTransaction.java:799) at com.atomikos.icatch.imp.PrepareMessage.send(PrepareMessage.java:79) at com.atomikos.icatch.imp.PropagationMessage.submit(PropagationMessage.java:86) at com.atomikos.icatch.imp.Propagator$PropagatorThread.run(Propagator.java:62) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Our workaroud is to use a tweaked Informix driver. We changed the behaviour of isSameRM : boolean returnValue = this.xares.isSameRM(((TweakedXAResource) xares).getXares()); if (this == xares) { try { forget(new IfxXid(777, new byte[]{0x27, 0x06}, new byte[]{0x19, 0x79})); } catch (XAException e) { if (e.errorCode != XAException.XAER_NOTA) { throw e; } } } return returnValue; This workaround could be avoided if Atomikos would use a simular trick to test the state of the connection: instead of boolean ret = true; // check if connection has not timed out try { // we should be the same as ourselves! // NOTE: xares_ is null if no connection could be gotten // in that case we just return true // otherwise, test the xaresource liveness if ( xares_ != null ) { xares_.isSameRM ( xares_ ); ret = false; } } catch ( XAException xa ) { // timed out? Configuration.logDebug ( servername_ + ": XAResource needs refresh?", xa ); } return ret; you could... boolean ret = true; // check if connection has not timed out try { // we should be the same as ourselves! // NOTE: xares_ is null if no connection could be gotten // in that case we just return true // otherwise, test the xaresource liveness if ( xares_ != null ) { xares_.forget(new IfxXid(777, new byte[]{0x27, 0x06}, new byte[]{0x19, 0x79})); ret = false; // should be impossible !! } } catch ( XAException xa ) { if (e.errorCode == XAException.XAER_NOTA) { ret = false; // timed out? Configuration.logDebug ( servername_ + ": XAResource needs refresh?", xa ); } } return ret; You will just need to alter the Xid constructor. Is this a good sollution or are better sollutions out there? |