Isolate the transaction managers between the primary environment and the second node environment
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@14364 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
5414f6bf99
commit
e73589d1bc
|
@ -29,7 +29,6 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.cfg.Mappings;
|
import org.hibernate.cfg.Mappings;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||||
import org.hibernate.transaction.CMTTransactionFactory;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -68,9 +67,9 @@ public abstract class CacheTestCaseBase extends FunctionalTestCase {
|
||||||
cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
|
cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
|
||||||
|
|
||||||
cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
|
cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
|
||||||
cfg.setProperty(Environment.CONNECTION_PROVIDER, org.hibernate.test.tm.ConnectionProviderImpl.class.getName());
|
cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
|
||||||
cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, org.hibernate.test.tm.TransactionManagerLookupImpl.class.getName());
|
cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
|
||||||
cfg.setProperty( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() );
|
// cfg.setProperty( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() );
|
||||||
|
|
||||||
configureCacheFactory(cfg);
|
configureCacheFactory(cfg);
|
||||||
}
|
}
|
||||||
|
@ -89,6 +88,14 @@ public abstract class CacheTestCaseBase extends FunctionalTestCase {
|
||||||
protected abstract Class<? extends RegionFactory> getCacheRegionFactory();
|
protected abstract Class<? extends RegionFactory> getCacheRegionFactory();
|
||||||
|
|
||||||
protected abstract boolean getUseQueryCache();
|
protected abstract boolean getUseQueryCache();
|
||||||
|
|
||||||
|
protected Class getConnectionProviderClass() {
|
||||||
|
return org.hibernate.test.tm.ConnectionProviderImpl.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class getTransactionManagerLookupClass() {
|
||||||
|
return org.hibernate.test.tm.TransactionManagerLookupImpl.class;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) {
|
public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) {
|
||||||
|
|
|
@ -22,6 +22,10 @@ import org.hibernate.cfg.Mappings;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.junit.functional.ExecutionEnvironment;
|
import org.hibernate.junit.functional.ExecutionEnvironment;
|
||||||
|
import org.hibernate.test.cache.jbc2.functional.util.DualNodeConnectionProviderImpl;
|
||||||
|
import org.hibernate.test.cache.jbc2.functional.util.DualNodeTestUtil;
|
||||||
|
import org.hibernate.test.cache.jbc2.functional.util.DualNodeTransactionManagerLookup;
|
||||||
|
import org.hibernate.test.cache.jbc2.functional.util.TestCacheInstanceManager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -35,6 +39,8 @@ public abstract class DualNodeTestCaseBase extends CacheTestCaseBase
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger( CacheTestCaseBase.class );
|
private static final Logger log = LoggerFactory.getLogger( CacheTestCaseBase.class );
|
||||||
|
|
||||||
|
public static final String CACHE_MANAGER_NAME_PROP = "hibernate.test.cluster.node.id";
|
||||||
|
|
||||||
private ExecutionEnvironment secondNodeEnvironment;
|
private ExecutionEnvironment secondNodeEnvironment;
|
||||||
private org.hibernate.classic.Session secondNodeSession;
|
private org.hibernate.classic.Session secondNodeSession;
|
||||||
|
|
||||||
|
@ -64,14 +70,31 @@ public abstract class DualNodeTestCaseBase extends CacheTestCaseBase
|
||||||
*
|
*
|
||||||
* @param the Configuration to update.
|
* @param the Configuration to update.
|
||||||
*/
|
*/
|
||||||
protected abstract void configureFirstNode(Configuration cfg);
|
protected void configureFirstNode(Configuration cfg)
|
||||||
|
{
|
||||||
|
cfg.setProperty(DualNodeTestUtil.NODE_ID_PROP,
|
||||||
|
DualNodeTestUtil.LOCAL);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Apply any node-specific configurations to our second node.
|
* Apply any node-specific configurations to our second node.
|
||||||
*
|
*
|
||||||
* @param the Configuration to update.
|
* @param the Configuration to update.
|
||||||
*/
|
*/
|
||||||
protected abstract void configureSecondNode(Configuration cfg);
|
protected void configureSecondNode(Configuration cfg)
|
||||||
|
{
|
||||||
|
cfg.setProperty(DualNodeTestUtil.NODE_ID_PROP,
|
||||||
|
DualNodeTestUtil.REMOTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class getConnectionProviderClass() {
|
||||||
|
return DualNodeConnectionProviderImpl.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class getTransactionManagerLookupClass() {
|
||||||
|
return DualNodeTransactionManagerLookup.class;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareTest() throws Exception
|
protected void prepareTest() throws Exception
|
||||||
|
|
|
@ -34,8 +34,11 @@ import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.cache.RegionFactory;
|
import org.hibernate.cache.RegionFactory;
|
||||||
import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
|
import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.test.cache.jbc2.functional.util.DualNodeTestUtil;
|
||||||
import org.hibernate.test.cache.jbc2.functional.util.TestCacheInstanceManager;
|
import org.hibernate.test.cache.jbc2.functional.util.TestCacheInstanceManager;
|
||||||
import org.hibernate.test.cache.jbc2.functional.util.TestJBossCacheRegionFactory;
|
import org.hibernate.test.cache.jbc2.functional.util.TestJBossCacheRegionFactory;
|
||||||
|
import org.hibernate.transaction.CMTTransactionFactory;
|
||||||
import org.jboss.cache.Cache;
|
import org.jboss.cache.Cache;
|
||||||
import org.jboss.cache.CacheManager;
|
import org.jboss.cache.CacheManager;
|
||||||
import org.jboss.cache.Fqn;
|
import org.jboss.cache.Fqn;
|
||||||
|
@ -55,10 +58,7 @@ extends DualNodeTestCaseBase
|
||||||
{
|
{
|
||||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private static final long SLEEP_TIME = 100l;
|
private static final long SLEEP_TIME = 50l;
|
||||||
|
|
||||||
private static final String LOCAL = "local";
|
|
||||||
private static final String REMOTE = "remote";
|
|
||||||
|
|
||||||
private static final Integer CUSTOMER_ID = new Integer(1);
|
private static final Integer CUSTOMER_ID = new Integer(1);
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ extends DualNodeTestCaseBase
|
||||||
@Override
|
@Override
|
||||||
public void configure(Configuration cfg)
|
public void configure(Configuration cfg)
|
||||||
{
|
{
|
||||||
|
cfg.setProperty( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() );
|
||||||
super.configure(cfg);
|
super.configure(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,20 +98,6 @@ extends DualNodeTestCaseBase
|
||||||
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP,
|
cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP,
|
||||||
getEntityCacheConfigName());
|
getEntityCacheConfigName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureFirstNode(Configuration cfg)
|
|
||||||
{
|
|
||||||
cfg.setProperty(TestCacheInstanceManager.CACHE_MANAGER_NAME_PROP,
|
|
||||||
LOCAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureSecondNode(Configuration cfg)
|
|
||||||
{
|
|
||||||
cfg.setProperty(TestCacheInstanceManager.CACHE_MANAGER_NAME_PROP,
|
|
||||||
REMOTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getEntityCacheConfigName() {
|
protected String getEntityCacheConfigName() {
|
||||||
return "pessimistic-shared";
|
return "pessimistic-shared";
|
||||||
|
@ -123,7 +110,7 @@ extends DualNodeTestCaseBase
|
||||||
|
|
||||||
// Bind a listener to the "local" cache
|
// Bind a listener to the "local" cache
|
||||||
// Our region factory makes its CacheManager available to us
|
// Our region factory makes its CacheManager available to us
|
||||||
CacheManager localManager = TestCacheInstanceManager.getTestCacheManager(LOCAL);
|
CacheManager localManager = TestCacheInstanceManager.getTestCacheManager(DualNodeTestUtil.LOCAL);
|
||||||
Cache localCache = localManager.getCache(getEntityCacheConfigName(), true);
|
Cache localCache = localManager.getCache(getEntityCacheConfigName(), true);
|
||||||
MyListener localListener = new MyListener();
|
MyListener localListener = new MyListener();
|
||||||
localCache.addCacheListener(localListener);
|
localCache.addCacheListener(localListener);
|
||||||
|
@ -131,7 +118,7 @@ extends DualNodeTestCaseBase
|
||||||
TransactionManager localTM = localCache.getConfiguration().getRuntimeConfig().getTransactionManager();
|
TransactionManager localTM = localCache.getConfiguration().getRuntimeConfig().getTransactionManager();
|
||||||
|
|
||||||
// Bind a listener to the "remote" cache
|
// Bind a listener to the "remote" cache
|
||||||
CacheManager remoteManager = TestCacheInstanceManager.getTestCacheManager(REMOTE);
|
CacheManager remoteManager = TestCacheInstanceManager.getTestCacheManager(DualNodeTestUtil.REMOTE);
|
||||||
Cache remoteCache = remoteManager.getCache(getEntityCacheConfigName(), true);
|
Cache remoteCache = remoteManager.getCache(getEntityCacheConfigName(), true);
|
||||||
MyListener remoteListener = new MyListener();
|
MyListener remoteListener = new MyListener();
|
||||||
remoteCache.addCacheListener(remoteListener);
|
remoteCache.addCacheListener(remoteListener);
|
||||||
|
@ -154,7 +141,9 @@ extends DualNodeTestCaseBase
|
||||||
// This actually brings the collection into the cache
|
// This actually brings the collection into the cache
|
||||||
getCustomer(ids.customerId, localFactory, localTM);
|
getCustomer(ids.customerId, localFactory, localTM);
|
||||||
|
|
||||||
// Now the collection is in the cache so, we the 2nd "get"
|
sleep(SLEEP_TIME);
|
||||||
|
|
||||||
|
// Now the collection is in the cache so, the 2nd "get"
|
||||||
// should read everything from the cache
|
// should read everything from the cache
|
||||||
System.out.println("Find(2) node 0");
|
System.out.println("Find(2) node 0");
|
||||||
localListener.clear();
|
localListener.clear();
|
||||||
|
@ -163,10 +152,6 @@ extends DualNodeTestCaseBase
|
||||||
//Check the read came from the cache
|
//Check the read came from the cache
|
||||||
System.out.println("Check cache 0");
|
System.out.println("Check cache 0");
|
||||||
assertLoadedFromCache(localListener, ids.customerId, ids.contactIds);
|
assertLoadedFromCache(localListener, ids.customerId, ids.contactIds);
|
||||||
|
|
||||||
// The above placement of the collection in the cache is replicated async
|
|
||||||
// so pause a bit before checking node 1
|
|
||||||
sleep(SLEEP_TIME);
|
|
||||||
|
|
||||||
System.out.println("Find node 1");
|
System.out.println("Find node 1");
|
||||||
getCustomer(ids.customerId, remoteFactory, remoteTM);
|
getCustomer(ids.customerId, remoteFactory, remoteTM);
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* 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 org.hibernate.test.cache.jbc2.functional.util;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.connection.ConnectionProvider;
|
||||||
|
import org.hibernate.connection.ConnectionProviderFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ConnectionProvider} implementation adding JTA-style transactionality
|
||||||
|
* around the returned connections using the {@link DualNodeJtaTransactionManagerImpl}.
|
||||||
|
*
|
||||||
|
* @author Brian Stansberry
|
||||||
|
*/
|
||||||
|
public class DualNodeConnectionProviderImpl implements ConnectionProvider {
|
||||||
|
private static ConnectionProvider actualConnectionProvider = ConnectionProviderFactory.newConnectionProvider();
|
||||||
|
|
||||||
|
private String nodeId;
|
||||||
|
private boolean isTransactional;
|
||||||
|
|
||||||
|
public static ConnectionProvider getActualConnectionProvider() {
|
||||||
|
return actualConnectionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configure(Properties props) throws HibernateException {
|
||||||
|
nodeId = props.getProperty(DualNodeTestUtil.NODE_ID_PROP);
|
||||||
|
if (nodeId == null)
|
||||||
|
throw new HibernateException(DualNodeTestUtil.NODE_ID_PROP + " not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection getConnection() throws SQLException {
|
||||||
|
DualNodeJtaTransactionImpl currentTransaction = DualNodeJtaTransactionManagerImpl.getInstance(nodeId).getCurrentTransaction();
|
||||||
|
if ( currentTransaction == null ) {
|
||||||
|
isTransactional = false;
|
||||||
|
return actualConnectionProvider.getConnection();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isTransactional = true;
|
||||||
|
Connection connection = currentTransaction.getEnlistedConnection();
|
||||||
|
if ( connection == null ) {
|
||||||
|
connection = actualConnectionProvider.getConnection();
|
||||||
|
currentTransaction.enlistConnection( connection );
|
||||||
|
}
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeConnection(Connection conn) throws SQLException {
|
||||||
|
if ( !isTransactional ) {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws HibernateException {
|
||||||
|
actualConnectionProvider.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsAggressiveRelease() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* 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 org.hibernate.test.cache.jbc2.functional.util;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import javax.transaction.HeuristicMixedException;
|
||||||
|
import javax.transaction.HeuristicRollbackException;
|
||||||
|
import javax.transaction.RollbackException;
|
||||||
|
import javax.transaction.Status;
|
||||||
|
import javax.transaction.Synchronization;
|
||||||
|
import javax.transaction.SystemException;
|
||||||
|
import javax.transaction.Transaction;
|
||||||
|
import javax.transaction.xa.XAResource;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SimpleJtaTransactionImpl variant that works with DualNodeTransactionManagerImpl.
|
||||||
|
*
|
||||||
|
* @author Brian Stansberry
|
||||||
|
*/
|
||||||
|
public class DualNodeJtaTransactionImpl implements Transaction {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger( DualNodeJtaTransactionImpl.class );
|
||||||
|
|
||||||
|
private int status;
|
||||||
|
private LinkedList synchronizations;
|
||||||
|
private Connection connection; // the only resource we care about is jdbc connection
|
||||||
|
private final DualNodeJtaTransactionManagerImpl jtaTransactionManager;
|
||||||
|
|
||||||
|
public DualNodeJtaTransactionImpl(DualNodeJtaTransactionManagerImpl jtaTransactionManager) {
|
||||||
|
this.jtaTransactionManager = jtaTransactionManager;
|
||||||
|
this.status = Status.STATUS_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit()
|
||||||
|
throws RollbackException, HeuristicMixedException, HeuristicRollbackException, IllegalStateException, SystemException {
|
||||||
|
|
||||||
|
if ( status == Status.STATUS_MARKED_ROLLBACK ) {
|
||||||
|
log.trace( "on commit, status was marked for rollback-only" );
|
||||||
|
rollback();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = Status.STATUS_PREPARING;
|
||||||
|
|
||||||
|
for ( int i = 0; i < synchronizations.size(); i++ ) {
|
||||||
|
Synchronization s = ( Synchronization ) synchronizations.get( i );
|
||||||
|
s.beforeCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Status.STATUS_COMMITTING;
|
||||||
|
|
||||||
|
if ( connection != null ) {
|
||||||
|
try {
|
||||||
|
connection.commit();
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
catch ( SQLException sqle ) {
|
||||||
|
status = Status.STATUS_UNKNOWN;
|
||||||
|
throw new SystemException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Status.STATUS_COMMITTED;
|
||||||
|
|
||||||
|
for ( int i = 0; i < synchronizations.size(); i++ ) {
|
||||||
|
Synchronization s = ( Synchronization ) synchronizations.get( i );
|
||||||
|
s.afterCompletion( status );
|
||||||
|
}
|
||||||
|
|
||||||
|
//status = Status.STATUS_NO_TRANSACTION;
|
||||||
|
jtaTransactionManager.endCurrent( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rollback() throws IllegalStateException, SystemException {
|
||||||
|
status = Status.STATUS_ROLLEDBACK;
|
||||||
|
|
||||||
|
if ( connection != null ) {
|
||||||
|
try {
|
||||||
|
connection.rollback();
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
catch ( SQLException sqle ) {
|
||||||
|
status = Status.STATUS_UNKNOWN;
|
||||||
|
throw new SystemException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < synchronizations.size(); i++ ) {
|
||||||
|
Synchronization s = ( Synchronization ) synchronizations.get( i );
|
||||||
|
s.afterCompletion( status );
|
||||||
|
}
|
||||||
|
|
||||||
|
//status = Status.STATUS_NO_TRANSACTION;
|
||||||
|
jtaTransactionManager.endCurrent( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRollbackOnly() throws IllegalStateException, SystemException {
|
||||||
|
status = Status.STATUS_MARKED_ROLLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerSynchronization(Synchronization synchronization)
|
||||||
|
throws RollbackException, IllegalStateException, SystemException {
|
||||||
|
// todo : find the spec-allowable statuses during which synch can be registered...
|
||||||
|
if ( synchronizations == null ) {
|
||||||
|
synchronizations = new LinkedList();
|
||||||
|
}
|
||||||
|
synchronizations.add( synchronization );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enlistConnection(Connection connection) {
|
||||||
|
if ( this.connection != null ) {
|
||||||
|
throw new IllegalStateException( "Connection already registered" );
|
||||||
|
}
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection getEnlistedConnection() {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean enlistResource(XAResource xaResource)
|
||||||
|
throws RollbackException, IllegalStateException, SystemException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* 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 org.hibernate.test.cache.jbc2.functional.util;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import javax.transaction.HeuristicMixedException;
|
||||||
|
import javax.transaction.HeuristicRollbackException;
|
||||||
|
import javax.transaction.InvalidTransactionException;
|
||||||
|
import javax.transaction.NotSupportedException;
|
||||||
|
import javax.transaction.RollbackException;
|
||||||
|
import javax.transaction.Status;
|
||||||
|
import javax.transaction.SystemException;
|
||||||
|
import javax.transaction.Transaction;
|
||||||
|
import javax.transaction.TransactionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant of SimpleJtaTransactionManagerImpl that doesn't use a VM-singleton,
|
||||||
|
* but rather a set of impls keyed by a node id.
|
||||||
|
*
|
||||||
|
* @author Brian Stansberry
|
||||||
|
*/
|
||||||
|
public class DualNodeJtaTransactionManagerImpl implements TransactionManager {
|
||||||
|
private static final Hashtable INSTANCES = new Hashtable();
|
||||||
|
|
||||||
|
private DualNodeJtaTransactionImpl currentTransaction;
|
||||||
|
|
||||||
|
public synchronized static DualNodeJtaTransactionManagerImpl getInstance(String nodeId) {
|
||||||
|
DualNodeJtaTransactionManagerImpl tm = (DualNodeJtaTransactionManagerImpl) INSTANCES.get(nodeId);
|
||||||
|
if (tm == null) {
|
||||||
|
tm = new DualNodeJtaTransactionManagerImpl();
|
||||||
|
INSTANCES.put(nodeId, tm);
|
||||||
|
}
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() throws SystemException {
|
||||||
|
return currentTransaction == null ? Status.STATUS_NO_TRANSACTION : currentTransaction.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transaction getTransaction() throws SystemException {
|
||||||
|
return currentTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DualNodeJtaTransactionImpl getCurrentTransaction() {
|
||||||
|
return currentTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void begin() throws NotSupportedException, SystemException {
|
||||||
|
currentTransaction = new DualNodeJtaTransactionImpl( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transaction suspend() throws SystemException {
|
||||||
|
DualNodeJtaTransactionImpl suspended = currentTransaction;
|
||||||
|
currentTransaction = null;
|
||||||
|
return suspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resume(Transaction transaction)
|
||||||
|
throws InvalidTransactionException, IllegalStateException, SystemException {
|
||||||
|
currentTransaction = ( DualNodeJtaTransactionImpl ) transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit()
|
||||||
|
throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
|
||||||
|
if ( currentTransaction == null ) {
|
||||||
|
throw new IllegalStateException( "no current transaction to commit" );
|
||||||
|
}
|
||||||
|
currentTransaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rollback() throws IllegalStateException, SecurityException, SystemException {
|
||||||
|
if ( currentTransaction == null ) {
|
||||||
|
throw new IllegalStateException( "no current transaction" );
|
||||||
|
}
|
||||||
|
currentTransaction.rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRollbackOnly() throws IllegalStateException, SystemException {
|
||||||
|
if ( currentTransaction == null ) {
|
||||||
|
throw new IllegalStateException( "no current transaction" );
|
||||||
|
}
|
||||||
|
currentTransaction.setRollbackOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransactionTimeout(int i) throws SystemException {
|
||||||
|
}
|
||||||
|
|
||||||
|
void endCurrent(DualNodeJtaTransactionImpl transaction) {
|
||||||
|
if ( transaction == currentTransaction ) {
|
||||||
|
currentTransaction = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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, v. 2.1. This program is distributed in the
|
||||||
|
* hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
|
||||||
|
* distribution; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Brian Stansberry
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.test.cache.jbc2.functional.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DualNodeTestUtil.
|
||||||
|
*
|
||||||
|
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class DualNodeTestUtil
|
||||||
|
{
|
||||||
|
public static final String NODE_ID_PROP = "hibernate.test.cluster.node.id";
|
||||||
|
|
||||||
|
public static final String LOCAL = "local";
|
||||||
|
public static final String REMOTE = "remote";
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* 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 org.hibernate.test.cache.jbc2.functional.util;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import javax.transaction.TransactionManager;
|
||||||
|
|
||||||
|
import org.hibernate.transaction.TransactionManagerLookup;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SimpleJtaTransactionManagerLookupImpl subclass that finds a different
|
||||||
|
* DualNodeTransactionManager based on the value of property
|
||||||
|
* {@link DualNodeTestUtil#NODE_ID_PROP}.
|
||||||
|
*
|
||||||
|
* @author Brian Stansberry
|
||||||
|
*/
|
||||||
|
public class DualNodeTransactionManagerLookup implements TransactionManagerLookup {
|
||||||
|
|
||||||
|
public TransactionManager getTransactionManager(Properties props) throws HibernateException {
|
||||||
|
String nodeId = props.getProperty(DualNodeTestUtil.NODE_ID_PROP);
|
||||||
|
if (nodeId == null)
|
||||||
|
throw new HibernateException(DualNodeTestUtil.NODE_ID_PROP + " not configured");
|
||||||
|
return DualNodeJtaTransactionManagerImpl.getInstance(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserTransactionName() {
|
||||||
|
throw new UnsupportedOperationException( "jndi currently not implemented for these tests" );
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,8 +43,6 @@ public class TestCacheInstanceManager extends MultiplexingCacheInstanceManager {
|
||||||
|
|
||||||
private static final Hashtable cacheManagers = new Hashtable();
|
private static final Hashtable cacheManagers = new Hashtable();
|
||||||
|
|
||||||
public static final String CACHE_MANAGER_NAME_PROP = "hibernate.test.cache.jbc2.cache.manager.name";
|
|
||||||
|
|
||||||
public static CacheManager getTestCacheManager(String name) {
|
public static CacheManager getTestCacheManager(String name) {
|
||||||
return (CacheManager) cacheManagers.get(name);
|
return (CacheManager) cacheManagers.get(name);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +61,7 @@ public class TestCacheInstanceManager extends MultiplexingCacheInstanceManager {
|
||||||
|
|
||||||
super.start(settings, properties);
|
super.start(settings, properties);
|
||||||
|
|
||||||
cacheManagerName = properties.getProperty(CACHE_MANAGER_NAME_PROP);
|
cacheManagerName = properties.getProperty(DualNodeTestUtil.NODE_ID_PROP);
|
||||||
cacheManagers.put(cacheManagerName, getCacheFactory());
|
cacheManagers.put(cacheManagerName, getCacheFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue