Your test is not correct - If rollback() or commit() from 
DummyTransactionManager is invoked in separate thread, 
DummyBaseTransactionManager can't find transaction stored in thread_local and 
IllegalStateException("thread not associated with transaction"); is throwed 
instead real rollback operation execution.

This is unit test that recreates this problem outside WebLogic. 
AsyncRollbackTransactionManager works like weblogic transaction manager.
Note: only rollbacks (and not all !!!!! Only timed out transactions and only if 
transaction was checked by internal transactionManager timer!) are executed in 
separate thread! 


AsyncRollbackTxTest

  | package org.jboss.cache.transaction;
  | 
  | import javax.transaction.SystemException;
  | import javax.transaction.TransactionManager;
  | 
  | import junit.framework.TestCase;
  | 
  | import org.jboss.cache.CacheException;
  | import org.jboss.cache.Fqn;
  | import org.jboss.cache.TreeCache;
  | 
  | /**
  |  * Test behaviour of async rollback timeouted transaction
  |  *
  |  * @author <a href="mailto:[EMAIL PROTECTED]">Jacek Halat</a>
  |  * @since 1.4.0
  |  */
  | public class AsyncRollbackTxTest extends TestCase
  | {
  |    private TreeCache cache;
  |    private TransactionManager tm;
  |    private Fqn fqn = Fqn.fromString("/test");
  | 
  |    protected void setUp() throws Exception
  |    {
  |       cache = new TreeCache();
  |       
cache.setTransactionManagerLookupClass("org.jboss.cache.transaction.AsyncRollbackTransactionManagerLookup");
  |       cache.startService();
  |       tm = cache.getTransactionManager();
  |    }
  | 
  |    protected void tearDown()
  |    {
  |       try
  |       {
  |          if (tm != null && tm.getTransaction() != null)
  |          {
  |             try
  |             {
  |                tm.rollback();
  |             }
  |             catch (SystemException e)
  |             {
  |                // do nothing
  |             }
  |          }
  |       }
  |       catch (SystemException e)
  |       {
  |          // do nothing
  |       }
  |       if (cache != null) cache.stopService();
  |       cache = null;
  |       tm = null;
  |    }
  | 
  |    public void testControl() throws Exception
  |    {
  |       assertEquals(0, cache.getNumberOfLocksHeld());
  |       tm.begin();
  |       cache.put(fqn, "k", "v");
  |       assertEquals(1, cache.getNumberOfLocksHeld());
  |       tm.rollback();
  |       assertEquals(0, cache.getNumberOfLocksHeld());
  |    }
  | 
  |    public void testRollbackInDifferentThread() throws Exception
  |    {
  |               tm.setTransactionTimeout(2);
  |           tm.begin();
  |           cache.put(fqn, "k", "v");
  |           assertEquals(1, cache.getNumberOfLocksHeld());
  |           Thread.sleep(5000);
  |        try{
  |           tm.commit();
  |        }catch(Exception e){
  |                e.printStackTrace();
  |        }
  |       assertEquals(0, cache.getNumberOfLocksHeld());
  |       cache.put(fqn, "k", "v");//Executed in Not transactional context
  | //      assertEquals(0, cache.getNumberOfLocksHeld());
  |       SeparateThread t = new SeparateThread();
  |       t.start();
  |       t.join();
  |       if (t.getException()!=null){
  |               throw t.getException();
  |       }
  |    }
  |    private class SeparateThread extends Thread{
  |       Exception e = null;
  |       public Exception getException() {
  |             return e;
  |     }
  |     @Override
  |     public void run() {
  |         try {
  |                     cache.put(fqn, "k", "v");
  |                   assertEquals(0, cache.getNumberOfLocksHeld());
  |             } catch (CacheException e) {
  |                     this.e = e;
  |             }
  |     }
  |   };
  | }
  | 
  | 

AsyncRollbackTransactionManager

  | package org.jboss.cache.transaction;
  | 
  | import java.util.HashMap;
  | import java.util.Iterator;
  | import java.util.Map;
  | import java.util.Properties;
  | 
  | import javax.naming.Context;
  | import javax.naming.InitialContext;
  | import javax.naming.NamingException;
  | import javax.transaction.HeuristicMixedException;
  | import javax.transaction.HeuristicRollbackException;
  | import javax.transaction.InvalidTransactionException;
  | import javax.transaction.NotSupportedException;
  | import javax.transaction.RollbackException;
  | import javax.transaction.SystemException;
  | import javax.transaction.Transaction;
  | 
  | public class AsyncRollbackTransactionManager extends 
