/*
* Bitronix Transaction Manager
*
* Copyright (c) 2010, Bitronix Software.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package bitronix.tm.mock;
import java.io.*;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import javax.sql.XAConnection;
import javax.transaction.*;
import javax.transaction.xa.*;
import org.slf4j.*;
import bitronix.tm.*;
import bitronix.tm.mock.events.*;
import bitronix.tm.mock.resource.MockXAResource;
import bitronix.tm.mock.resource.jdbc.MockDriver;
import bitronix.tm.resource.common.XAPool;
import bitronix.tm.resource.jdbc.*;
import bitronix.tm.resource.jdbc.lrc.LrcXADataSource;
/**
*
* @author lorban
*/
public class NewJdbcProperUsageMockTest extends AbstractMockJdbcTest {
private final static Logger log = LoggerFactory.getLogger(NewJdbcProperUsageMockTest.class);
private static final int LOOPS = 2;
public void testSimpleWorkingCase() throws Exception {
Thread.currentThread().setName("testSimpleWorkingCase");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.setTransactionTimeout(10);
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(17, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testOrderedCommitResources() throws Exception {
Thread.currentThread().setName("testOrderedCommitResources");
poolingDataSource1.setTwoPcOrderingPosition(200);
poolingDataSource2.setTwoPcOrderingPosition(-1);
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.setTransactionTimeout(10);
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(17, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
XAResourcePrepareEvent prepareEvent1 = (XAResourcePrepareEvent) orderedEvents.get(i++);
assertEquals(XAResource.XA_OK, prepareEvent1.getReturnCode());
XAResourcePrepareEvent prepareEvent2 = (XAResourcePrepareEvent) orderedEvents.get(i++);
assertEquals(XAResource.XA_OK, prepareEvent2.getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
XAResourceCommitEvent commitEvent1 = (XAResourceCommitEvent) orderedEvents.get(i++);
assertTrue(prepareEvent2.getSource() == commitEvent1.getSource());
assertEquals(false, commitEvent1.isOnePhase());
XAResourceCommitEvent commitEvent2 = (XAResourceCommitEvent) orderedEvents.get(i++);
assertTrue(prepareEvent1.getSource() == commitEvent2.getSource());
assertEquals(false, commitEvent2.isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testReversePhase2Order() throws Exception {
Thread.currentThread().setName("testReversePhase2Order");
poolingDataSource1.setTwoPcOrderingPosition(1);
poolingDataSource2.setTwoPcOrderingPosition(1);
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.setTransactionTimeout(10);
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(17, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
XAResourcePrepareEvent prepareEvent1 = (XAResourcePrepareEvent) orderedEvents.get(i++);
assertEquals(XAResource.XA_OK, prepareEvent1.getReturnCode());
XAResourcePrepareEvent prepareEvent2 = (XAResourcePrepareEvent) orderedEvents.get(i++);
assertEquals(XAResource.XA_OK, prepareEvent2.getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
XAResourceCommitEvent commitEvent1 = (XAResourceCommitEvent) orderedEvents.get(i++);
assertTrue(prepareEvent2.getSource() == commitEvent1.getSource());
assertEquals(false, commitEvent1.isOnePhase());
XAResourceCommitEvent commitEvent2 = (XAResourceCommitEvent) orderedEvents.get(i++);
assertTrue(prepareEvent1.getSource() == commitEvent2.getSource());
assertEquals(false, commitEvent2.isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testLrc() throws Exception {
Thread.currentThread().setName("testLrc");
PoolingDataSource poolingDataSource2 = new PoolingDataSource();
poolingDataSource2.setClassName(LrcXADataSource.class.getName());
poolingDataSource2.setUniqueName(DATASOURCE2_NAME + "_lrc");
poolingDataSource2.setMinPoolSize(POOL_SIZE);
poolingDataSource2.setMaxPoolSize(POOL_SIZE);
poolingDataSource2.setAllowLocalTransactions(true);
poolingDataSource2.getDriverProperties().setProperty("driverClassName", MockDriver.class.getName());
poolingDataSource2.getDriverProperties().setProperty("user", "user");
poolingDataSource2.getDriverProperties().setProperty("password", "password");
poolingDataSource2.init();
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.setTransactionTimeout(10);
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 2");
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 1");
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(12, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(LocalCommitEvent.class, orderedEvents.get(i++).getClass());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testStatementTimeout() throws Exception {
Thread.currentThread().setName("testStatementTimeout");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.setTransactionTimeout(1);
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 1");
connection1.createStatement();
Thread.sleep(1500);
try {
if (log.isDebugEnabled()) log.debug("*** creating statement 2 on connection 1");
connection1.createStatement();
fail("expected transaction to time out");
} catch (SQLException ex) {
assertEquals("transaction timed out", ex.getCause().getMessage());
}
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** rolling back");
tm.rollback();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(9, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_MARKED_ROLLBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_ROLLING_BACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResourceRollbackEvent.class, orderedEvents.get(i++).getClass());
assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testCommitTimeout() throws Exception {
Thread.currentThread().setName("testCommitTimeout");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.setTransactionTimeout(1);
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** creating statement 1 on connection 1");
connection1.createStatement();
Thread.sleep(1500);
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** committing");
try {
tm.commit();
fail("expected transaction to time out");
} catch (RollbackException ex) {
assertEquals("transaction timed out and has been rolled back", ex.getMessage());
}
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(9, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_MARKED_ROLLBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_ROLLING_BACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResourceRollbackEvent.class, orderedEvents.get(i++).getClass());
assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testGlobalAfterLocal() throws Exception {
Thread.currentThread().setName("testGlobalAfterLocal");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1 in local ctx");
Connection connection1 = poolingDataSource1.getConnection();
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2 in local ctx");
Connection connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1 in global ctx");
connection1 = poolingDataSource1.getConnection();
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2 in global ctx");
connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(21, orderedEvents.size());
int i=0;
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testDeferredReleaseAfterMarkedRollback() throws Exception {
Thread.currentThread().setName("testDeferredReleaseAfterMarkedRollback");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** marking TX for rollback only");
tm.setRollbackOnly();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** rolling back");
tm.rollback();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(9, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_MARKED_ROLLBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_ROLLING_BACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResourceRollbackEvent.class, orderedEvents.get(i++).getClass());
assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testRollingBackSynchronization() throws Exception {
Thread.currentThread().setName("testRollingBackSynchronization");
if (log.isDebugEnabled()) log.debug("*** getting TM");
final BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
tm.getTransaction().registerSynchronization(new Synchronization() {
public void beforeCompletion() {
try {
if (log.isDebugEnabled()) log.debug("**** before setRollbackOnly");
tm.setRollbackOnly();
if (log.isDebugEnabled()) log.debug("**** after setRollbackOnly");
} catch (SystemException ex) {
throw new RuntimeException("could not setRollbackOnly", ex);
}
}
public void afterCompletion(int status) {
}
});
if (log.isDebugEnabled()) log.debug("*** after registerSynchronization");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
try {
tm.commit();
fail("transaction should not have been able to commit as it has been marked as rollback only");
} catch (RollbackException ex) {
assertEquals("transaction was marked as rollback only and has been rolled back", ex.getMessage());
}
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(14, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_MARKED_ROLLBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_ROLLING_BACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResourceRollbackEvent.class, orderedEvents.get(i++).getClass());
assertEquals(XAResourceRollbackEvent.class, orderedEvents.get(i++).getClass());
assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testSuspendResume() throws Exception {
Thread.currentThread().setName("testSuspendResume");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** suspending transaction");
Transaction tx = tm.suspend();
if (log.isDebugEnabled()) log.debug("*** resuming transaction");
tm.resume(tx);
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(23, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm());
assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(true, ((XAResourceIsSameRmEvent) orderedEvents.get(i++)).isSameRm());
assertEquals(XAResource.TMJOIN, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testLooseWorkingCaseOutsideOutside() throws Exception {
Thread.currentThread().setName("testLooseWorkingCaseOutsideOutside");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
connection1.createStatement();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(17, orderedEvents.size());
int i=0;
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testLooseWorkingCaseOutsideInside() throws Exception {
Thread.currentThread().setName("testLooseWorkingCaseOutsideInside");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
connection1.createStatement();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(17, orderedEvents.size());
int i=0;
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testLooseWorkingCaseInsideOutside() throws Exception {
Thread.currentThread().setName("testLooseWorkingCaseInsideOutside");
if (log.isDebugEnabled()) log.debug("*** getting TM");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** before begin");
tm.begin();
if (log.isDebugEnabled()) log.debug("*** after begin");
if (log.isDebugEnabled()) log.debug("*** getting connection from DS1");
Connection connection1 = poolingDataSource1.getConnection();
connection1.createStatement();
if (log.isDebugEnabled()) log.debug("*** getting connection from DS2");
Connection connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
if (log.isDebugEnabled()) log.debug("*** committing");
tm.commit();
if (log.isDebugEnabled()) log.debug("*** TX is done");
if (log.isDebugEnabled()) log.debug("*** closing connection 1");
connection1.close();
if (log.isDebugEnabled()) log.debug("*** closing connection 2");
connection2.close();
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(17, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i++)).isOnePhase());
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testHeuristicCommitWorkingCase() throws Exception {
Thread.currentThread().setName("testHeuristicCommitWorkingCase");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
tm.begin();
Connection connection1 = poolingDataSource1.getConnection();
PooledConnectionProxy handle = (PooledConnectionProxy) connection1;
JdbcPooledConnection pc1 = handle.getPooledConnection();
XAConnection mockXAConnection1 = (XAConnection) getWrappedXAConnectionOf(pc1);
MockXAResource mockXAResource = (MockXAResource) mockXAConnection1.getXAResource();
mockXAResource.setCommitException(new XAException(XAException.XA_HEURCOM));
connection1.createStatement();
Connection connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
connection1.close();
connection2.close();
tm.commit();
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(18, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_PREPARING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(XAResource.XA_OK, ((XAResourcePrepareEvent) orderedEvents.get(i++)).getReturnCode());
assertEquals(Status.STATUS_PREPARED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(Status.STATUS_COMMITTING, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
XAResourceCommitEvent event = ((XAResourceCommitEvent) orderedEvents.get(i++));
assertEquals(false, event.isOnePhase());
if (event.getException() != null) {
assertNotNull(orderedEvents.get(i++));
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i)).isOnePhase());
assertNull(((XAResourceCommitEvent) orderedEvents.get(i++)).getException());
}
else {
assertEquals(false, ((XAResourceCommitEvent) orderedEvents.get(i)).isOnePhase());
assertNotNull(((XAResourceCommitEvent) orderedEvents.get(i++)).getException());
assertNotNull(orderedEvents.get(i++));
}
assertEquals(Status.STATUS_COMMITTED, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testHeuristicRollbackWorkingCase() throws Exception {
Thread.currentThread().setName("testHeuristicRollbackWorkingCase");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
tm.begin();
Connection connection1 = poolingDataSource1.getConnection();
PooledConnectionProxy handle = (PooledConnectionProxy) connection1;
JdbcPooledConnection pc1 = handle.getPooledConnection();
XAConnection mockXAConnection1 = (XAConnection) getWrappedXAConnectionOf(pc1);
MockXAResource mockXAResource = (MockXAResource) mockXAConnection1.getXAResource();
mockXAResource.setRollbackException(new XAException(XAException.XA_HEURRB));
connection1.createStatement();
Connection connection2 = poolingDataSource2.getConnection();
connection2.createStatement();
connection1.close();
connection2.close();
tm.setTransactionTimeout(3);
tm.rollback();
// check flow
List orderedEvents = EventRecorder.getOrderedEvents();
log.info(EventRecorder.dumpToString());
assertEquals(14, orderedEvents.size());
int i=0;
assertEquals(Status.STATUS_ACTIVE, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(DATASOURCE2_NAME, ((ConnectionDequeuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(XAResource.TMNOFLAGS, ((XAResourceStartEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(XAResource.TMSUCCESS, ((XAResourceEndEvent) orderedEvents.get(i++)).getFlag());
assertEquals(Status.STATUS_ROLLING_BACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
XAResourceRollbackEvent event = ((XAResourceRollbackEvent) orderedEvents.get(i++));
assertNotNull(event);
if (event.getException() != null) {
assertNotNull(orderedEvents.get(i++));
assertNotNull(orderedEvents.get(i++));
}
else {
assertNotNull(orderedEvents.get(i));
assertNotNull(((XAResourceRollbackEvent) orderedEvents.get(i++)).getException());
assertNotNull(orderedEvents.get(i++));
}
assertEquals(Status.STATUS_ROLLEDBACK, ((JournalLogEvent) orderedEvents.get(i++)).getStatus());
assertEquals(DATASOURCE1_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
assertEquals(DATASOURCE2_NAME, ((ConnectionQueuedEvent) orderedEvents.get(i++)).getPooledConnectionImpl().getPoolingDataSource().getUniqueName());
}
public void testNonXaPool() throws Exception {
Thread.currentThread().setName("testNonXaPool");
for (int i=0; i<LOOPS ;i++) {
TransactionManagerServices.getTransactionManager().begin();
assertEquals(1, TransactionManagerServices.getTransactionManager().getInFlightTransactionCount());
assertEquals(0, ((BitronixTransaction)TransactionManagerServices.getTransactionManager().getTransaction()).getResourceManager().size());
Connection c = poolingDataSource1.getConnection();
c.createStatement();
c.close();
assertEquals(1, ((BitronixTransaction)TransactionManagerServices.getTransactionManager().getTransaction()).getResourceManager().size());
// rollback is necessary if deferConnectionRelease=true and to avoid nested TX
TransactionManagerServices.getTransactionManager().rollback();
assertEquals(0, TransactionManagerServices.getTransactionManager().getInFlightTransactionCount());
}
log.info(EventRecorder.dumpToString());
List events = EventRecorder.getOrderedEvents();
/* LOOPS * 9 events:
JournalLogEvent ACTIVE
ConnectionDequeuedEvent
XAResourceStartEvent
ConnectionCloseEvent
XAResourceEndEvent
JournalLogEvent ROLLINGBACK
XAResourceRollbackEvent
JournalLogEvent ROLLEDBACK
ConnectionQueuedEvent
*/
assertEquals(8 * LOOPS, events.size());
for (int i = 0; i < 8 * LOOPS; ) {
Event event;
event = (Event) events.get(i++);
assertEquals("at " + i, JournalLogEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, ConnectionDequeuedEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, XAResourceStartEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, XAResourceEndEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, JournalLogEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, XAResourceRollbackEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, JournalLogEvent.class, event.getClass());
event = (Event) events.get(i++);
assertEquals("at " + i, ConnectionQueuedEvent.class, event.getClass());
}
}
public void testDuplicateClose() throws Exception {
Thread.currentThread().setName("testDuplicateClose");
Field poolField = poolingDataSource1.getClass().getDeclaredField("pool");
poolField.setAccessible(true);
XAPool pool = (XAPool) poolField.get(poolingDataSource1);
assertEquals(POOL_SIZE, pool.inPoolSize());
if (log.isDebugEnabled()) log.debug(" *** getting connection");
Connection c = poolingDataSource1.getConnection();
assertEquals(POOL_SIZE -1, pool.inPoolSize());
if (log.isDebugEnabled()) log.debug(" *** closing once");
c.close();
assertEquals(POOL_SIZE, pool.inPoolSize());
if (log.isDebugEnabled()) log.debug(" *** closing twice");
c.close();
assertEquals(POOL_SIZE, pool.inPoolSize());
if (log.isDebugEnabled()) log.debug(" *** checking pool size");
Connection c1 = poolingDataSource1.getConnection();
Connection c2 = poolingDataSource1.getConnection();
Connection c3 = poolingDataSource1.getConnection();
Connection c4 = poolingDataSource1.getConnection();
Connection c5 = poolingDataSource1.getConnection();
assertEquals(POOL_SIZE -5, pool.inPoolSize());
c1.close();
c2.close();
c3.close();
c4.close();
c5.close();
assertEquals(POOL_SIZE, pool.inPoolSize());
if (log.isDebugEnabled()) log.debug(" *** done");
}
public void testPoolBoundsWithLooseEnlistment() throws Exception {
Thread.currentThread().setName("testPoolBoundsWithLooseEnlistment");
ArrayList list = new ArrayList();
for (int i=0; i<LOOPS ;i++) {
Thread t = new LooseTransactionThread(i, poolingDataSource1);
list.add(t);
t.start();
}
for (int i = 0; i < list.size(); i++) {
LooseTransactionThread thread = (LooseTransactionThread) list.get(i);
thread.join(5000);
if (!thread.isSuccesful())
log.info("thread " + thread.getNumber() + " failed");
}
assertEquals(LOOPS, LooseTransactionThread.successes);
assertEquals(0, LooseTransactionThread.failures);
LooseTransactionThread thread = new LooseTransactionThread(-1, poolingDataSource1);
thread.run();
assertTrue(thread.isSuccesful());
}
static class LooseTransactionThread extends Thread {
static int successes = 0;
static int failures = 0;
private int number;
private PoolingDataSource poolingDataSource;
private boolean succesful = false;
public LooseTransactionThread(int number, PoolingDataSource poolingDataSource) {
this.number = number;
this.poolingDataSource = poolingDataSource;
}
public void run() {
try {
UserTransaction ut = TransactionManagerServices.getTransactionManager();
if (log.isDebugEnabled()) log.debug("*** getting connection - " + number);
Connection c1 = poolingDataSource.getConnection();
if (log.isDebugEnabled()) log.debug("*** beginning the transaction - " + number);
ut.begin();
c1.prepareStatement("");
if (log.isDebugEnabled()) log.debug("*** committing the transaction - " + number);
ut.commit();
if (log.isDebugEnabled()) log.debug("*** closing connection - " + number);
c1.close();
if (log.isDebugEnabled()) log.debug("*** all done - " + number);
synchronized (LooseTransactionThread.class) {
successes++;
}
succesful = true;
} catch (Exception ex) {
log.warn("*** catched exception, waiting 500ms - " + number, ex);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// ignore
}
if (log.isDebugEnabled()) log.debug("*** catched exception, waited 500ms - " + number, ex);
synchronized (LooseTransactionThread.class) {
failures++;
}
}
} // run
public int getNumber() {
return number;
}
public boolean isSuccesful() {
return succesful;
}
}
public void testNonEnlistingMethodInTxContext() throws Exception {
Thread.currentThread().setName("testNonEnlistingMethodInTxContext");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
tm.begin();
Connection c = poolingDataSource1.getConnection();
assertTrue(c.getAutoCommit());
c.close();
tm.commit();
tm.shutdown();
}
public void testAutoCommitFalseWhenEnlisted() throws Exception {
Thread.currentThread().setName("testAutoCommitFalseWhenEnlisted");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
tm.begin();
Connection c = poolingDataSource1.getConnection();
c.prepareStatement("");
assertFalse(c.getAutoCommit());
c.close();
tm.commit();
tm.shutdown();
}
public void testAutoCommitTrueWhenEnlistedButSuspended() throws Exception {
Thread.currentThread().setName("testAutoCommitTrueWhenEnlistedButSuspended");
BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
tm.begin();
Connection c = poolingDataSource1.getConnection();
c.prepareStatement("");
Transaction tx = tm.suspend();
assertNull(tm.getTransaction());
assertTrue(c.getAutoCommit());
tm.resume(tx);
c.close();
tm.commit();
tm.shutdown();
}
public void testSerialization() throws Exception {
Thread.currentThread().setName("testSerialization");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(poolingDataSource1);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
poolingDataSource1 = (PoolingDataSource) ois.readObject();
ois.close();
}
}