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:
parent
b3428358b7
commit
2052b06d53
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue