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 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 {
Configuration cfg = jbcCache.getConfiguration();
if (cfg.isUseRegionBasedMarshalling()) {
@ -128,6 +133,11 @@ public abstract class BasicRegionAdapter implements Region {
catch (Exception e) {
throw new CacheException(e.getMessage(), e);
}
finally {
if (tx != null)
resume(tx);
}
}
private void establishRegionRootNode()

View File

@ -16,9 +16,6 @@
package org.hibernate.test.cache.jbc2.functional;
import javax.transaction.TransactionManager;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Mappings;
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.DualNodeTestUtil;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

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

View File

@ -73,6 +73,12 @@ extends DualNodeTestCaseBase
static int test = 0;
private Cache localCache;
private CacheAccessListener localListener;
private Cache remoteCache;
private CacheAccessListener remoteListener;
public PessimisticIsolatedClassLoaderTest(String name)
{
super(name);
@ -120,6 +126,22 @@ extends DualNodeTestCaseBase
// Don't clean up the managers, just the transactions
// Managers are still needed by the long-lived caches
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();
}
}
/**
@ -145,9 +167,11 @@ extends DualNodeTestCaseBase
org.jboss.cache.Fqn fqn = org.jboss.cache.Fqn.fromString("/isolated1");
org.jboss.cache.Region r = localCache.getRegion(fqn, true);
r.registerContextClassLoader(cl.getParent());
r.activate();
r = remoteCache.getRegion(fqn, true);
r.registerContextClassLoader(cl.getParent());
r.activate();
Thread.currentThread().setContextClassLoader(cl);
Account acct = new Account();
@ -182,16 +206,16 @@ extends DualNodeTestCaseBase
// Bind a listener to the "local" cache
// Our region factory makes its CacheManager available to us
CacheManager localManager = TestCacheInstanceManager.getTestCacheManager(DualNodeTestUtil.LOCAL);
Cache localCache = localManager.getCache(getEntityCacheConfigName(), true);
CacheAccessListener localListener = new CacheAccessListener();
this.localCache = localManager.getCache(getEntityCacheConfigName(), true);
this.localListener = new CacheAccessListener();
localCache.addCacheListener(localListener);
TransactionManager localTM = localCache.getConfiguration().getRuntimeConfig().getTransactionManager();
// Bind a listener to the "remote" cache
CacheManager remoteManager = TestCacheInstanceManager.getTestCacheManager(DualNodeTestUtil.REMOTE);
Cache remoteCache = remoteManager.getCache(getEntityCacheConfigName(), true);
CacheAccessListener remoteListener = new CacheAccessListener();
this.remoteCache = remoteManager.getCache(getEntityCacheConfigName(), true);
this.remoteListener = new CacheAccessListener();
remoteCache.addCacheListener(remoteListener);
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.TransactionManager;
import org.hibernate.test.cache.jbc2.functional.classloader.ClassLoaderTestDAO;
import org.hsqldb.lib.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -52,7 +50,7 @@ public class DualNodeJtaTransactionManagerImpl implements TransactionManager {
private static final Hashtable INSTANCES = new Hashtable();
private DualNodeJtaTransactionImpl currentTransaction;
private ThreadLocal currentTransaction = new ThreadLocal();
private String nodeId;
public synchronized static DualNodeJtaTransactionManagerImpl getInstance(String nodeId) {
@ -87,62 +85,66 @@ public class DualNodeJtaTransactionManagerImpl implements TransactionManager {
}
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 {
return currentTransaction;
return (Transaction) currentTransaction.get();
}
public DualNodeJtaTransactionImpl getCurrentTransaction() {
return currentTransaction;
return (DualNodeJtaTransactionImpl) currentTransaction.get();
}
public void begin() throws NotSupportedException, SystemException {
currentTransaction = new DualNodeJtaTransactionImpl( this );
currentTransaction.set(new DualNodeJtaTransactionImpl( this ));
}
public Transaction suspend() throws SystemException {
log.trace(nodeId + ": Suspending " + currentTransaction + " for thread " + Thread.currentThread().getName());
DualNodeJtaTransactionImpl suspended = currentTransaction;
currentTransaction = null;
DualNodeJtaTransactionImpl suspended = getCurrentTransaction();
log.trace(nodeId + ": Suspending " + suspended + " for thread " + Thread.currentThread().getName());
currentTransaction.set(null);
return suspended;
}
public void resume(Transaction transaction)
throws InvalidTransactionException, IllegalStateException, SystemException {
currentTransaction = ( DualNodeJtaTransactionImpl ) transaction;
log.trace(nodeId + ": Resumed " + currentTransaction + " for thread " + Thread.currentThread().getName());
currentTransaction.set(( DualNodeJtaTransactionImpl ) transaction);
log.trace(nodeId + ": Resumed " + transaction + " for thread " + Thread.currentThread().getName());
}
public void commit()
throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
if ( currentTransaction == null ) {
Transaction tx = getCurrentTransaction();
if ( tx == null ) {
throw new IllegalStateException( "no current transaction to commit" );
}
currentTransaction.commit();
tx.commit();
}
public void rollback() throws IllegalStateException, SecurityException, SystemException {
if ( currentTransaction == null ) {
Transaction tx = getCurrentTransaction();
if ( tx == null ) {
throw new IllegalStateException( "no current transaction" );
}
currentTransaction.rollback();
tx.rollback();
}
public void setRollbackOnly() throws IllegalStateException, SystemException {
if ( currentTransaction == null ) {
Transaction tx = getCurrentTransaction();
if ( tx == null ) {
throw new IllegalStateException( "no current transaction" );
}
currentTransaction.setRollbackOnly();
tx.setRollbackOnly();
}
public void setTransactionTimeout(int i) throws SystemException {
}
void endCurrent(DualNodeJtaTransactionImpl transaction) {
if ( transaction == currentTransaction ) {
currentTransaction = null;
if ( transaction == currentTransaction.get() ) {
currentTransaction.set(null);
}
}

View File

@ -20,8 +20,6 @@ import junit.framework.Test;
import org.hibernate.test.util.SelectedClassnameClassLoader;
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
@ -55,36 +53,34 @@ public class IsolatedCacheTestSetup extends SelectedClassnameClassLoaderTestSetu
protected void setUp() throws Exception
{
super.setUp();
// 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();
org.jgroups.ChannelFactory cf = new org.jgroups.JChannelFactory();
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();
TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.LOCAL, cm);
// Inject the desired defaultClassLoader into our caches
Configuration cfg = cm.getConfigurationRegistry().getConfiguration(cacheConfig);
Cache cache = new CustomClassLoaderCacheFactory(tccl).createCache(cfg, false);
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(cm.getChannelFactory());
cm.registerCache(cache, cacheConfig);
cm.getCache(cacheConfig, true);
// Repeat for the "remote" cache
cf = new org.jgroups.JChannelFactory();
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();
TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.REMOTE, cm);
cfg = cm.getConfigurationRegistry().getConfiguration(cacheConfig);
cache = new CustomClassLoaderCacheFactory(tccl).createCache(cfg, false);
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(cm.getChannelFactory());
cm.registerCache(cache, cacheConfig);
cm.getCache(cacheConfig, true);
// Now make the isolatedClasses visible
// Now make the isolatedClasses visible to the test driver itself
SelectedClassnameClassLoader visible = new SelectedClassnameClassLoader(isolatedClasses, null, null, tccl);
Thread.currentThread().setContextClassLoader(visible);
}