[jboss-cvs] JBossAS SVN: r73532 - in projects/ejb3/trunk/core/src: test/java/org/jboss/ejb3/test/clusteredentity and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue May 20 10:48:58 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-05-20 10:48:58 -0400 (Tue, 20 May 2008)
New Revision: 73532

Added:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheBase.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/PessimisticJBCCache.java
Removed:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCache.java
Modified:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheFactory.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/OptimisticJBCCache.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TransactionalCacheFactory.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TreeCacheProviderHook.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java
Log:
[EJBTHREE-1373] Fix JBC 2 integration via TreeCacheProviderHook

Deleted: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCache.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCache.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCache.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -1,346 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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 software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.entity;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.cache.Cache;
-import org.hibernate.cache.CacheException;
-import org.hibernate.cache.StandardQueryCache;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.Node;
-import org.jboss.cache.Region;
-import org.jboss.cache.config.Option;
-import org.jboss.cache.lock.TimeoutException;
-
-/**
- * {@link Cache} implementation that uses a 2.x or later release of JBoss Cache.
- * 
- * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
- * @version $Revision: 1.1 $
- */
-public class JBCCache implements Cache
-{
-    
-    private static final Log log = LogFactory.getLog(JBCCache.class);
-
-    private static final String ITEM = "item";
-
-    private org.jboss.cache.Cache cache;
-    private final String regionName;
-    private final Fqn regionFqn;
-    private final TransactionManager transactionManager;
-    private boolean localWritesOnly;
-
-    public JBCCache(org.jboss.cache.Cache cache, String regionName, 
-                    String regionPrefix, TransactionManager transactionManager) 
-    throws CacheException {
-        this.cache = cache;
-        this.regionName = regionName;
-        this.regionFqn = Fqn.fromString(SecondLevelCacheUtil.createRegionFqn(regionName, regionPrefix));
-        this.transactionManager = transactionManager;
-        if (cache.getConfiguration().isUseRegionBasedMarshalling())
-        {           
-           localWritesOnly = StandardQueryCache.class.getName().equals(regionName);
-           
-           boolean fetchState = cache.getConfiguration().isFetchInMemoryState();
-           try
-           {
-              // We don't want a state transfer for the StandardQueryCache,
-              // as it can include classes from multiple scoped classloaders
-              if (localWritesOnly)
-                 cache.getConfiguration().setFetchInMemoryState(false);
-              
-              // We always activate
-              activateCacheRegion(regionFqn.toString());
-           }
-           finally
-           {
-              // Restore the normal state transfer setting
-              if (localWritesOnly)
-                 cache.getConfiguration().setFetchInMemoryState(fetchState);              
-           }
-        }
-        else
-        {
-           log.debug("TreeCache is not configured for region based marshalling");
-        }
-    }
-
-    public Object get(Object key) throws CacheException {
-        Transaction tx = suspend();
-        try {
-            return read(key);
-        }
-        finally {
-            resume( tx );
-        }
-    }
-    
-    public Object read(Object key) throws CacheException {
-        try {
-            return cache.get( new Fqn( regionFqn, key ), ITEM );
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-    }
-
-    public void update(Object key, Object value) throws CacheException {
-        try {
-        	if (localWritesOnly) {
-               Option option = new Option();
-               option.setCacheModeLocal(true);
-               cache.getInvocationContext().setOptionOverrides(option);
-               cache.put( new Fqn( regionFqn, key ), ITEM, value );
-            }
-            else {                
-            	cache.put( new Fqn( regionFqn, key ), ITEM, value );
-            }
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-    }
-
-    public void put(Object key, Object value) throws CacheException {
-        Transaction tx = suspend();
-        try {
-        	if (localWritesOnly) {
-               Option option = new Option();
-               option.setCacheModeLocal(true);
-               cache.getInvocationContext().setOptionOverrides(option);
-               //do the failfast put outside the scope of the JTA txn               
-               cache.putForExternalRead(new Fqn( regionFqn, key ), ITEM, value);
-            }
-            else {
-               cache.putForExternalRead(new Fqn( regionFqn, key ), ITEM, value);
-            }
-        }
-        catch (TimeoutException te) {
-            //ignore!
-            log.debug("ignoring write lock acquisition failure");
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-        finally {
-            resume( tx );
-        }
-    }
-
-    private void resume(Transaction tx) {
-        try {
-            if (tx!=null) transactionManager.resume(tx);
-        }
-        catch (Exception e) {
-            throw new CacheException("Could not resume transaction", e);
-        }
-    }
-
-    private Transaction suspend() {
-        Transaction tx = null;
-        try {
-            if ( transactionManager!=null ) {
-                tx = transactionManager.suspend();
-            }
-        }
-        catch (SystemException se) {
-            throw new CacheException("Could not suspend transaction", se);
-        }
-        return tx;
-    }
-
-    public void remove(Object key) throws CacheException {
-        try {
-           if (localWritesOnly) {
-              Option option = new Option();
-              option.setCacheModeLocal(true);
-              cache.getInvocationContext().setOptionOverrides(option);
-              cache.removeNode( new Fqn( regionFqn, key ) );
-           }
-           else {           
-              cache.removeNode( new Fqn( regionFqn, key ) );
-           }
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-    }
-
-    public void clear() throws CacheException {
-        try {
-            cache.removeNode( regionFqn );
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-    }
-
-    public void destroy() throws CacheException {
-        try {
-            // NOTE : evict() operates locally only (i.e., does not propogate
-            // to any other nodes in the potential cluster).  This is
-            // exactly what is needed when we destroy() here; destroy() is used
-            // as part of the process of shutting down a SessionFactory; thus
-            // these removals should not be propogated
-           // FIXME NPE bug in 2.0.0.ALPHA1, so we don't use evict 'til fixed
-//            cache.evict( regionFqn, true );
-           InvocationContext ctx = cache.getInvocationContext();
-           Option opt = new Option();
-           opt.setCacheModeLocal(true);
-           ctx.setOptionOverrides(opt);
-           cache.removeNode( regionFqn );
-           
-           if (cache.getConfiguration().isUseRegionBasedMarshalling() && !SecondLevelCacheUtil.isSharedClassLoaderRegion(regionName))
-           {
-              inactivateCacheRegion();
-           }
-        }
-        catch( Exception e ) {
-            throw SecondLevelCacheUtil.convertToHibernateException( e );
-        }
-    }
-
-    public void lock(Object key) throws CacheException {
-        throw new UnsupportedOperationException( "TreeCache is a fully transactional cache" + regionName );
-    }
-
-    public void unlock(Object key) throws CacheException {
-        throw new UnsupportedOperationException( "TreeCache is a fully transactional cache: " + regionName );
-    }
-
-    public long nextTimestamp() {
-        return System.currentTimeMillis() / 100;
-    }
-
-    public int getTimeout() {
-        return 600; //60 seconds
-    }
-
-    public String getRegionName() {
-        return regionName;
-    }
-
-    public long getSizeInMemory() {
-        return -1;
-    }
-
-    public long getElementCountInMemory() {
-        try {
-            Set children = getChildrenNames();
-            return children == null ? 0 : children.size();
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-    }
-
-    public long getElementCountOnDisk() {
-        return 0;
-    }
-    
-    public Map toMap() {
-        try {
-            Map result = new HashMap();
-            Set childrenNames = getChildrenNames();
-            if (childrenNames != null) {
-                Iterator iter = childrenNames.iterator();
-                while ( iter.hasNext() ) {
-                    Object key = iter.next();
-                    result.put( 
-                            key, 
-                            cache.get( new Fqn( regionFqn, key ), ITEM )
-                        );
-                }
-            }
-            return result;
-        }
-        catch (Exception e) {
-            throw SecondLevelCacheUtil.convertToHibernateException(e);
-        }
-    }
-    
-    private Set getChildrenNames()
-    {
-       try {
-          Node base = cache.getRoot().getChild( regionFqn );
-          return base == null ? null : base.getChildrenNames();
-       }
-       catch (Exception e) {
-          throw SecondLevelCacheUtil.convertToHibernateException(e);
-       }   
-    }
-    
-    public String toString() {
-        return "JBCCache(" + regionName + ')';
-    }
-    
-    private void activateCacheRegion(String regionName) throws CacheException
-    {
-       Region region = cache.getRegion(regionFqn, true);
-       if (region.isActive() == false)
-       {
-          try
-          {
-             // Only register the classloader if it's not a shared region.  
-             // If it's shared, no single classloader is valid
-             if (!SecondLevelCacheUtil.isSharedClassLoaderRegion(regionName))
-             {
-                region.registerContextClassLoader(Thread.currentThread().getContextClassLoader());
-             }
-             region.activate();
-          }
-          catch (Exception e)
-          {
-             throw SecondLevelCacheUtil.convertToHibernateException(e);
-          }
-       }
-    }
-    
-    private void inactivateCacheRegion() throws CacheException
-    {
-       Region region = cache.getRegion(regionFqn, false);
-       if (region != null && region.isActive())
-       {
-          try
-          {
-             region.deactivate();
-             region.unregisterContextClassLoader();
-          }
-          catch (Exception e)
-          {
-             throw SecondLevelCacheUtil.convertToHibernateException(e);
-          }
-       }        
-    }	
-}

Added: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheBase.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheBase.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheBase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -0,0 +1,304 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.entity;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.StandardQueryCache;
+import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.Region;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Configuration.CacheMode;
+
+/**
+ * Base superclass for a {@link Cache} implementation that uses a 2.x or later 
+ * release of JBoss Cache.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class JBCCacheBase
+{
+   public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.region.jbc2.query.localonly";
+   
+   protected static final String ITEM = "item";
+ 
+   protected org.jboss.cache.Cache<Object, Object> cache;
+   protected final String regionName;
+   protected final Fqn<String> regionFqn;
+   protected final TransactionManager transactionManager;
+   protected boolean localOnlyQueries;
+   protected boolean forTimestamps;
+   protected boolean forceAsync;
+   protected Node<Object, Object> regionRoot;
+   protected final Object regionRootMutex = new Object();
+
+
+   public JBCCacheBase(org.jboss.cache.Cache<Object, Object> cache, String regionName, 
+                       String regionPrefix, TransactionManager transactionManager,
+                       Properties properties) 
+   throws CacheException 
+   {
+       this.cache = cache;
+       this.regionName = regionName;
+       this.regionFqn = Fqn.fromString(SecondLevelCacheUtil.createRegionFqn(regionName, regionPrefix));
+       this.transactionManager = transactionManager;
+       this.forTimestamps = regionName.contains(UpdateTimestampsCache.class.getName());
+       CacheMode mode = cache.getConfiguration().getCacheMode();
+       if (forTimestamps)
+       {          
+          if (mode == CacheMode.INVALIDATION_ASYNC || mode == CacheMode.INVALIDATION_SYNC)
+          {
+             throw new IllegalStateException("Cache is configured for " + mode + 
+                                             "; not supported for a timestamps cache");
+          }
+          
+          forceAsync = (mode == CacheMode.REPL_SYNC);
+       }
+       
+       // We don't want to waste effort setting an option if JBC is
+       // already in LOCAL mode. If JBC is REPL_(A)SYNC then check
+       // if they passed a config option to disable query replication
+       if (mode != CacheMode.LOCAL)
+       {
+          localOnlyQueries = PropertiesHelper.getBoolean(QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
+          // If its the standard query region with no prefix, its possibly shared
+          // between classloaders, so we make it local only
+          localOnlyQueries = localOnlyQueries || 
+                             StandardQueryCache.class.getName().equals(regionName);
+       }
+       
+       activateLocalClusterNode();
+   }
+   
+   private 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 = cache.getConfiguration();
+         if (cfg.isUseRegionBasedMarshalling()) {                
+
+            Region jbcRegion = cache.getRegion(regionFqn, true);
+
+            // Only register the classloader if it's not a shared region.  
+            // If it's shared, no single classloader is valid
+            boolean shared = SecondLevelCacheUtil.isSharedClassLoaderRegion(regionName);
+            if (!shared)
+            {
+               ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+               if (classLoader == null) {
+                  classLoader = getClass().getClassLoader();
+               }
+               jbcRegion.registerContextClassLoader(classLoader);
+            }
+
+            if ( !jbcRegion.isActive() ) 
+            {
+               boolean fetchState = cfg.isFetchInMemoryState();
+               try
+               {
+                  // We don't want a state transfer for a shared region,
+                  // as it can include classes from multiple scoped classloaders
+                  if (shared)
+                     cfg.setFetchInMemoryState(false);
+
+                  jbcRegion.activate();
+               }
+               finally
+               {
+                  // Restore the normal state transfer setting
+                  if (shared)
+                     cfg.setFetchInMemoryState(fetchState);              
+               }
+
+            }
+         }
+
+         regionRoot = createRegionRootNode();
+      }
+      catch (Exception e)
+      {
+         throw SecondLevelCacheUtil.convertToHibernateException(e);
+      }
+      finally {
+         resume(tx);
+      }        
+    }
+
+   protected abstract void establishRegionRootNode();
+
+   protected abstract Node<Object, Object> createRegionRootNode();
+
+   /**
+     * Checks for the validity of the root cache node for this region,
+     * creating a new one if it does not exist or is invalid, and also
+     * ensuring that the root node is marked as resident.  Suspends any 
+     * transaction while doing this to ensure no transactional locks are held 
+     * on the region root.
+     * 
+     * TODO remove this once JBCACHE-1250 is resolved.
+     */
+   protected void ensureRegionRootExists()
+   {       
+       if (regionRoot == null || !regionRoot.isValid())
+       {
+          synchronized (regionRootMutex)
+          {
+             // If we've been blocking for the mutex, perhaps another
+             // thread has already reestablished the root.
+             // In case the node was reestablised via replication, confirm it's 
+             // marked "resident" (a status which doesn't replicate)
+             if (regionRoot != null && regionRoot.isValid()) {
+                return;
+             }
+             
+             establishRegionRootNode();
+          }
+       }
+       
+       // Fix up the resident flag
+       if (regionRoot != null && regionRoot.isValid() && !regionRoot.isResident())
+          regionRoot.setResident(true);
+    }
+
+   protected void resume(Transaction tx)
+   {
+      if (tx != null)
+      {
+         try {
+            transactionManager.resume(tx);
+         }
+         catch (Exception e) {
+            throw new CacheException("Could not resume transaction", e);
+         }
+      }
+   }
+
+   protected Transaction suspend()
+   {
+      Transaction tx = null;
+      if (transactionManager != null)
+      {
+         try {
+            tx = transactionManager.suspend();
+         }
+         catch (SystemException se) {
+            throw new CacheException("Could not suspend transaction", se);
+         }
+      }
+      return tx;
+   }
+   
+   protected void inactivateCacheRegion() throws CacheException
+   {
+      Region region = cache.getRegion(regionFqn, false);
+      if (region != null && region.isActive())
+      {
+         try
+         {
+            region.deactivate();
+            region.unregisterContextClassLoader();
+         }
+         catch (Exception e)
+         {
+            throw SecondLevelCacheUtil.convertToHibernateException(e);
+         }
+      }        
+   }
+
+   public void lock(Object key) throws CacheException {
+       throw new UnsupportedOperationException( "TreeCache is a fully transactional cache" + regionName );
+   }
+
+   public void unlock(Object key) throws CacheException {
+       throw new UnsupportedOperationException( "TreeCache is a fully transactional cache: " + regionName );
+   }
+
+   public long nextTimestamp() {
+       return System.currentTimeMillis() / 100;
+   }
+
+   public int getTimeout() {
+       return 600; //60 seconds
+   }
+
+   public String getRegionName() {
+       return regionName;
+   }
+
+   public long getSizeInMemory() {
+       return -1;
+   }
+
+   public long getElementCountInMemory() {
+       try {
+           return getChildrenNames().size();
+       }
+       catch (Exception e) {
+           throw SecondLevelCacheUtil.convertToHibernateException(e);
+       }
+   }
+
+   public long getElementCountOnDisk() {
+       return 0;
+   }
+
+   public Map<Object, Object> toMap() {
+       try {
+           Map<Object, Object> result = new HashMap<Object, Object>();
+           for (Object key : getChildrenNames() ) {
+               result.put(key, cache.get( new Fqn( regionFqn, key ), ITEM ));
+           }
+           return result;
+       }
+       catch (Exception e) {
+           throw SecondLevelCacheUtil.convertToHibernateException(e);
+       }
+   }
+   
+   private Set<Object> getChildrenNames()
+   {
+      try {
+         return regionRoot == null ? new HashSet<Object>() : regionRoot.getChildrenNames();
+      }
+      catch (Exception e) {
+         throw SecondLevelCacheUtil.convertToHibernateException(e);
+      }   
+   }
+
+}
\ No newline at end of file

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheFactory.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheFactory.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCacheFactory.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -1,3 +1,24 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
 package org.jboss.ejb3.entity;
 
 import java.util.Properties;
@@ -8,12 +29,21 @@
 import org.jboss.cache.CacheStatus;
 import org.jboss.ejb3.tx.TxUtil;
 import org.jboss.ha.framework.server.CacheManagerLocator;
+import org.jboss.logging.Logger;
 
+/**
+ * Concrete implementation of TransactionalCacheFactory meant for use with
+ * JBoss Cache 2.x
+ * 
+ * @author Brian Stansberry
+ */
 class JBCCacheFactory extends TransactionalCacheFactory
 {
+   private static final Logger log = Logger.getLogger(JBCCacheFactory.class);
+   
    private CacheManager cacheManager;
    private String cacheName;
-   private org.jboss.cache.Cache cache;
+   private org.jboss.cache.Cache<Object, Object> cache;
    private boolean optimistic;
    
    JBCCacheFactory()
@@ -76,19 +106,25 @@
       
       if (optimistic)
       {
-         return new OptimisticJBCCache(cache, regionName, regionPrefix);
+         return new OptimisticJBCCache(cache, regionName, regionPrefix,
+                                       TxUtil.getTransactionManager(),
+                                       properties);
       }
       else
       {
-         return new JBCCache(cache, regionName, regionPrefix,
-                             TxUtil.getTransactionManager());
+         return new PessimisticJBCCache(cache, regionName, regionPrefix,
+                                        TxUtil.getTransactionManager(),
+                                        properties);
       }
    }
    
    public void stop()
    {
       if (cache != null)
+      {
          cacheManager.releaseCache(cacheName);
+         log.debug("Cache " + cacheName + " released");
+      }
    }
    
    public boolean isOptimistic()

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/OptimisticJBCCache.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/OptimisticJBCCache.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/OptimisticJBCCache.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -21,27 +21,24 @@
  */
 package org.jboss.ejb3.entity;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
 import java.util.Comparator;
+import java.util.Properties;
 
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.OptimisticCache;
 import org.hibernate.cache.OptimisticCacheSource;
-import org.hibernate.cache.StandardQueryCache;
-import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cache.QueryKey;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.Node;
-import org.jboss.cache.Region;
+import org.jboss.cache.NodeSPI;
 import org.jboss.cache.optimistic.DataVersion;
-import org.jboss.cache.config.Configuration;
 import org.jboss.cache.config.Option;
 import org.jboss.cache.lock.TimeoutException;
+import org.jboss.logging.Logger;
 
 /**
  * Represents a particular region within the given JBossCache TreeCache
@@ -52,56 +49,61 @@
  * @author Steve Ebersole
  * @author Brian Stansberry
  */
-public class OptimisticJBCCache implements OptimisticCache {
+public class OptimisticJBCCache extends JBCCacheBase implements OptimisticCache 
+{
 
-	// todo : eventually merge this with TreeCache and just add optional opt-lock support there.
+   private static final Logger log = Logger.getLogger(OptimisticJBCCache.class);
+   
+   private OptimisticCacheSource source;
 
-	private static final Log log = LogFactory.getLog( OptimisticJBCCache.class);
+   public OptimisticJBCCache(org.jboss.cache.Cache<Object, Object> cache, 
+         String regionName, String regionPrefix, 
+         TransactionManager transactionManager,
+         Properties properties) 
+   throws CacheException {
+      super(cache, regionName, regionPrefix, transactionManager, properties);
+   }
 
-	private static final String ITEM = "item";
+   @Override
+   protected void establishRegionRootNode()
+   {
+      // Don't hold a transactional lock for this 
+      Transaction tx = suspend();
+      Node<Object, Object> newRoot = null;
+      try {
+         // Make sure the root node for the region exists and 
+         // has a DataVersion that never complains
+         newRoot = createRegionRootNode();
+      }
+      finally {
+         resume(tx);
+         regionRoot = newRoot;
+      }
+   }
 
-	private org.jboss.cache.Cache cache;
-	private final String regionName;
-	private final Fqn regionFqn;
-	private OptimisticCacheSource source;
-    private boolean localWritesOnly;
+   @Override
+   protected Node<Object, Object> createRegionRootNode()
+   {
+      Node<Object, Object> root = cache.getRoot();
+      Node<Object, Object> targetNode = root.getChild( regionFqn );
+      if (targetNode == null || !targetNode.isValid()) {
+         cache.getInvocationContext().getOptionOverrides().setDataVersion(NonLockingDataVersion.INSTANCE);          
+         targetNode = root.addChild( regionFqn );    
+      }
+      else if (targetNode instanceof NodeSPI) {
+         // FIXME Hacky workaround to JBCACHE-1202
+         if ( !( ( ( NodeSPI ) targetNode ).getVersion() instanceof NonLockingDataVersion ) ) {
+              ((NodeSPI) targetNode).setVersion(NonLockingDataVersion.INSTANCE);
+         }
+      }
 
-	public OptimisticJBCCache(org.jboss.cache.Cache cache, 
-                              String regionName, String regionPrefix)
-	throws CacheException {
-		this.cache = cache;
-		this.regionName = regionName;
-        this.regionFqn = Fqn.fromString(SecondLevelCacheUtil.createRegionFqn(regionName, regionPrefix));
-        Configuration config = cache.getConfiguration();
-        if (config.isUseRegionBasedMarshalling())
-        {           
-           localWritesOnly = StandardQueryCache.class.getName().equals(regionName);
-           
-           boolean fetchState = config.isFetchInMemoryState();
-           try
-           {
-              // We don't want a state transfer for the StandardQueryCache,
-              // as it can include classes from multiple scoped classloaders
-              if (localWritesOnly)
-                 config.setFetchInMemoryState(false);
-              
-              // We always activate
-              activateCacheRegion(regionFqn.toString());
-           }
-           finally
-           {
-              // Restore the normal state transfer setting
-              if (localWritesOnly)
-                 config.setFetchInMemoryState(fetchState);              
-           }
-        }
-        else
-        {
-           log.debug("TreeCache is not configured for region based marshalling");
-        }
-	}
+      // Never evict this node
+      targetNode.setResident(true);
 
+      return targetNode;
+   }
 
+
 	// OptimisticCache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	public void setSource(OptimisticCacheSource source) {
@@ -112,14 +114,18 @@
 		writeUpdate( key, value, currentVersion, null );
 	}
 
+	@SuppressWarnings("unchecked")
 	public void writeUpdate(Object key, Object value, Object currentVersion, Object previousVersion) {
 		try {
+            ensureRegionRootExists();
+            
 			Option option = new Option();
 			DataVersion dv = ( source != null && source.isVersioned() )
 			                 ? new DataVersionAdapter( currentVersion, previousVersion, source.getVersionComparator(), source.toString() )
 			                 : NonLockingDataVersion.INSTANCE;
 			option.setDataVersion( dv );
-            option.setCacheModeLocal(localWritesOnly);
+			if (localOnlyQueries && key instanceof QueryKey)
+               option.setCacheModeLocal(true);
             cache.getInvocationContext().setOptionOverrides(option);
 			cache.put( new Fqn( regionFqn, key ), ITEM, value );
 		}
@@ -128,48 +134,86 @@
 		}
 	}
 
-	public void writeLoad(Object key, Object value, Object currentVersion) {
-		try {
-			Option option = new Option();
-			option.setFailSilently( true );
-			option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            option.setCacheModeLocal(localWritesOnly);
-            cache.getInvocationContext().setOptionOverrides(option);
-			cache.remove( new Fqn( regionFqn, key ), "ITEM" );
+	@SuppressWarnings("unchecked")
+    public void writeLoad(Object key, Object value, Object currentVersion) {
+	   Transaction tx = null;
+	   try {
+	      Option option = new Option();
+	      DataVersion dv = ( source != null && source.isVersioned() )
+	                           ? new DataVersionAdapter( currentVersion, currentVersion, source.getVersionComparator(), source.toString() )
+	                           : NonLockingDataVersion.INSTANCE;
+	      option.setDataVersion( dv );
 
-			option = new Option();
-			option.setFailSilently( true );
-			DataVersion dv = ( source != null && source.isVersioned() )
-			                 ? new DataVersionAdapter( currentVersion, currentVersion, source.getVersionComparator(), source.toString() )
-			                 : NonLockingDataVersion.INSTANCE;
-			option.setDataVersion( dv );
-            option.setCacheModeLocal(localWritesOnly);
-            cache.getInvocationContext().setOptionOverrides(option);
-			cache.put( new Fqn( regionFqn, key ), ITEM, value );
-		}
-		catch (Exception e) {
-			throw SecondLevelCacheUtil.convertToHibernateException(e);
-		}
+	      if (forTimestamps) 
+	      {
+	         tx = suspend();
+
+	         ensureRegionRootExists();
+
+	         // Timestamps don't use putForExternalRead, but are async
+	         if (forceAsync)
+	            option.setForceAsynchronous(true);
+	         cache.getInvocationContext().setOptionOverrides(option);
+	         cache.put(new Fqn( regionFqn, key ), ITEM, value);               
+	      }
+	      else if (key instanceof QueryKey) 
+	      {
+	         ensureRegionRootExists();
+
+	         option.setCacheModeLocal(localOnlyQueries);
+             option.setLockAcquisitionTimeout(2);
+	         cache.getInvocationContext().setOptionOverrides(option);
+	         cache.put( new Fqn( regionFqn, key ), ITEM, value );
+	      }
+	      else
+	      {
+	         ensureRegionRootExists();
+	         cache.getInvocationContext().setOptionOverrides(option);
+	         cache.putForExternalRead( new Fqn( regionFqn, key ), ITEM, value );
+	      }
+	   }
+	   catch (TimeoutException te) {
+	      if (!(key instanceof QueryKey))
+	         throw SecondLevelCacheUtil.convertToHibernateException(te);
+	   } 
+	   catch (Exception e) {
+	      throw SecondLevelCacheUtil.convertToHibernateException(e);
+	   }
+	   finally {
+	      resume(tx);
+	   }
 	}
 
 
 	// Cache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	public Object get(Object key) throws CacheException {
-		try {
-			Option option = new Option();
-			option.setFailSilently( true );
-//			option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            cache.getInvocationContext().setOptionOverrides(option);
+	    Transaction tx = suspend();
+	    try {
+	        ensureRegionRootExists();
+		    if (key instanceof QueryKey)
+		    {		       
+		       cache.getInvocationContext().getOptionOverrides().setLockAcquisitionTimeout(0);		       
+		    }
+		    
 			return cache.get( new Fqn( regionFqn, key ), ITEM );
 		}
+		catch (TimeoutException e) {
+		   if (key instanceof QueryKey)
+		      return null;
+		   throw SecondLevelCacheUtil.convertToHibernateException(e);
+		}
 		catch (Exception e) {
 			throw SecondLevelCacheUtil.convertToHibernateException(e);
 		}
+		finally {
+		   resume(tx);
+		}
 	}
 
 	public Object read(Object key) throws CacheException {
 		try {
+            ensureRegionRootExists();
 			return cache.get( new Fqn( regionFqn, key ), ITEM );
 		}
 		catch (Exception e) {
@@ -179,9 +223,11 @@
 
 	public void update(Object key, Object value) throws CacheException {
 		try {
+            ensureRegionRootExists();
 			Option option = new Option();
 			option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            option.setCacheModeLocal(localWritesOnly);
+            if (localOnlyQueries && key instanceof QueryKey)
+               option.setCacheModeLocal(true);
             cache.getInvocationContext().setOptionOverrides(option);
 			cache.put( new Fqn( regionFqn, key ), ITEM, value );
 		}
@@ -191,51 +237,67 @@
 	}
 
 	public void put(Object key, Object value) throws CacheException {
+	    Transaction tx = null;
 		try {
-			log.trace( "performing put() into region [" + regionName + "]" );
-			// do the put outside the scope of the JTA txn
-			Option option = new Option();
-			option.setFailSilently( true );
-			option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            option.setCacheModeLocal(localWritesOnly);
-            cache.getInvocationContext().setOptionOverrides(option);
-			cache.put( new Fqn( regionFqn, key ), ITEM, value );
+            Option option = new Option();
+            option.setDataVersion( NonLockingDataVersion.INSTANCE );
+            if (forTimestamps) {
+               tx = suspend();
+
+               ensureRegionRootExists();
+               
+               // Timestamps don't use putForExternalRead, but are async
+               if (forceAsync)
+                  option.setForceAsynchronous(true);
+               cache.getInvocationContext().setOptionOverrides(option);
+               cache.put(new Fqn( regionFqn, key ), ITEM, value);               
+            }
+            else if (key instanceof QueryKey) { 
+               
+               ensureRegionRootExists();
+               
+               option.setCacheModeLocal(localOnlyQueries);
+               option.setLockAcquisitionTimeout(2);
+               cache.getInvocationContext().setOptionOverrides(option);
+               cache.put(new Fqn( regionFqn, key ), ITEM, value); 
+            }
+            else {
+               ensureRegionRootExists();
+               cache.getInvocationContext().setOptionOverrides(option);
+   			   cache.putForExternalRead( new Fqn( regionFqn, key ), ITEM, value );
+            }
 		}
 		catch (TimeoutException te) {
-			//ignore!
-			log.debug("ignoring write lock acquisition failure");
+			if (!(key instanceof QueryKey))
+	            throw SecondLevelCacheUtil.convertToHibernateException(te);
 		}
 		catch (Exception e) {
 			throw SecondLevelCacheUtil.convertToHibernateException(e);
 		}
+		finally {
+		   resume(tx);
+		}
 	}
 
 	public void remove(Object key) throws CacheException {
-		try {
-			// tree cache in optimistic mode seems to have as very difficult
-			// time with remove calls on non-existent nodes (NPEs)...
-			if ( cache.get( new Fqn( regionFqn, key ), ITEM ) != null ) {
-				Option option = new Option();
-				option.setDataVersion( NonLockingDataVersion.INSTANCE );
-                option.setCacheModeLocal(localWritesOnly);
-                cache.getInvocationContext().setOptionOverrides(option);
-				cache.removeNode( new Fqn( regionFqn, key ) );
-			}
-			else {
-				log.trace( "skipping remove() call as the underlying node did not seem to exist" );
-			}
-		}
-		catch (Exception e) {
-			throw SecondLevelCacheUtil.convertToHibernateException(e);
-		}
+	   try {
+	      ensureRegionRootExists();
+
+	      Option option = new Option();
+	      option.setDataVersion( NonLockingDataVersion.INSTANCE );
+	      if (localOnlyQueries && key instanceof QueryKey)
+	         option.setCacheModeLocal(true);
+	      cache.getInvocationContext().setOptionOverrides(option);
+	      cache.removeNode( new Fqn( regionFqn, key ) );
+	   }
+	   catch (Exception e) {
+	      throw SecondLevelCacheUtil.convertToHibernateException(e);
+	   }
 	}
 
 	public void clear() throws CacheException {
 		try {
-			Option option = new Option();
-			option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            option.setCacheModeLocal(localWritesOnly);
-            cache.getInvocationContext().setOptionOverrides(option);
+			cache.getInvocationContext().getOptionOverrides().setDataVersion( NonLockingDataVersion.INSTANCE );
 			cache.removeNode( regionFqn );
 		}
 		catch (Exception e) {
@@ -247,13 +309,12 @@
 		try {
 			Option option = new Option();
 			option.setCacheModeLocal( true );
-			option.setFailSilently( true );
 			option.setDataVersion( NonLockingDataVersion.INSTANCE );
             cache.getInvocationContext().setOptionOverrides(option);
 			cache.removeNode( regionFqn );
             
             if (cache.getConfiguration().isUseRegionBasedMarshalling() 
-                  && !isSharedClassLoaderRegion(regionName))
+                  && !SecondLevelCacheUtil.isSharedClassLoaderRegion(regionName))
             {
                inactivateCacheRegion();
             }
@@ -263,134 +324,19 @@
 		}
 	}
 
-	public void lock(Object key) throws CacheException {
-		throw new UnsupportedOperationException( "TreeCache is a fully transactional cache" + regionName );
-	}
-
-	public void unlock(Object key) throws CacheException {
-		throw new UnsupportedOperationException( "TreeCache is a fully transactional cache: " + regionName );
-	}
-
-	public long nextTimestamp() {
-		return System.currentTimeMillis() / 100;
-	}
-
-	public int getTimeout() {
-		return 600; //60 seconds
-	}
-
-	public String getRegionName() {
-		return regionName;
-	}
-
-	public long getSizeInMemory() {
-		return -1;
-	}
-
-	public long getElementCountInMemory() {
-		try {
-			Set children = getChildrenNames();
-			return children == null ? 0 : children.size();
-		}
-		catch (Exception e) {
-			throw SecondLevelCacheUtil.convertToHibernateException(e);
-		}
-	}
-
-	public long getElementCountOnDisk() {
-		return 0;
-	}
-
-	public Map toMap() {
-		try {
-			Map result = new HashMap();
-			Set childrenNames = getChildrenNames();
-			if (childrenNames != null) {
-				Iterator iter = childrenNames.iterator();
-				while ( iter.hasNext() ) {
-					Object key = iter.next();
-					result.put(
-							key,
-					        cache.get( new Fqn( regionFqn, key ), ITEM )
-						);
-				}
-			}
-			return result;
-		}
-		catch (Exception e) {
-			throw SecondLevelCacheUtil.convertToHibernateException(e);
-		}
-	}
-    
-    private Set getChildrenNames()
-    {
-       try {
-          Node base = cache.getRoot().getChild( regionFqn );
-          return base == null ? null : base.getChildrenNames();
-       }
-       catch (Exception e) {
-          throw SecondLevelCacheUtil.convertToHibernateException(e);
-       }   
-    }
-
 	public String toString() {
-		return "OptimisticTreeCache(" + regionName + ')';
+		return "OptimisticJBCCache(" + regionName + ')';
 	}
-       
-    private boolean isSharedClassLoaderRegion(String regionName)
-    {
-       return (StandardQueryCache.class.getName().equals(regionName) 
-                || UpdateTimestampsCache.class.getName().equals(regionName));
-    }
-    
-    private void activateCacheRegion(String regionName) throws CacheException
-    {
-       Region region = cache.getRegion(regionFqn, true);
-       if (region.isActive() == false)
-       {
-          try
-          {
-             // Only register the classloader if it's not a shared region.  
-             // If it's shared, no single classloader is valid
-             if (!isSharedClassLoaderRegion(regionName))
-             {
-                region.registerContextClassLoader(Thread.currentThread().getContextClassLoader());
-             }
-             region.activate();
-          }
-          catch (Exception e)
-          {
-             throw SecondLevelCacheUtil.convertToHibernateException(e);
-          }
-       }
-    }
-    
-    private void inactivateCacheRegion() throws CacheException
-    {
-       Region region = cache.getRegion(regionFqn, false);
-       if (region != null && region.isActive())
-       {
-          try
-          {
-             region.deactivate();
-             region.unregisterContextClassLoader();
-          }
-          catch (Exception e)
-          {
-             throw SecondLevelCacheUtil.convertToHibernateException(e);
-          }
-       }        
-    }
 
 	public static class DataVersionAdapter implements DataVersion 
     {
         private static final long serialVersionUID = 5564692336076405571L;
 		private final Object currentVersion;
 		private final Object previousVersion;
-		private final Comparator versionComparator;
+		private final Comparator<Object> versionComparator;
 		private final String sourceIdentifer;
 
-		public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator, String sourceIdentifer) {
+		public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator<Object> versionComparator, String sourceIdentifer) {
 			this.currentVersion = currentVersion;
 			this.previousVersion = previousVersion;
 			this.versionComparator = versionComparator;

Copied: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/PessimisticJBCCache.java (from rev 73422, projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/JBCCache.java)
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/PessimisticJBCCache.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/PessimisticJBCCache.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -0,0 +1,208 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.entity;
+
+import java.util.Properties;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.QueryKey;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+import org.jboss.ejb3.entity.OptimisticJBCCache.NonLockingDataVersion;
+
+/**
+ * {@link Cache} implementation that uses a 2.x or later release of 
+ * JBoss Cache configured for pessimistic locking.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class PessimisticJBCCache extends JBCCacheBase implements Cache
+{
+   public PessimisticJBCCache(org.jboss.cache.Cache<Object, Object> cache, String regionName, 
+                              String regionPrefix, TransactionManager transactionManager,
+                              Properties properties) 
+   throws CacheException {
+       super(cache, regionName, regionPrefix, transactionManager, properties);
+   }
+
+   @Override
+   protected void establishRegionRootNode()
+   {            
+      // For pessimistic locking, we just want to toss out our ref
+      // to any old invalid root node and get the latest (may be null)            
+      regionRoot = cache.getRoot().getChild( regionFqn );               
+   }
+
+   @Override
+   protected Node<Object, Object> createRegionRootNode()
+   {
+      Node<Object, Object> root = cache.getRoot();
+      Node<Object, Object> targetNode = root.getChild( regionFqn );
+      if (targetNode == null || !targetNode.isValid()) {
+         cache.getInvocationContext().getOptionOverrides().setDataVersion(NonLockingDataVersion.INSTANCE);          
+         targetNode = root.addChild( regionFqn );    
+      }
+
+      // Never evict this node
+      targetNode.setResident(true);
+
+      return targetNode;
+   }
+
+    public Object get(Object key) throws CacheException {
+        Transaction tx = suspend();
+        try {
+            ensureRegionRootExists();
+            if (key instanceof QueryKey) {
+               cache.getInvocationContext().getOptionOverrides().setLockAcquisitionTimeout(0);  
+            }
+            return cache.get( new Fqn( regionFqn, key ), ITEM );
+        }
+        catch (TimeoutException e) {
+           if (key instanceof QueryKey)
+              return null;
+           throw SecondLevelCacheUtil.convertToHibernateException(e);
+        }
+        finally {
+            resume( tx );
+        }
+    }
+    
+    public Object read(Object key) throws CacheException {
+        try {
+            ensureRegionRootExists();
+            return cache.get( new Fqn( regionFqn, key ), ITEM );
+        }
+        catch (Exception e) {
+            throw SecondLevelCacheUtil.convertToHibernateException(e);
+        }
+    }
+
+    public void update(Object key, Object value) throws CacheException {
+        try {
+            ensureRegionRootExists();
+        	if (localOnlyQueries && key instanceof QueryKey) {
+               cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+            }
+            cache.put( new Fqn( regionFqn, key ), ITEM, value );
+        }
+        catch (Exception e) {
+            throw SecondLevelCacheUtil.convertToHibernateException(e);
+        }
+    }
+
+    public void put(Object key, Object value) throws CacheException {
+        Transaction tx = null;
+        try {
+            if (forTimestamps) {
+               // For timestamps, we suspend and send async
+               tx = suspend();
+               ensureRegionRootExists();
+               // Timestamps don't use putForExternalRead, but are async
+               if (forceAsync) // else the cache already is async or local
+               {
+                  cache.getInvocationContext().getOptionOverrides().setForceAsynchronous(true);
+               }
+               cache.put(new Fqn( regionFqn, key ), ITEM, value);               
+            }
+            else if (key instanceof QueryKey) {
+               // For queries we use a short timeout and ignore failures
+               ensureRegionRootExists();
+               Option option = new Option();
+               option.setCacheModeLocal(localOnlyQueries);
+               option.setLockAcquisitionTimeout(2);
+               cache.getInvocationContext().setOptionOverrides(option);
+               cache.put(new Fqn( regionFqn, key ), ITEM, value);
+            }
+            else {
+               ensureRegionRootExists();
+               cache.putForExternalRead(new Fqn( regionFqn, key ), ITEM, value);
+            }
+        }
+        catch (TimeoutException te) {
+           if (!(key instanceof QueryKey))
+              throw SecondLevelCacheUtil.convertToHibernateException(te);
+        }
+        catch (Exception e) {
+            throw SecondLevelCacheUtil.convertToHibernateException(e);
+        }
+        finally {
+            resume( tx );
+        }
+    }
+
+    public void remove(Object key) throws CacheException {
+        try {
+           ensureRegionRootExists();
+           if (localOnlyQueries && key instanceof QueryKey) {
+              cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+           }
+           cache.removeNode( new Fqn( regionFqn, key ) );
+        }
+        catch (Exception e) {
+            throw SecondLevelCacheUtil.convertToHibernateException(e);
+        }
+    }
+
+    public void clear() throws CacheException {
+        try {
+            cache.removeNode( regionFqn );
+        }
+        catch (Exception e) {
+            throw SecondLevelCacheUtil.convertToHibernateException(e);
+        }
+    }
+
+    public void destroy() throws CacheException {
+        try {
+            // NOTE : evict() operates locally only (i.e., does not propogate
+            // to any other nodes in the potential cluster).  This is
+            // exactly what is needed when we destroy() here; destroy() is used
+            // as part of the process of shutting down a SessionFactory; thus
+            // these removals should not be propogated
+           // FIXME NPE bug in 2.0.0.ALPHA1, so we don't use evict 'til fixed
+//            cache.evict( regionFqn, true );
+           cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+           cache.removeNode( regionFqn );
+           
+           if (cache.getConfiguration().isUseRegionBasedMarshalling() 
+                 && !SecondLevelCacheUtil.isSharedClassLoaderRegion(regionName))
+           {
+              inactivateCacheRegion();
+           }
+        }
+        catch( Exception e ) {
+            throw SecondLevelCacheUtil.convertToHibernateException( e );
+        }
+    }
+    
+    public String toString() {
+        return "PessimisticJBCCache(" + regionName + ')';
+    }
+}

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TransactionalCacheFactory.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TransactionalCacheFactory.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TransactionalCacheFactory.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -1,3 +1,24 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
 package org.jboss.ejb3.entity;
 
 import java.util.Properties;
@@ -6,6 +27,12 @@
 import org.hibernate.cache.CacheException;
 import org.jboss.cache.Version;
 
+/**
+ * Factory for <cdoe>org.hibernate.cache.Cache</code> implementations that
+ * work with JBoss Cache.
+ * 
+ * @author Brian Stansberry
+ */
 public abstract class TransactionalCacheFactory
 {
 

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TreeCacheProviderHook.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -103,7 +103,7 @@
     * @throws org.hibernate.cache.CacheException
     *          Indicates a problem preparing cache for use.
     */
-   public void start(Properties properties)
+   public void start(Properties properties) throws CacheException
    {
       cacheFactory = TransactionalCacheFactory.getFactory(properties);
       cacheFactory.start();

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -60,7 +60,7 @@
    
    private String cacheConfigName;
    
-   private transient Cache cache;
+   private transient Cache<Object, Object> cache;
    
    private transient MyListener listener;
 
@@ -78,7 +78,7 @@
       try
       {
          //Just to initialise the cache with a listener
-         Cache cache = getCache();
+         Cache<Object, Object> cache = getCache();
          if (listener == null)
          {
             listener = new MyListener();
@@ -193,7 +193,6 @@
             Cache c = getCache();
             if (c != null)
                c.removeCacheListener(listener);
-            listener = null;
          }
       }
       catch (Exception e)
@@ -232,7 +231,7 @@
       }
    }
 
-   private Cache getCache() throws Exception
+   private Cache<Object, Object> getCache() throws Exception
    {
       if (cache == null && cacheConfigName != null)
       {

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -52,6 +52,6 @@
    
    public abstract void cleanup();
    
-   public abstract void remove();
+   public abstract void remove(boolean removeEntities);
 
 }
\ No newline at end of file

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -66,7 +66,7 @@
    
    private String cacheConfigName;
    
-   private transient Cache cache;
+   private transient Cache<Object, Object> cache;
    
    private MyListener listener;
 
@@ -84,7 +84,7 @@
       try
       {
          //Just to initialise the cache with a listener
-         Cache cache = getCache();
+         Cache<Object, Object> cache = getCache();
          listener = new MyListener();
          cache.addCacheListener(listener);         
       }
@@ -243,7 +243,7 @@
             saw = true;
          }
       }
-   return saw;
+      return saw;
       
    }
    
@@ -276,21 +276,24 @@
    
    @PreDestroy
    @Remove
-   public void remove()
+   public void remove(boolean removeEntities)
    {
-      try
+      if (removeEntities)
       {
-         internalCleanup();
+         try
+         {
+            internalCleanup();
+         }
+         catch (Exception e)
+         {
+            log.error("Caught exception in remove", e);
+         }
       }
-      catch (Exception e)
-      {
-         log.error("Caught exception in remove", e);
-      }
       
       try
       {
          listener.clear();
-         getCache().removeCacheListener(listener);
+         getCache().removeCacheListener(listener);         
       }
       catch (Exception e)
       {
@@ -308,7 +311,7 @@
       }
    }
 
-   private Cache getCache() throws Exception
+   private Cache<Object, Object> getCache() throws Exception
    {
       if (cache == null && cacheConfigName != null)
       {

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -99,7 +99,7 @@
       {
          try
          {
-            sfsb0.remove();
+            sfsb0.remove(true);
          }
          catch (Exception e) {}
       }
@@ -107,7 +107,7 @@
       {
          try
          {
-            sfsb1.remove();
+            sfsb1.remove(true);
          }
          catch (Exception e) {}
       }
@@ -191,8 +191,9 @@
     *                                <code>false</code> if it should be assumed
     *                                the region is activated and able to 
     *                                receive replication events.
+    * @param localOnly TODO
     */
-   protected void queryTest(boolean setupEntities, boolean useNamedQuery, boolean useNamedRegion, boolean expectInactivatedRegion)
+   protected void queryTest(boolean setupEntities, boolean useNamedQuery, boolean useNamedRegion, boolean expectInactivatedRegion, boolean localOnly)
    {
       if (setupEntities)
          standardEntitySetup();
@@ -219,33 +220,33 @@
       // Sleep a bit to allow async repl to happen
       sleep(SLEEP_TIME);
       
-      // If region isn't activated yet, should not have been modified      
-      if (expectInactivatedRegion)
+      // If region is activated and cache isn't localOnly, replication should have been modified
+      boolean modifiedRemotely = sfsb1.getSawRegionModification(regionName);
+      assertEquals("Query cache remotely modified " + regionName, 
+                   !expectInactivatedRegion && !localOnly,
+                   modifiedRemotely);
+      // Clear the access state
+      sfsb1.getSawRegionAccess(regionName);
+      
+      assertEquals("63088 has correct # of accounts", 6, sfsb1.getCountForBranch("63088", useNamedQuery, useNamedRegion));
+      
+      if (!modifiedRemotely)
       {
-         assertFalse("Query cache remotely modified " + regionName, 
+         // If not replicated before, local query should have cached it
+         assertTrue("Query cache modified " + regionName,
                       sfsb1.getSawRegionModification(regionName));
          // Clear the access state
          sfsb1.getSawRegionAccess(regionName);
       }
-      else //if (useNamedRegion)
+      else
       {
-         assertTrue("Query cache remotely modified " + regionName, 
-                    sfsb1.getSawRegionModification(regionName));
-         // Clear the access state
-         sfsb1.getSawRegionAccess(regionName);         
+         // Hibernate may change the query SQL slightly, so we could either
+         // have a modification or an access; either are OK
+         boolean modified = sfsb1.getSawRegionModification(regionName);
+         boolean accessed = sfsb1.getSawRegionAccess(regionName);
+         assertTrue("Query cache used " + regionName, modified || accessed);
       }
       
-      assertEquals("63088 has correct # of accounts", 6, sfsb1.getCountForBranch("63088", useNamedQuery, useNamedRegion));
-      
-      if (expectInactivatedRegion)
-      {
-         // Query should have activated the region and then been inserted
-         assertTrue("Query cache modified " + regionName, 
-                    sfsb1.getSawRegionModification(regionName));
-         // Clear the access state
-         sfsb1.getSawRegionAccess(regionName);
-      }
-      
       log.info("First query on node 1 done");
       
       // We now have the query cache region activated on both nodes.
@@ -272,9 +273,9 @@
       // Do it again from node 1
       
       // First check if the previous queries replicated (if the region is replicable)
-      
-      assertTrue("Query cache remotely modified " + regionName, 
-                 sfsb1.getSawRegionModification(regionName));
+      modifiedRemotely = sfsb1.getSawRegionModification(regionName);
+      assertEquals("Query cache remotely modified " + regionName,
+                   !localOnly, modifiedRemotely);
       // Clear the access state
       sfsb1.getSawRegionAccess(regionName);
       
@@ -282,11 +283,22 @@
       
       assertEquals("Correct high balances for Jones", 40, sfsb1.getTotalBalance(JONES, useNamedQuery, useNamedRegion));
       
-      // Should be no change; query was already there
-      assertFalse("Query cache modified " + regionName, 
-                  sfsb1.getSawRegionModification(regionName));
-      assertTrue("Query cache accessed " + regionName, 
-                 sfsb1.getSawRegionAccess(regionName));
+      if (!modifiedRemotely)
+      {
+         // If not replicated before, local query should have cached it
+         assertTrue("Query cache modified " + regionName,
+                      sfsb1.getSawRegionModification(regionName));
+         // Clear the access state
+         sfsb1.getSawRegionAccess(regionName);
+      }
+      else
+      {
+         // Hibernate may change the query SQL slightly, so we could either
+         // have a modification or an access; either are OK
+         boolean modified = sfsb1.getSawRegionModification(regionName);
+         boolean accessed = sfsb1.getSawRegionAccess(regionName);
+         assertTrue("Query cache used " + regionName, modified || accessed);
+      }
       
       log.info("Second set of queries on node1 done");
       

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -46,19 +46,22 @@
    public void testRedeploy() throws Exception
    {
       // Set things up with the default region
-      queryTest(true, true, false, false);
+      queryTest(true, true, false, false, false);
       // Now get the named query regions active
-      queryTest(false, true, true, true);
+      queryTest(false, true, true, true, false);
       
       redeploy();
       
       // Redo the test, but no entity creation
-      queryTest(false, true, false, false);
-      queryTest(false, true, true, true);
+      queryTest(false, true, false, false, false);
+      queryTest(false, true, true, true, false);
    }
    
    private void redeploy() throws Exception
    {
+      // Get rid of our old sfsb and make sure its listener is removed from cache
+      sfsb1.remove(false);
+      
       MBeanServerConnection[] adaptors = getAdaptors();
       undeploy(adaptors[1], getEarName() + ".ear");
       

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -45,7 +45,7 @@
    public void testManualQueryDefaultRegion() throws Exception
    {
       log.info("+++ start testManualQueryDefaultRegion");
-      queryTest(true, false, false, false);
+      queryTest(true, false, false, false, false);
       log.info("+++ end testManualQueryDefaultRegion");
    }
    
@@ -54,7 +54,7 @@
       log.info("+++ start testManualQueryNamedRegion");
       try
       {
-         queryTest(true, false, true, firstNamedRegionTest);
+         queryTest(true, false, true, firstNamedRegionTest, false);
       }
       finally
       {
@@ -66,7 +66,7 @@
    public void testNamedQueryDefaultRegion() throws Exception
    {    
       log.info("+++ start testNamedQueryDefaultRegion");
-      queryTest(true, true, false, false);
+      queryTest(true, true, false, false, false);
       log.info("+++ end testNamedQueryDefaultRegion");
    }
    
@@ -75,7 +75,7 @@
       log.info("+++ start testNamedQueryNamedRegion");
       try
       {
-         queryTest(true, true, true, firstNamedRegionTest);
+         queryTest(true, true, true, firstNamedRegionTest, false);
       }
       finally
       {

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -45,13 +45,46 @@
    static boolean deployed = false;
    static int test = 0;
 
+   private EntityTest tester0;
+   private EntityTest tester1;
+   
    public EntityUnitTestCase(String name)
    {
-
       super(name);
-
    }
    
+   
+   @Override
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+      
+      if (tester0 != null)
+      {
+         try
+         {
+            tester0.cleanup();
+         }
+         catch (Exception e)
+         {
+            log.error("Problem cleaning up tester0", e);
+         }
+      }
+      
+      if (tester1 != null)
+      {
+         try
+         {
+            tester1.cleanup();
+         }
+         catch (Exception e)
+         {
+            log.error("Problem cleaning up tester1", e);
+         }
+      }
+   }
+
+
    public void testAll() throws Exception
    {
       System.out.println("*** testServerFound()");
@@ -78,63 +111,56 @@
       InitialContext ctx0 = new InitialContext(prop0);
       
       System.out.println("Create node 0");
-      EntityTest tester0 = (EntityTest)ctx0.lookup("EntityTestBean/remote");
+      tester0 = (EntityTest)ctx0.lookup("EntityTestBean/remote");
+      System.out.println("Lookup node 1");
+      InitialContext ctx1 = new InitialContext(prop1);
+      tester1 = (EntityTest)ctx1.lookup("EntityTestBean/remote");
+      
+      tester0.getCache(isOptimistic());
+      
+      Customer customer = tester0.createCustomer();
+      
+      //Call finder twice since Hibernate seems to not actually save collections 
+      //into cache on persist(), so make sure it is put into cache on find.       
+      System.out.println("Find node 0");
+      customer = tester0.findByCustomerId(customer.getId());
+      System.out.println("Find(2) node 0");
+      customer = tester0.findByCustomerId(customer.getId());
+      
+      //Check everything was in cache
+      System.out.println("Check cache 0");
+      try
+      {
+         tester0.loadedFromCache();
+      }
+      catch (Exception e)
+      {
+         log.info("Call to tester0 failed", e);
+         fail(e.getMessage());
+      }
 
+      // The above placement of the collection in the cache is replicated async
+      // so pause a bit before checking node 1
+      sleep(SLEEP_TIME);
+      
+      //Now connect to cache on node2 and make sure it is all there
+      
+      
+      tester1.getCache(isOptimistic());
+      
+      System.out.println("Find node 1");
+      customer = tester1.findByCustomerId(customer.getId());
+
+      //Check everything was in cache
+      System.out.println("Check cache 1");
       try
       {
-         tester0.getCache(isOptimistic());
-         
-         Customer customer = tester0.createCustomer();
-         
-         //Call finder twice since Hibernate seems to not actually save collections 
-         //into cache on persist(), so make sure it is put into cache on find.       
-         System.out.println("Find node 0");
-         customer = tester0.findByCustomerId(customer.getId());
-         System.out.println("Find(2) node 0");
-         customer = tester0.findByCustomerId(customer.getId());
-         
-         //Check everything was in cache
-         System.out.println("Check cache 0");
-         try
-         {
-            tester0.loadedFromCache();
-         }
-         catch (Exception e)
-         {
-            log.info("Call to tester0 failed", e);
-            fail(e.getMessage());
-         }
-   
-         // The above placement of the collection in the cache is replicated async
-         // so pause a bit before checking node 1
-         sleep(SLEEP_TIME);
-         
-         //Now connect to cache on node2 and make sure it is all there
-         System.out.println("Lookup node 1");
-         InitialContext ctx1 = new InitialContext(prop1);
-         
-         EntityTest tester1 = (EntityTest)ctx1.lookup("EntityTestBean/remote");
-         tester1.getCache(isOptimistic());
-         
-         System.out.println("Find node 1");
-         customer = tester1.findByCustomerId(customer.getId());
-   
-         //Check everything was in cache
-         System.out.println("Check cache 1");
-         try
-         {
-            tester1.loadedFromCache();
-         }
-         catch (Exception e)
-         {
-            log.info("Call to tester1 failed", e);
-            fail(e.getMessage());
-         }
+         tester1.loadedFromCache();
       }
-      finally
+      catch (Exception e)
       {
-         // cleanup the db so we can run this test multiple times w/o restarting the cluster
-         tester0.cleanup();
+         log.info("Call to tester1 failed", e);
+         fail(e.getMessage());
       }
    }
 

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -65,6 +65,11 @@
    {
       return EAR_NAME;      
    }
+            
+   protected String getJarName()
+   {
+      return EAR_NAME;
+   }
 
    @Override
    protected boolean isOptimistic()

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java	2008-05-20 14:48:50 UTC (rev 73531)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java	2008-05-20 14:48:58 UTC (rev 73532)
@@ -62,6 +62,11 @@
    {
       return EAR_NAME;      
    }
+            
+   protected String getJarName()
+   {
+      return EAR_NAME;
+   }
 
    @Override
    protected boolean isOptimistic()




More information about the jboss-cvs-commits mailing list