/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.jca.test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Attribute;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
import javax.security.auth.Subject;
import javax.transaction.RollbackException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.logging.Logger;
import org.jboss.resource.connectionmanager.CachedConnectionManager;
import org.jboss.resource.connectionmanager.ConnectionListener;
import org.jboss.resource.connectionmanager.InternalManagedConnectionPool;
import org.jboss.resource.connectionmanager.JBossManagedConnectionPool.BasePool;
import org.jboss.resource.connectionmanager.JBossManagedConnectionPool;
import org.jboss.resource.connectionmanager.ManagedConnectionPool;
import org.jboss.resource.connectionmanager.TxConnectionManager;
import org.jboss.test.JBossTestCase;
import org.jboss.test.util.ejb.EJBTestCase;
import org.jboss.tm.TransactionManagerLocator;
import org.jboss.tm.TxUtils;
import org.jboss.test.jca.adapter.TestConnection;
import org.jboss.test.jca.adapter.TestConnectionRequestInfo;
import org.jboss.test.jca.adapter.TestManagedConnection;
import org.jboss.test.jca.adapter.TestManagedConnectionFactory;
/**
* Unit test for class TxConnectionManager
*
* @author <a href="mailto:jesper.pedersen@jboss.org">Jesper Pedersen</a>
* @version $Revision: 108300 $
*/
public class TxConnectionManagerUnitTestCase extends EJBTestCase
{
private static final Logger log = Logger.getLogger(TxConnectionManagerUnitTestCase.class);
private Subject subject = new Subject();
private ConnectionRequestInfo cri = new TestConnectionRequestInfo();
private CachedConnectionManager ccm = new CachedConnectionManager();
private TestManagedConnectionFactory mcf;
private TxConnectionManager cm;
private TransactionManager tm;
private int txTimeout;
/**
* Creates a new <code>TxConnectionManagerUnitTestCase</code> instance.
* @param name test name
*/
public TxConnectionManagerUnitTestCase(String name)
{
super(name);
}
public static Test suite() throws Exception
{
TestSuite suite = new TestSuite();
suite.addTest(new TxConnectionManagerUnitTestCase("testAllocateConnection"));
suite.addTest(new TxConnectionManagerUnitTestCase("testConnectionEventListenerConnectionClosed"));
suite.addTest(new TxConnectionManagerUnitTestCase("testSynchronizationAfterCompletion"));
suite.addTest(new TxConnectionManagerUnitTestCase("testSynchronizationAfterCompletionTxTimeout"));
suite.addTest(new TxConnectionManagerUnitTestCase("testGetManagedConnection"));
suite.addTest(new TxConnectionManagerUnitTestCase("testGetManagedConnectionTimeout"));
suite.addTest(new TxConnectionManagerUnitTestCase("testGetManagedConnectionTrackByTx"));
suite.addTest(new TxConnectionManagerUnitTestCase("testGetManagedConnectionTimeoutTrackByTx"));
suite.addTest(new TxConnectionManagerUnitTestCase("testConnectionError"));
suite.addTest(new TxConnectionManagerUnitTestCase("testConnectionErrorTrackByTx"));
suite.addTest(new TxConnectionManagerUnitTestCase("testSimulateConnectionError"));
suite.addTest(new TxConnectionManagerUnitTestCase("testSimulateConnectionErrorTrackByTx"));
return JBossTestCase.getDeploySetup(suite, "jca-tests.jar");
}
@Override
protected void setUp() throws Exception
{
super.setUp();
tm = TransactionManagerLocator.getInstance().locate();
mcf = new TestManagedConnectionFactory();
InternalManagedConnectionPool.PoolParams pp = new InternalManagedConnectionPool.PoolParams();
ManagedConnectionPool poolingStrategy = new JBossManagedConnectionPool.OnePool(mcf, pp, false, log);
cm = new TxConnectionManager(ccm, poolingStrategy, tm);
poolingStrategy.setConnectionListenerFactory(cm);
MBeanServer server = MBeanServerLocator.locateJBoss();
ObjectName onCE = new ObjectName("jboss.jta:name=CoordinatorEnvironmentBean");
txTimeout = ((Integer)server.getAttribute(onCE, "DefaultTimeout")).intValue();
}
@Override
protected void tearDown() throws Exception
{
JBossManagedConnectionPool.OnePool pool = (JBossManagedConnectionPool.OnePool)cm.getPoolingStrategy();
pool.shutdown();
tm.setTransactionTimeout(0);
tm = null;
cm = null;
mcf = null;
super.tearDown();
}
/**
* Test that a connection can be allocated
* @exception Exception If an error occurs
*/
public void testAllocateConnection() throws Exception
{
log.info("----------------------");
log.info("testAllocateConnection");
log.info("----------------------");
tm.begin();
TestConnection c = null;
try
{
c = (TestConnection)cm.allocateConnection(mcf, cri);
try
{
assertTrue("Connection not enlisted in tx!", c.isInTx());
}
finally
{
c.close();
}
}
finally
{
Transaction tx = tm.getTransaction();
if (tx != null)
{
if (TxUtils.isActive(tx))
tm.commit();
else
tm.rollback();
}
else
fail("Transaction is null");
}
assertTrue("Connection still enlisted in tx!", !c.isInTx());
}
/**
* Test
* @exception Exception If an error occurs
*/
public void testConnectionEventListenerConnectionClosed() throws Exception
{
log.info("-------------------------------------------");
log.info("testConnectionEventListenerConnectionClosed");
log.info("-------------------------------------------");
tm.begin();
try
{
TestConnection c = (TestConnection)cm.allocateConnection(mcf, cri);
c.close();
}
finally
{
Transaction tx = tm.getTransaction();
if (tx != null)
{
if (TxUtils.isActive(tx))
tm.commit();
else
tm.rollback();
}
else
fail("Transaction is null");
}
}
/**
* Test
* @exception Exception If an error occurs
*/
public void testSynchronizationAfterCompletion() throws Exception
{
log.info("----------------------------------");
log.info("testSynchronizationAfterCompletion");
log.info("----------------------------------");
// track-by-tx = true
cm.setTrackConnectionByTx(true);
tm.begin();
try
{
TestConnection c = (TestConnection)cm.allocateConnection(mcf, cri);
c.close();
}
finally
{
Transaction tx = tm.getTransaction();
if (tx != null)
{
if (TxUtils.isActive(tx))
tm.commit();
else
tm.rollback();
}
else
fail("Transaction is null");
}
}
/**
* Test
* @exception Exception If an error occurs
*/
public void testSynchronizationAfterCompletionTxTimeout() throws Exception
{
log.info("-------------------------------------------");
log.info("testSynchronizationAfterCompletionTxTimeout");
log.info("-------------------------------------------");
// track-by-tx = true
cm.setTrackConnectionByTx(true);
tm.setTransactionTimeout(2);
TestConnection c = null;
try
{
tm.begin();
assertEquals("1", 0, cm.getPoolingStrategy().getInUseConnectionCount());
c = (TestConnection)cm.allocateConnection(mcf, cri);
assertEquals("2", 1, cm.getPoolingStrategy().getInUseConnectionCount());
Thread.sleep(2500L);
Transaction tx = tm.getTransaction();
if (tx != null && TxUtils.isActive(tx))
fail("TX is still active");
c.close();
c = null;
assertEquals("3", 0, cm.getPoolingStrategy().getInUseConnectionCount());
}
finally
{
if (c != null)
{
c.close();
fail("Connection wasnt closed");
}
assertNotNull(tm);
if (!TxUtils.isCompleted(tm))
{
tm.rollback();
fail("Tx was still active");
}
}
}
/**
* Test that a connection can be obtained from getManagedConnection
* and enlisted/delisted in a transaction
* @exception Exception If an error occurs
*/
public void testGetManagedConnection() throws Exception
{
log.info("------------------------");
log.info("testGetManagedConnection");
log.info("------------------------");
ConnectionListener cl = null;
try
{
assertNotNull(tm);
tm.begin();
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
cl = cm.getManagedConnection(subject, cri);
assertEquals(1, cm.getPoolingStrategy().getInUseConnectionCount());
assertNotNull(cl);
cl.enlist();
assertNotNull(tm);
tm.commit();
cl.delist();
cm.returnManagedConnection(cl, false);
cl = null;
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
}
finally
{
if (cl != null)
{
cm.returnManagedConnection(cl, true);
fail("ConnectionListener wasnt returned to the pool");
}
assertNotNull(tm);
if (TxUtils.isUncommitted(tm))
{
tm.rollback();
}
}
}
/**
* Test that a connection can be obtained from getManagedConnection
* and enlisted in a transaction that suffer timeout
* @exception Exception If an error occurs
*/
public void testGetManagedConnectionTimeout() throws Exception
{
log.info("-------------------------------");
log.info("testGetManagedConnectionTimeout");
log.info("-------------------------------");
ConnectionListener cl = null;
try
{
assertNotNull(tm);
tm.setTransactionTimeout(2);
tm.begin();
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
cl = cm.getManagedConnection(subject, cri);
assertEquals(1, cm.getPoolingStrategy().getInUseConnectionCount());
assertNotNull(cl);
cl.enlist();
Thread.sleep(2500L);
cl.delist();
cm.returnManagedConnection(cl, false);
cl = null;
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
}
finally
{
if (cl != null)
{
cm.returnManagedConnection(cl, true);
fail("ConnectionListener wasnt returned to the pool");
}
assertNotNull(tm);
if (!TxUtils.isCompleted(tm))
{
tm.rollback();
fail("Tx was still active");
}
}
}
/**
* Test that a connection can be obtained from getManagedConnection
* and enlisted/delisted in a transaction with track-by-tx enabled
* @exception Exception If an error occurs
*/
public void testGetManagedConnectionTrackByTx() throws Exception
{
log.info("---------------------------------");
log.info("testGetManagedConnectionTrackByTx");
log.info("---------------------------------");
// track-by-tx = true
cm.setTrackConnectionByTx(true);
ConnectionListener cl = null;
try
{
assertNotNull(tm);
tm.begin();
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
cl = cm.getManagedConnection(subject, cri);
assertEquals(1, cm.getPoolingStrategy().getInUseConnectionCount());
assertNotNull(cl);
cl.enlist();
assertNotNull(tm);
tm.commit();
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
cl = null;
}
finally
{
if (cl != null)
{
cm.returnManagedConnection(cl, true);
fail("ConnectionListener wasnt returned to the pool");
}
assertNotNull(tm);
if (TxUtils.isUncommitted(tm))
{
tm.rollback();
}
}
}
/**
* Test that a connection can be obtained from getManagedConnection
* and enlisted in a transaction that suffer timeout with track-by-tx enabled
* @exception Exception If an error occurs
*/
public void testGetManagedConnectionTimeoutTrackByTx() throws Exception
{
log.info("----------------------------------------");
log.info("testGetManagedConnectionTimeoutTrackByTx");
log.info("----------------------------------------");
// track-by-tx = true
cm.setTrackConnectionByTx(true);
ConnectionListener cl = null;
try
{
assertNotNull(tm);
tm.setTransactionTimeout(2);
tm.begin();
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
cl = cm.getManagedConnection(subject, cri);
assertEquals(1, cm.getPoolingStrategy().getInUseConnectionCount());
assertNotNull(cl);
cl.enlist();
Thread.sleep(2500L);
assertEquals(0, cm.getPoolingStrategy().getInUseConnectionCount());
cl = null;
}
finally
{
if (cl != null)
{
cm.returnManagedConnection(cl, true);
fail("ConnectionListener wasnt returned to the pool");
}
assertNotNull(tm);
if (!TxUtils.isCompleted(tm))
{
tm.rollback();
fail("Tx was still active");
}
}
}
/**
* Test a connection error
* @exception Exception If an error occurs
*/
public void testConnectionError() throws Exception
{
log.info("-------------------");
log.info("testConnectionError");
log.info("-------------------");
tm.begin();
TestConnection c = (TestConnection)cm.allocateConnection(mcf, cri);
c.fireConnectionError();
try
{
c.close();
}
catch (Exception ignored)
{
}
try
{
tm.commit();
fail("Should not be here");
}
catch (RollbackException expected)
{
}
assertTrue("Connection still enlisted in tx!", !c.isInTx());
}
/**
* Test a connection error with track-by-tx enabled
* @exception Exception If an error occurs
*/
public void testConnectionErrorTrackByTx() throws Exception
{
log.info("----------------------------");
log.info("testConnectionErrorTrackByTx");
log.info("----------------------------");
// track-by-tx = true
cm.setTrackConnectionByTx(true);
tm.begin();
TestConnection c = (TestConnection)cm.allocateConnection(mcf, cri);
c.fireConnectionError();
try
{
c.close();
}
catch (Exception ignored)
{
}
try
{
tm.commit();
fail("Should not be here");
}
catch (RollbackException expected)
{
}
assertTrue("Connection still enlisted in tx!", !c.isInTx());
}
/**
* Test a connection error
* @exception Exception If an error occurs
*/
public void testSimulateConnectionError() throws Exception
{
log.info("---------------------------");
log.info("testSimulateConnectionError");
log.info("---------------------------");
tm.begin();
TestConnection c = (TestConnection)cm.allocateConnection(mcf, cri);
try
{
c.simulateConnectionError();
fail("No exception thrown");
}
catch (Exception expected)
{
}
c.close();
try
{
tm.commit();
fail("Should not be here");
}
catch (RollbackException expected)
{
}
assertTrue("Connection still enlisted in tx!", !c.isInTx());
}
/**
* Test a connection error with track-by-tx enabled
* @exception Exception If an error occurs
*/
public void testSimulateConnectionErrorTrackByTx() throws Exception
{
log.info("------------------------------------");
log.info("testSimulateConnectionErrorTrackByTx");
log.info("------------------------------------");
// track-by-tx = true
cm.setTrackConnectionByTx(true);
tm.begin();
TestConnection c = (TestConnection)cm.allocateConnection(mcf, cri);
try
{
c.simulateConnectionError();
fail("No exception thrown");
}
catch (Exception expected)
{
}
c.close();
try
{
tm.commit();
fail("Should not be here");
}
catch (RollbackException expected)
{
}
assertTrue("Connection still enlisted in tx!", !c.isInTx());
}
}