DummyTransactionManager{
  |        static AsyncRollbackTransactionManager instance=null;
  | 
  |        public static DummyTransactionManager getInstance() {
  |                   if(instance == null) {
  |                      instance=new AsyncRollbackTransactionManager();
  |                      try {
  |                         Properties p=new Properties();
  |                         p.put(Context.INITIAL_CONTEXT_FACTORY, 
"org.jboss.cache.transaction.DummyContextFactory");
  |                         Context ctx=new InitialContext(p);
  |                         ctx.bind("java:/TransactionManager", instance);
  |                         ctx.bind("UserTransaction", new 
DummyUserTransaction(instance));
  |                      }
  |                      catch(NamingException e) {
  |                         log.error("binding of DummyTransactionManager 
failed", e);
  |                      }
  |                   }
  |                   return instance;
  |                }
  |        
  |     private Thread timedOutTransactionsChecker = null;
  |     private int timeout = 30;
  |     private Map txMap = new HashMap();
  |     @Override
  |     public void setTransactionTimeout(int seconds) throws SystemException {
  |             this.timeout = seconds;
  |     }
  |     public AsyncRollbackTransactionManager(){
  |             timedOutTransactionsChecker = new TimedOutTransactionsChecker();
  |             timedOutTransactionsChecker.start();
  |     }
  |     private class TimedOutTransactionsChecker extends Thread{
  |             private boolean running;
  |             public TimedOutTransactionsChecker(){
  |             }
  |             public void run() {
  |                     running = true;
  |                     while (running){
  |                             try {
  |                                     Thread.sleep(500);
  |                             synchronized(this)
  |                         {
  |                             Iterator iterator = txMap.values().iterator();
  |                             do
  |                             {
  |                                 if(!iterator.hasNext())
  |                                     break;
  |                                 AsyncRollbackTransaction t = 
(AsyncRollbackTransaction)iterator.next();
  |                             try {
  |                                                             t.wakeUp();
  |                                                     } catch 
(SystemException e) {
  |                                                             
e.printStackTrace();
  |                                                     }
  | 
  |                             } while(true);
  |                         }
  |                             } catch (InterruptedException e) {
  |                             }
  |                     }
  |             }
  |             
  |     }
  |     @SuppressWarnings("unchecked")
  |     @Override
  |     public void begin() throws NotSupportedException, SystemException {
  |           Transaction currentTx;
  |           if((currentTx=getTransaction()) != null)
  |              throw new NotSupportedException(Thread.currentThread() +
  |                                              " is already associated with a 
transaction (" + currentTx + ")");
  |           AsyncRollbackTransaction tx=new 
AsyncRollbackTransaction(this,timeout);
  |           setTransaction(tx);
  |           txMap.put(tx.generateTransactionId(), tx);
  |     }
  |     @Override
  |     public void rollback() throws IllegalStateException, SecurityException, 
SystemException {
  |         removeTxFromMap();
  |             super.rollback();
  |     }
  |     public void removeTxFromMap() throws SystemException {
  |             AsyncRollbackTransaction tx=(AsyncRollbackTransaction) 
getTransaction();
  |             if (tx!=null){
  |                     txMap.remove(tx.getTransactionId());
  |             }
  |     }
  |     @Override
  |     public void commit() throws RollbackException, HeuristicMixedException, 
HeuristicRollbackException, SecurityException, IllegalStateException, 
SystemException {
  |         AsyncRollbackTransaction tx=(AsyncRollbackTransaction) 
getTransaction();
  |             if (tx!=null){
  |                     txMap.remove(tx.getTransactionId());
  |             }
  |             super.commit();
  |     }
  |     @Override
  |     public void resume(Transaction tx) throws InvalidTransactionException, 
IllegalStateException, SystemException {
  |             //TODO Not implemented TX timeout counting
  |             super.resume(tx);
  |     }
  |     @Override
  |     public Transaction suspend() throws SystemException {
  |             //TODO Not implemented TX timeout counting
  |             return super.suspend();
  |     }
  | }
  | 
  | 
  | 

AsyncRollbackTransactionManagerLookup

  | package org.jboss.cache.transaction;
  | 
  | import javax.transaction.TransactionManager;
  | 
  | import org.jboss.cache.TransactionManagerLookup;
  | 
  | public class AsyncRollbackTransactionManagerLookup implements 
TransactionManagerLookup{
  |     public TransactionManager getTransactionManager() throws Exception {
  |             return AsyncRollbackTransactionManager.getInstance();
  |     }
  | 
  | }
  | 


AsyncRollbackTransaction

  | package org.jboss.cache.transaction;
  | 
  | import javax.transaction.SystemException;
  | 
  | 
  | public class AsyncRollbackTransaction extends DummyTransaction {
  |     private static long transactionNums = 0;
  | 
  |     private long transactionId;
  | 
  |     private long beginTimeMillis;
  | 
  |     private int timeoutSec;
  | 
  |     public AsyncRollbackTransaction(DummyBaseTransactionManager tm, int 
timeout) {
  |             super(tm);
  |             this.timeoutSec = timeout;
  |             this.beginTimeMillis = System.currentTimeMillis();
  |     }
  | 
  |     /**
  |      * @return the transactionId
  |      */
  |     public long getTransactionId() {
  |             return transactionId;
  |     }
  | 
  |     public long generateTransactionId() {
  |             long result = 0;
  |             synchronized (AsyncRollbackTransaction.class) {
  |                     transactionNums++;
  |                     result = transactionNums;
  |             }
  |             this.transactionId = result;
  |             return result;
  |     }
  | 
  |     final int getTimeoutSeconds() {
  |             return timeoutSec;
  |     }
  | 
  |     protected final void asyncRollback() throws SystemException {
  |             Thread asyncRollbackThread = new Thread() {
  |                     public void run() {
  |                             try {
  |                                     rollback();
  |                             } catch (Exception exception) {
  |                             }
  |                     }
  |             };
  |             ((AsyncRollbackTransactionManager)tm_).removeTxFromMap();
  |             asyncRollbackThread.start();
  |     }
  | 
  |     public void wakeUp() throws SystemException {
  |             if (isTransactionTimedOut()) {
  |                     asyncRollback();
  |             }
  |     }
  |     private boolean isTransactionTimedOut() {
  |             return (System.currentTimeMillis() - beginTimeMillis) > 
(timeoutSec * 1000);
  |     }
  | }
  | 

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3998433#3998433

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3998433
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to