Fix classloader isolation tests

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@14494 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Brian Stansberry 2008-04-03 19:38:24 +00:00
parent b3428358b7
commit 2052b06d53
7 changed files with 135 additions and 43 deletions

View File

@ -85,6 +85,11 @@ public abstract class BasicRegionAdapter implements Region {
protected abstract Fqn<String> createRegionFqn(String regionName, String regionPrefix); protected abstract Fqn<String> createRegionFqn(String regionName, String regionPrefix);
protected void activateLocalClusterNode() { protected void activateLocalClusterNode() {
// Regions can get instantiated in the course of normal work (e.g.
// a named query region will be created the first time the query is
// executed), so suspend any ongoing tx
Transaction tx = suspend();
try { try {
Configuration cfg = jbcCache.getConfiguration(); Configuration cfg = jbcCache.getConfiguration();
if (cfg.isUseRegionBasedMarshalling()) { if (cfg.isUseRegionBasedMarshalling()) {
@ -128,6 +133,11 @@ public abstract class BasicRegionAdapter implements Region {
catch (Exception e) { catch (Exception e) {
throw new CacheException(e.getMessage(), e); throw new CacheException(e.getMessage(), e);
} }
finally {
if (tx != null)
resume(tx);
}
} }
private void establishRegionRootNode() private void establishRegionRootNode()

View File

@ -16,9 +16,6 @@
package org.hibernate.test.cache.jbc2.functional; package org.hibernate.test.cache.jbc2.functional;
import javax.transaction.TransactionManager;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Mappings; import org.hibernate.cfg.Mappings;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
@ -28,7 +25,6 @@ import org.hibernate.test.cache.jbc2.functional.util.DualNodeConnectionProviderI
import org.hibernate.test.cache.jbc2.functional.util.DualNodeJtaTransactionManagerImpl; import org.hibernate.test.cache.jbc2.functional.util.DualNodeJtaTransactionManagerImpl;
import org.hibernate.test.cache.jbc2.functional.util.DualNodeTestUtil; 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.DualNodeTransactionManagerLookup;
import org.hibernate.test.cache.jbc2.functional.util.TestCacheInstanceManager;
import org.hibernate.transaction.CMTTransactionFactory; import org.hibernate.transaction.CMTTransactionFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -212,6 +212,10 @@ public class ClassLoaderTestDAO
try { try {
Query query = sessionFactory.getCurrentSession().createQuery("select account.balance from Account as account where account.accountHolder = ?"); Query query = sessionFactory.getCurrentSession().createQuery("select account.balance from Account as account where account.accountHolder = ?");
query.setParameter(0, holder); query.setParameter(0, holder);
if (useRegion)
{
query.setCacheRegion("AccountRegion");
}
query.setCacheable(true); query.setCacheable(true);
results = query.list(); results = query.list();
tm.commit(); tm.commit();

View File

@ -73,6 +73,12 @@ extends DualNodeTestCaseBase
static int test = 0; static int test = 0;
private Cache localCache;
private CacheAccessListener localListener;
private Cache remoteCache;
private CacheAccessListener remoteListener;
public PessimisticIsolatedClassLoaderTest(String name) public PessimisticIsolatedClassLoaderTest(String name)
{ {
super(name); super(name);
@ -122,6 +128,22 @@ extends DualNodeTestCaseBase
DualNodeJtaTransactionManagerImpl.cleanupTransactions(); DualNodeJtaTransactionManagerImpl.cleanupTransactions();
} }
@Override
protected void cleanupTest() throws Exception
{
try
{
if (localCache != null && localListener != null)
localCache.removeCacheListener(localListener);
if (remoteCache != null && remoteListener != null)
remoteCache.removeCacheListener(remoteListener);
}
finally
{
super.cleanupTest();
}
}
/** /**
* Simply confirms that the test fixture's classloader isolation setup * Simply confirms that the test fixture's classloader isolation setup
* is functioning as expected. * is functioning as expected.
@ -145,9 +167,11 @@ extends DualNodeTestCaseBase
org.jboss.cache.Fqn fqn = org.jboss.cache.Fqn.fromString("/isolated1"); org.jboss.cache.Fqn fqn = org.jboss.cache.Fqn.fromString("/isolated1");
org.jboss.cache.Region r = localCache.getRegion(fqn, true); org.jboss.cache.Region r = localCache.getRegion(fqn, true);
r.registerContextClassLoader(cl.getParent());
r.activate(); r.activate();
r = remoteCache.getRegion(fqn, true); r = remoteCache.getRegion(fqn, true);
r.registerContextClassLoader(cl.getParent());
r.activate(); r.activate();
Thread.currentThread().setContextClassLoader(cl); Thread.currentThread().setContextClassLoader(cl);
Account acct = new Account(); Account acct = new Account();
@ -182,16 +206,16 @@ 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(DualNodeTestUtil.LOCAL); CacheManager localManager = TestCacheInstanceManager.getTestCacheManager(DualNodeTestUtil.LOCAL);
Cache localCache = localManager.getCache(getEntityCacheConfigName(), true); this.localCache = localManager.getCache(getEntityCacheConfigName(), true);
CacheAccessListener localListener = new CacheAccessListener(); this.localListener = new CacheAccessListener();
localCache.addCacheListener(localListener); localCache.addCacheListener(localListener);
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(DualNodeTestUtil.REMOTE); CacheManager remoteManager = TestCacheInstanceManager.getTestCacheManager(DualNodeTestUtil.REMOTE);
Cache remoteCache = remoteManager.getCache(getEntityCacheConfigName(), true); this.remoteCache = remoteManager.getCache(getEntityCacheConfigName(), true);
CacheAccessListener remoteListener = new CacheAccessListener(); this.remoteListener = new CacheAccessListener();
remoteCache.addCacheListener(remoteListener); remoteCache.addCacheListener(remoteListener);
TransactionManager remoteTM = remoteCache.getConfiguration().getRuntimeConfig().getTransactionManager(); TransactionManager remoteTM = remoteCache.getConfiguration().getRuntimeConfig().getTransactionManager();

View File

@ -0,0 +1,60 @@
/*
* 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;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheManagerImpl;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.config.Configuration;
import org.jgroups.ChannelFactory;
/**
* CacheManager implementation that lets us set a default ClassLoader
* on the created cache.
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 1 $
*/
public class CustomClassLoaderCacheManager extends CacheManagerImpl
{
private final ClassLoader defaultClassLoader;
/**
* Create a new CustomClassLoaderCacheManager.
*
* @param configFileName
* @param factory
*/
public CustomClassLoaderCacheManager(String configFileName,
ChannelFactory factory,
ClassLoader defaultClassLoader)
{
super(configFileName, factory);
this.defaultClassLoader = defaultClassLoader;
}
@Override
protected Cache<Object, Object> createCache(Configuration config)
{
DefaultCacheFactory<Object, Object> factory = new DefaultCacheFactory<Object, Object>();
factory.setDefaultClassLoader(defaultClassLoader);
return factory.createCache(config, false);
}
}

View File

@ -35,8 +35,6 @@ import javax.transaction.SystemException;
import javax.transaction.Transaction; import javax.transaction.Transaction;
import javax.transaction.TransactionManager; import javax.transaction.TransactionManager;
import org.hibernate.test.cache.jbc2.functional.classloader.ClassLoaderTestDAO;
import org.hsqldb.lib.Iterator;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -52,7 +50,7 @@ public class DualNodeJtaTransactionManagerImpl implements TransactionManager {
private static final Hashtable INSTANCES = new Hashtable(); private static final Hashtable INSTANCES = new Hashtable();
private DualNodeJtaTransactionImpl currentTransaction; private ThreadLocal currentTransaction = new ThreadLocal();
private String nodeId; private String nodeId;
public synchronized static DualNodeJtaTransactionManagerImpl getInstance(String nodeId) { public synchronized static DualNodeJtaTransactionManagerImpl getInstance(String nodeId) {
@ -87,62 +85,66 @@ public class DualNodeJtaTransactionManagerImpl implements TransactionManager {
} }
public int getStatus() throws SystemException { public int getStatus() throws SystemException {
return currentTransaction == null ? Status.STATUS_NO_TRANSACTION : currentTransaction.getStatus(); Transaction tx = getCurrentTransaction();
return tx == null ? Status.STATUS_NO_TRANSACTION : tx.getStatus();
} }
public Transaction getTransaction() throws SystemException { public Transaction getTransaction() throws SystemException {
return currentTransaction; return (Transaction) currentTransaction.get();
} }
public DualNodeJtaTransactionImpl getCurrentTransaction() { public DualNodeJtaTransactionImpl getCurrentTransaction() {
return currentTransaction; return (DualNodeJtaTransactionImpl) currentTransaction.get();
} }
public void begin() throws NotSupportedException, SystemException { public void begin() throws NotSupportedException, SystemException {
currentTransaction = new DualNodeJtaTransactionImpl( this ); currentTransaction.set(new DualNodeJtaTransactionImpl( this ));
} }
public Transaction suspend() throws SystemException { public Transaction suspend() throws SystemException {
log.trace(nodeId + ": Suspending " + currentTransaction + " for thread " + Thread.currentThread().getName()); DualNodeJtaTransactionImpl suspended = getCurrentTransaction();
DualNodeJtaTransactionImpl suspended = currentTransaction; log.trace(nodeId + ": Suspending " + suspended + " for thread " + Thread.currentThread().getName());
currentTransaction = null; currentTransaction.set(null);
return suspended; return suspended;
} }
public void resume(Transaction transaction) public void resume(Transaction transaction)
throws InvalidTransactionException, IllegalStateException, SystemException { throws InvalidTransactionException, IllegalStateException, SystemException {
currentTransaction = ( DualNodeJtaTransactionImpl ) transaction; currentTransaction.set(( DualNodeJtaTransactionImpl ) transaction);
log.trace(nodeId + ": Resumed " + currentTransaction + " for thread " + Thread.currentThread().getName()); log.trace(nodeId + ": Resumed " + transaction + " for thread " + Thread.currentThread().getName());
} }
public void commit() public void commit()
throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
if ( currentTransaction == null ) { Transaction tx = getCurrentTransaction();
if ( tx == null ) {
throw new IllegalStateException( "no current transaction to commit" ); throw new IllegalStateException( "no current transaction to commit" );
} }
currentTransaction.commit(); tx.commit();
} }
public void rollback() throws IllegalStateException, SecurityException, SystemException { public void rollback() throws IllegalStateException, SecurityException, SystemException {
if ( currentTransaction == null ) { Transaction tx = getCurrentTransaction();
if ( tx == null ) {
throw new IllegalStateException( "no current transaction" ); throw new IllegalStateException( "no current transaction" );
} }
currentTransaction.rollback(); tx.rollback();
} }
public void setRollbackOnly() throws IllegalStateException, SystemException { public void setRollbackOnly() throws IllegalStateException, SystemException {
if ( currentTransaction == null ) { Transaction tx = getCurrentTransaction();
if ( tx == null ) {
throw new IllegalStateException( "no current transaction" ); throw new IllegalStateException( "no current transaction" );
} }
currentTransaction.setRollbackOnly(); tx.setRollbackOnly();
} }
public void setTransactionTimeout(int i) throws SystemException { public void setTransactionTimeout(int i) throws SystemException {
} }
void endCurrent(DualNodeJtaTransactionImpl transaction) { void endCurrent(DualNodeJtaTransactionImpl transaction) {
if ( transaction == currentTransaction ) { if ( transaction == currentTransaction.get() ) {
currentTransaction = null; currentTransaction.set(null);
} }
} }

View File

@ -20,8 +20,6 @@ import junit.framework.Test;
import org.hibernate.test.util.SelectedClassnameClassLoader; import org.hibernate.test.util.SelectedClassnameClassLoader;
import org.hibernate.test.util.SelectedClassnameClassLoaderTestSetup; import org.hibernate.test.util.SelectedClassnameClassLoaderTestSetup;
import org.jboss.cache.Cache;
import org.jboss.cache.config.Configuration;
/** /**
* A TestSetup that uses SelectedClassnameClassLoader to ensure that * A TestSetup that uses SelectedClassnameClassLoader to ensure that
@ -57,34 +55,32 @@ public class IsolatedCacheTestSetup extends SelectedClassnameClassLoaderTestSetu
super.setUp(); super.setUp();
// At this point the TCCL cannot see the isolatedClasses // At this point the TCCL cannot see the isolatedClasses
// We want the caches to use this CL as their default classloader
ClassLoader tccl = Thread.currentThread().getContextClassLoader(); ClassLoader tccl = Thread.currentThread().getContextClassLoader();
org.jgroups.ChannelFactory cf = new org.jgroups.JChannelFactory(); org.jgroups.ChannelFactory cf = new org.jgroups.JChannelFactory();
cf.setMultiplexerConfig(DEF_JGROUPS_RESOURCE); cf.setMultiplexerConfig(DEF_JGROUPS_RESOURCE);
org.jboss.cache.CacheManagerImpl cm = new org.jboss.cache.CacheManagerImpl(DEF_CACHE_FACTORY_RESOURCE, cf); // Use a CacheManager that will inject the desired defaultClassLoader into our caches
CustomClassLoaderCacheManager cm = new CustomClassLoaderCacheManager(DEF_CACHE_FACTORY_RESOURCE, cf, tccl);
cm.start(); cm.start();
TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.LOCAL, cm); TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.LOCAL, cm);
// Inject the desired defaultClassLoader into our caches cm.getCache(cacheConfig, true);
Configuration cfg = cm.getConfigurationRegistry().getConfiguration(cacheConfig);
Cache cache = new CustomClassLoaderCacheFactory(tccl).createCache(cfg, false); // Repeat for the "remote" cache
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(cm.getChannelFactory());
cm.registerCache(cache, cacheConfig);
cf = new org.jgroups.JChannelFactory(); cf = new org.jgroups.JChannelFactory();
cf.setMultiplexerConfig(DEF_JGROUPS_RESOURCE); cf.setMultiplexerConfig(DEF_JGROUPS_RESOURCE);
cm = new org.jboss.cache.CacheManagerImpl(DEF_CACHE_FACTORY_RESOURCE, cf); cm = new CustomClassLoaderCacheManager(DEF_CACHE_FACTORY_RESOURCE, cf, tccl);
cm.start(); cm.start();
TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.REMOTE, cm); TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.REMOTE, cm);
cfg = cm.getConfigurationRegistry().getConfiguration(cacheConfig); cm.getCache(cacheConfig, true);
cache = new CustomClassLoaderCacheFactory(tccl).createCache(cfg, false);
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(cm.getChannelFactory());
cm.registerCache(cache, cacheConfig);
// Now make the isolatedClasses visible // Now make the isolatedClasses visible to the test driver itself
SelectedClassnameClassLoader visible = new SelectedClassnameClassLoader(isolatedClasses, null, null, tccl); SelectedClassnameClassLoader visible = new SelectedClassnameClassLoader(isolatedClasses, null, null, tccl);
Thread.currentThread().setContextClassLoader(visible); Thread.currentThread().setContextClassLoader(visible);
} }