[jboss-cvs] JBossAS SVN: r61096 - in trunk/ejb3: src/main/org/jboss/ejb3/entity and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Mar 5 15:15:01 EST 2007


Author: bstansberry at jboss.com
Date: 2007-03-05 15:15:01 -0500 (Mon, 05 Mar 2007)
New Revision: 61096

Added:
   trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticTreeCacheProviderHook.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEmbeddedIdClassloaderTestCase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityUnitTestCase.java
Modified:
   trunk/ejb3/build-test.xml
   trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java
   trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java
   trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java
   trunk/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EmbeddedIdClassloaderTestCase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java
   trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java
Log:
[EJBTHREE-886] Port OptimisticJBCCache et al to trunk

Modified: trunk/ejb3/build-test.xml
===================================================================
--- trunk/ejb3/build-test.xml	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/build-test.xml	2007-03-05 20:15:01 UTC (rev 61096)
@@ -2896,6 +2896,15 @@
          </fileset>
       </jar>
 
+    <jar jarfile="${build.lib}/clusteredentity-optimistic-test.jar">
+       <fileset dir="${build.classes}">
+          <include name="org/jboss/ejb3/test/clusteredentity/*.class"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/optimistic">
+          <include name="META-INF/persistence.xml"/>
+       </fileset>
+    </jar>
+
       <jar jarfile="${build.lib}/clusteredentity-classloader-test.jar">
          <fileset dir="${build.classes}">
             <include name="org/jboss/ejb3/test/clusteredentity/classloader/*.class"/>
@@ -2905,6 +2914,16 @@
          </fileset>
       </jar>
 
+    <jar jarfile="${build.lib}/clusteredentity-classloader-optimistic-test.jar">
+       <fileset dir="${build.classes}">
+          <include name="org/jboss/ejb3/test/clusteredentity/classloader/*.class"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/classloader/optimistic">
+          <include name="META-INF/persistence.xml"/>
+          <!--include name="META-INF/jboss.xml"/-->
+       </fileset>
+    </jar>
+
     <jar jarfile="${build.lib}/clusteredentity-classloader-test.ear">
        <fileset dir="${build.lib}">
           <include name="clusteredentity-classloader-test.jar"/>
@@ -2916,6 +2935,21 @@
        </fileset>
     </jar>
 
+    <jar jarfile="${build.lib}/clusteredentity-classloader-optimistic-test.ear">
+       <fileset dir="${build.lib}">
+          <include name="clusteredentity-classloader-optimistic-test.jar"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/classloader">
+          <include name="META-INF/jboss-app.xml"/>
+          <include name="clusteredentity-ds.xml"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/classloader/optimistic">
+          <include name="META-INF/application.xml"/>
+          <include name="META-INF/jboss-app.xml"/>
+          <include name="clusteredentity-ds.xml"/>
+       </fileset>
+    </jar>
+
     <jar jarfile="${build.lib}/clusteredentity-embeddedid-test.jar">
        <fileset dir="${build.classes}">
           <include name="org/jboss/ejb3/test/clusteredentity/embeddedid/*.class"/>
@@ -2925,6 +2959,16 @@
        </fileset>
     </jar>
 
+    <jar jarfile="${build.lib}/clusteredentity-embeddedid-optimistic-test.jar">
+       <fileset dir="${build.classes}">
+          <include name="org/jboss/ejb3/test/clusteredentity/embeddedid/*.class"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/classloader/optimistic">
+          <include name="META-INF/persistence.xml"/>
+          <!--include name="META-INF/jboss.xml"/-->
+       </fileset>
+    </jar>
+
     <jar jarfile="${build.lib}/clusteredentity-embeddedid-test.ear">
        <fileset dir="${build.lib}">
           <include name="clusteredentity-embeddedid-test.jar"/>
@@ -2937,6 +2981,26 @@
          <include name="META-INF/application.xml"/>
        </fileset>
     </jar>
+
+    <jar jarfile="${build.lib}/clusteredentity-embeddedid-optimistic-test.ear">
+       <fileset dir="${build.lib}">
+          <include name="clusteredentity-embeddedid-optimistic-test.jar"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/classloader">
+          <include name="META-INF/jboss-app.xml"/>
+          <include name="clusteredentity-ds.xml"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/embeddedid/optimistic">
+         <include name="META-INF/application.xml"/>
+       </fileset>
+    </jar>
+    
+    <!-- Copy the optimistic locking JBC config to ${build.lib} so we can deploy it -->
+    <copy todir="${build.lib}">
+       <fileset dir="${resources}/test/clusteredentity/optimistic">
+          <include name="optimistic-entity-cache-*.xml"/>
+       </fileset>
+    </copy>
    
    </target>
 

Modified: trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -25,7 +25,12 @@
    {
        try
        {
-          ObjectName mbeanObjectName = new ObjectName((String) hibernateConfig.get("hibernate.treecache.mbean.object_name"));
+          String cacheName = (String) hibernateConfig.get(TreeCacheProviderHook.HIBERNATE_CACHE_OBJECT_NAME_PROPERTY);
+          if (cacheName == null)
+          {
+             cacheName = TreeCacheProviderHook.DEFAULT_MBEAN_OBJECT_NAME;
+          }
+          ObjectName mbeanObjectName = new ObjectName(cacheName);
           CacheJmxWrapperMBean mbean = (CacheJmxWrapperMBean) MBeanProxyExt.create(CacheJmxWrapperMBean.class, mbeanObjectName, MBeanServerLocator.locateJBoss());
           cache = mbean.getCache();
           optimistic = cache.getConfiguration().isNodeLockingOptimistic();
@@ -38,14 +43,19 @@
    
    public Cache buildCache(String regionName, Properties properties) throws CacheException
    {
-//      if (optimistic)
-//      {
-//         return new OptimisticJBCCache(cache, regionName);
-//      }
-//      else
-//      {
+      if (optimistic)
+      {
+         return new OptimisticJBCCache(cache, regionName);
+      }
+      else
+      {
          return new JBCCache(cache, regionName, TxUtil.getTransactionManager());
-//      }
+      }
    }
+   
+   public boolean isOptimistic()
+   {
+      return optimistic;
+   }
 
 }

Modified: trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -1,409 +1,479 @@
-package org.jboss.ejb3.entity;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-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.jboss.cache.Fqn;
-import org.jboss.cache.InvocationContext;
-import org.jboss.cache.Node;
-import org.jboss.cache.config.Option;
-import org.jboss.cache.lock.TimeoutException;
-import org.jboss.cache.optimistic.DataVersion;
-
-public class OptimisticJBCCache implements OptimisticCache
-{
-    // todo : eventually merge this with TreeCache and just add optional opt-lock support there.
-
-    private static final Log log = LogFactory.getLog( OptimisticJBCCache.class);
-
-    private static final String ITEM = "item";
-
-    private static final Option NONLOCKING_OPTION = new Option();
-    private static final Option FAIL_SILENT_OPTION = new Option();
-    private static final Option FAIL_SILENT_NONLOCKING_OPTION = new Option();
-    
-    static
-    {
-       FAIL_SILENT_OPTION.setFailSilently( true );
-       
-       FAIL_SILENT_NONLOCKING_OPTION.setFailSilently( true );
-       FAIL_SILENT_NONLOCKING_OPTION.setDataVersion( NonLockingDataVersion.INSTANCE );
-       NONLOCKING_OPTION.setDataVersion( NonLockingDataVersion.INSTANCE );        
-    }
-    
-    private org.jboss.cache.Cache cache;
-    private final String regionName;
-    private final Fqn regionFqn;
-    private OptimisticCacheSource source;
-
-    public OptimisticJBCCache(org.jboss.cache.Cache cache, String regionName)
-    throws CacheException {
-        this.cache = cache;
-        this.regionName = regionName;
-        this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
-    }
-
-
-    // OptimisticCache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    public void setSource(OptimisticCacheSource source) {
-        this.source = source;
-    }
-
-    public void writeInsert(Object key, Object value, Object currentVersion) {
-        writeUpdate( key, value, currentVersion, null );
-    }
-
-    public void writeUpdate(Object key, Object value, Object currentVersion, Object previousVersion) 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-            Option option = new Option();
-            DataVersion dv = ( source != null && source.isVersioned() )
-                             ? new DataVersionAdapter( currentVersion, previousVersion, source.getVersionComparator(), source.toString() )
-                             : NonLockingDataVersion.INSTANCE;
-            option.setDataVersion( dv );
-            
-            ctx.setOptionOverrides(option);
-            cache.put( new Fqn( regionFqn, key ), ITEM, value);
-        }
-        catch ( Exception e ) {
-            throw new CacheException( e );
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    public void writeLoad(Object key, Object value, Object currentVersion) 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-           
-            ctx.setOptionOverrides(FAIL_SILENT_NONLOCKING_OPTION);
-            cache.remove( new Fqn( regionFqn, key ), "ITEM");
-
-            Option 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 );
-            
-            ctx = cache.getInvocationContext();
-            ctx.setOptionOverrides(option);
-            cache.put( new Fqn( regionFqn, key ), ITEM, value);
-        }
-        catch (Exception e) {
-            throw new CacheException(e);
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-
-    // Cache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    public Object get(Object key) throws CacheException 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-            
-//            ctx.setOptionOverrides(FAIL_SILENT_NONLOCKING_OPTION);
-            ctx.setOptionOverrides(FAIL_SILENT_OPTION);
-            return cache.get( new Fqn( regionFqn, key ), ITEM);
-        }
-        catch (Exception e) {
-            throw new CacheException(e);
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    public Object read(Object key) throws CacheException {
-        try {
-            return cache.get( new Fqn( regionFqn, key ), ITEM );
-        }
-        catch (Exception e) {
-            throw new CacheException(e);
-        }
-    }
-
-    public void update(Object key, Object value) throws CacheException 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-            ctx.setOptionOverrides(NONLOCKING_OPTION);
-            cache.put( new Fqn( regionFqn, key ), ITEM, value );
-        }
-        catch (Exception e) {
-            throw new CacheException(e);
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    public void put(Object key, Object value) throws CacheException 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-            log.trace( "performing put() into region [" + regionName + "]" );
-            // do the put outside the scope of the JTA txn
-            ctx.setOptionOverrides(FAIL_SILENT_NONLOCKING_OPTION);
-            cache.put( new Fqn( regionFqn, key ), ITEM, value );
-        }
-        catch (TimeoutException te) {
-            //ignore!
-            log.debug("ignoring write lock acquisition failure");
-        }
-        catch (Exception e) {
-            throw new CacheException(e);
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    public void remove(Object key) throws CacheException 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        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 );
-                ctx.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 new CacheException(e);
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    public void clear() throws CacheException 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-            Option option = new Option();
-            option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            ctx.setOptionOverrides(option);
-            cache.removeNode( regionFqn );
-        }
-        catch (Exception e) {
-            throw new CacheException(e);
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    public void destroy() throws CacheException 
-    {
-       InvocationContext ctx = cache.getInvocationContext();
-       Option existing = ctx.getOptionOverrides();
-        try {
-            Option option = new Option();
-            option.setCacheModeLocal( true );
-            option.setFailSilently( true );
-            option.setDataVersion( NonLockingDataVersion.INSTANCE );
-            ctx.setOptionOverrides(option);
-            cache.removeNode( regionFqn );
-        }
-        catch( Exception e ) {
-            throw new CacheException( e );
-        }
-        finally
-        {
-           ctx.setOptionOverrides(existing);
-        }
-    }
-
-    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 new CacheException(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 new CacheException(e);
-        }
-    }
-    
-    private Set getChildrenNames()
-    {
-       try {
-          Node base = cache.getRoot().getChild( regionFqn );
-          return base == null ? null : base.getChildrenNames();
-       }
-       catch (Exception e) {
-          throw new CacheException(e);
-       }   
-    }
-
-    public String toString() {
-        return "OptimisticTreeCache(" + regionName + ')';
-    }
-
-    public static class DataVersionAdapter implements DataVersion {
-        private final Object currentVersion;
-        private final Object previousVersion;
-        private final Comparator versionComparator;
-        private final String sourceIdentifer;
-
-        public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator, String sourceIdentifer) {
-            this.currentVersion = currentVersion;
-            this.previousVersion = previousVersion;
-            this.versionComparator = versionComparator;
-            this.sourceIdentifer = sourceIdentifer;
-            log.trace( "created " + this );
-        }
-
-        /**
-         * newerThan() call is dispatched against the DataVersion currently
-         * associated with the node; the passed dataVersion param is the
-         * DataVersion associated with the data we are trying to put into
-         * the node.
-         * <p/>
-         * we are expected to return true in the case where we (the current
-         * node DataVersion) are newer that then incoming value.  Returning
-         * true here essentially means that a optimistic lock failure has
-         * occured (because conversely, the value we are trying to put into
-         * the node is "older than" the value already there...)
-         */
-        public boolean newerThan(DataVersion dataVersion) {
-            log.trace( "checking [" + this + "] against [" + dataVersion + "]" );
-            if ( dataVersion instanceof CircumventChecksDataVersion ) {
-                log.trace( "skipping lock checks..." );
-                return false;
-            }
-            else if ( dataVersion instanceof NonLockingDataVersion ) {
-                // can happen because of the multiple ways Cache.remove()
-                // can be invoked :(
-                log.trace( "skipping lock checks..." );
-                return false;
-            }
-            DataVersionAdapter other = ( DataVersionAdapter ) dataVersion;
-            if ( other.previousVersion == null ) {
-                log.warn( "Unexpected optimistic lock check on inserting data" );
-                // work around the "feature" where tree cache is validating the
-                // inserted node during the next transaction.  no idea...
-                if ( this == dataVersion ) {
-                    log.trace( "skipping lock checks due to same DV instance" );
-                    return false;
-                }
-            }
-            return versionComparator.compare( currentVersion, other.previousVersion ) >= 1;
-        }
-
-        public String toString() {
-            return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src=" + sourceIdentifer + "]";
-        }
-    }
-
-    /**
-     * Used in regions where no locking should ever occur.  This includes query-caches,
-     * update-timestamps caches, collection caches, and entity caches where the entity
-     * is not versioned.
-     */
-    public static class NonLockingDataVersion implements DataVersion {
-        public static final DataVersion INSTANCE = new NonLockingDataVersion();
-        public boolean newerThan(DataVersion dataVersion) {
-            log.trace( "non locking lock check...");
-            return false;
-        }
-    }
-
-    /**
-     * Used to signal to a DataVersionAdapter to simply not perform any checks.  This
-     * is currently needed for proper handling of remove() calls for entity cache regions
-     * (we do not know the version info...).
-     */
-    public static class CircumventChecksDataVersion implements DataVersion {
-        public static final DataVersion INSTANCE = new CircumventChecksDataVersion();
-        public boolean newerThan(DataVersion dataVersion) {
-            throw new CacheException( "optimistic locking checks should never happen on CircumventChecksDataVersion" );
-        }
-    }
-
-}
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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 java.util.Comparator;
+
+
+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.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.Region;
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+
+/**
+ * Represents a particular region within the given JBossCache TreeCache
+ * utilizing TreeCache's optimistic locking capabilities.
+ *
+ * @see org.hibernate.cache.OptimisticTreeCacheProvider for more details
+ *
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ */
+public class OptimisticJBCCache implements OptimisticCache {
+
+	// todo : eventually merge this with TreeCache and just add optional opt-lock support there.
+
+	private static final Log log = LogFactory.getLog( OptimisticJBCCache.class);
+
+	private static final String ITEM = "item";
+
+	private org.jboss.cache.Cache cache;
+	private final String regionName;
+	private final Fqn regionFqn;
+	private OptimisticCacheSource source;
+    private boolean localWritesOnly;
+
+	public OptimisticJBCCache(org.jboss.cache.Cache cache, String regionName)
+	throws CacheException {
+		this.cache = cache;
+		this.regionName = regionName;
+		this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
+        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");
+        }
+	}
+
+
+	// OptimisticCache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void setSource(OptimisticCacheSource source) {
+		this.source = source;
+	}
+
+	public void writeInsert(Object key, Object value, Object currentVersion) {
+		writeUpdate( key, value, currentVersion, null );
+	}
+
+	public void writeUpdate(Object key, Object value, Object currentVersion, Object previousVersion) {
+		try {
+			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);
+            cache.getInvocationContext().setOptionOverrides(option);
+			cache.put( new Fqn( regionFqn, key ), ITEM, value );
+		}
+		catch ( Exception e ) {
+			throw new CacheException( e );
+		}
+	}
+
+	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" );
+
+			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 new CacheException(e);
+		}
+	}
+
+
+	// 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);
+			return cache.get( new Fqn( regionFqn, key ), ITEM );
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public Object read(Object key) throws CacheException {
+		try {
+			return cache.get( new Fqn( regionFqn, key ), ITEM );
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void update(Object key, Object value) throws CacheException {
+		try {
+			Option option = new Option();
+			option.setDataVersion( NonLockingDataVersion.INSTANCE );
+            option.setCacheModeLocal(localWritesOnly);
+            cache.getInvocationContext().setOptionOverrides(option);
+			cache.put( new Fqn( regionFqn, key ), ITEM, value );
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void put(Object key, Object value) throws CacheException {
+		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 );
+		}
+		catch (TimeoutException te) {
+			//ignore!
+			log.debug("ignoring write lock acquisition failure");
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	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 new CacheException(e);
+		}
+	}
+
+	public void clear() throws CacheException {
+		try {
+			Option option = new Option();
+			option.setDataVersion( NonLockingDataVersion.INSTANCE );
+            option.setCacheModeLocal(localWritesOnly);
+            cache.getInvocationContext().setOptionOverrides(option);
+			cache.removeNode( regionFqn );
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void destroy() throws CacheException {
+		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))
+            {
+               inactivateCacheRegion();
+            }
+		}
+		catch( Exception e ) {
+			throw new CacheException( 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 new CacheException(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 new CacheException(e);
+		}
+	}
+    
+    private Set getChildrenNames()
+    {
+       try {
+          Node base = cache.getRoot().getChild( regionFqn );
+          return base == null ? null : base.getChildrenNames();
+       }
+       catch (Exception e) {
+          throw new CacheException(e);
+       }   
+    }
+
+	public String toString() {
+		return "OptimisticTreeCache(" + 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 new CacheException("Problem activating region " + regionFqn, 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 new CacheException("Problem inactivating region " + regionFqn, 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 String sourceIdentifer;
+
+		public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator, String sourceIdentifer) {
+			this.currentVersion = currentVersion;
+			this.previousVersion = previousVersion;
+			this.versionComparator = versionComparator;
+			this.sourceIdentifer = sourceIdentifer;
+			log.trace( "created " + this );
+		}
+
+		/**
+		 * newerThan() call is dispatched against the DataVersion currently
+		 * associated with the node; the passed dataVersion param is the
+		 * DataVersion associated with the data we are trying to put into
+		 * the node.
+		 * <p/>
+		 * we are expected to return true in the case where we (the current
+		 * node DataVersion) are newer that then incoming value.  Returning
+		 * true here essentially means that a optimistic lock failure has
+		 * occured (because conversely, the value we are trying to put into
+		 * the node is "older than" the value already there...)
+		 */
+		public boolean newerThan(DataVersion dataVersion) {
+			log.trace( "checking [" + this + "] against [" + dataVersion + "]" );
+			if ( dataVersion instanceof CircumventChecksDataVersion ) {
+				log.trace( "skipping lock checks..." );
+				return false;
+			}
+			else if ( dataVersion instanceof NonLockingDataVersion ) {
+				// can happen because of the multiple ways Cache.remove()
+				// can be invoked :(
+				log.trace( "skipping lock checks..." );
+				return false;
+			}
+			DataVersionAdapter other = ( DataVersionAdapter ) dataVersion;
+			if ( other.previousVersion == null ) {
+				log.warn( "Unexpected optimistic lock check on inserting data" );
+				// work around the "feature" where tree cache is validating the
+				// inserted node during the next transaction.  no idea...
+				if ( this == dataVersion ) {
+					log.trace( "skipping lock checks due to same DV instance" );
+					return false;
+				}
+			}
+            
+            if (currentVersion == null)
+            {
+               // If the workspace node has null as well, OK; if not we've
+               // been modified in a non-comparable manner, which we have to
+               // treat as us being newer 
+               return (other.previousVersion != null);
+            }
+            
+			return versionComparator.compare( currentVersion, other.previousVersion ) >= 1;
+		}
+
+		public String toString() {
+			return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src=" + sourceIdentifer + "]";
+		}
+	}
+
+	/**
+	 * Used in regions where no locking should ever occur.  This includes query-caches,
+	 * update-timestamps caches, collection caches, and entity caches where the entity
+	 * is not versioned.
+	 */
+	public static class NonLockingDataVersion implements DataVersion 
+    {
+        private static final long serialVersionUID = 7050722490368630553L;
+		public static final DataVersion INSTANCE = new NonLockingDataVersion();
+		public boolean newerThan(DataVersion dataVersion) {
+			log.trace( "non locking lock check...");
+			return false;
+		}
+	}
+
+	/**
+	 * Used to signal to a DataVersionAdapter to simply not perform any checks.  This
+	 * is currently needed for proper handling of remove() calls for entity cache regions
+	 * (we do not know the version info...).
+	 */
+	public static class CircumventChecksDataVersion implements DataVersion  
+    {
+        private static final long serialVersionUID = 7996980646166032369L;
+		public static final DataVersion INSTANCE = new CircumventChecksDataVersion();
+		public boolean newerThan(DataVersion dataVersion) {
+			throw new CacheException( "optimistic locking checks should never happen on CircumventChecksDataVersion" );
+		}
+	}
+}

Copied: trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticTreeCacheProviderHook.java (from rev 61058, branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/OptimisticTreeCacheProviderHook.java)
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticTreeCacheProviderHook.java	                        (rev 0)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticTreeCacheProviderHook.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ * 
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.ejb3.entity;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheException;
+
+/**
+ * Trivial {@link TreeCacheProviderHook} subclass that logs a warning in
+ * {@link #start(Properties) start} if the underlying JBoss Cache 
+ * is not configured for optimistic locking.  Like the superclass,
+ * will provide working Cache implementations whether JBoss Cache is
+ * configured for optimistic locking or not; the only added behavior
+ * is the logging of the warning if the JBoss Cache configuration doesn't 
+ * match the intent implied by the use of this class.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ * @author Brian Stansberry
+ */
+public class OptimisticTreeCacheProviderHook 
+   extends TreeCacheProviderHook 
+{
+   public void start(Properties properties) throws CacheException
+   {
+      super.start(properties);
+      
+      if (getCacheFactory().isOptimistic() == false)
+      {
+         log.warn("JBoss Cache is not configured for optimistic locking; " +
+         "provided Cache implementations therefore will not implement OptimisticCache");
+      }
+   }
+
+}

Modified: trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -73,4 +73,12 @@
     */
    protected abstract void configure(Properties hibernateConfig);
    
+   /**
+    * Gets whether the underlying JBoss Cache instance is configured
+    * for optimistic locking.
+    * 
+    * @return <code>true</code> if the JBoss Cache uses optimistic locking;
+    *         <code>false</code> if it uses pessimistic locking
+    */
+   public abstract boolean isOptimistic();
 }

Modified: trunk/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -26,16 +26,38 @@
 import org.hibernate.cache.Cache;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.CacheProvider;
+import org.jboss.logging.Logger;
 
 /**
- * Support for a standalone JBossCache (TreeCache) instance.  The JBossCache is configured
- * via a local config resource.
- *
+ * Support for integration as a 2nd level cache with an already existing 
+ * JBoss Cache (TreeCache) instance.  The ObjectName of the cache is 
+ * provided via the <code>hibernate.treecache.mbean.object_name</code>
+ * configuration property.
+ * <p/>
+ * This class supports both optimistic and pessimistic locking, providing
+ * instances of <code>org.hibernate.cache.OptimisticCache</code> if the 
+ * underlying JBoss Cache is configured for optimistic locking.
+ * 
  * @author Gavin King
  * @author Brian Stansberry
  */
 public class TreeCacheProviderHook implements CacheProvider
 {
+   /**
+    * Name of the Hibernate configuration property used to provide
+    * the ObjectName of the JBoss Cache instance.
+    */
+   public static final String HIBERNATE_CACHE_OBJECT_NAME_PROPERTY = 
+      "hibernate.treecache.mbean.object_name";
+   
+   /**
+    * Default ObjectName for the JBoss Cache instance that will be used
+    * if {@link HIBERNATE_CACHE_OBJECT_NAME_PROPERTY} is not provided.
+    */
+   public static final String DEFAULT_MBEAN_OBJECT_NAME = "jboss.cache:service=EJB3EntityTreeCache";
+   
+   protected Logger log = Logger.getLogger(getClass());
+   
    private TransactionalCacheFactory cacheFactory;
 
    /**
@@ -49,7 +71,6 @@
     */
    public Cache buildCache(String regionName, Properties properties) throws CacheException
    {
-//      return new TreeCache(cache, regionName, TxUtil.getTransactionManager());
       return cacheFactory.buildCache(regionName, properties);
    }
 
@@ -64,29 +85,27 @@
    }
 
    /**
-    * Prepare the underlying JBossCache TreeCache instance.
+    * Find the underlying JBoss Cache TreeCache instance.
     *
-    * @param properties All current config settings.
+    * @param properties  All current config settings. 
+    *                    If {@link #HIBERNATE_CACHE_OBJECT_NAME_PROPERTY} is provided,
+    *                    the value will be the expected name of the cache; otherwise
+    *                    {@link #DEFAULT_MBEAN_OBJECT_NAME} will be used.
     * @throws org.hibernate.cache.CacheException
     *          Indicates a problem preparing cache for use.
     */
    public void start(Properties properties)
    {
       cacheFactory = TransactionalCacheFactory.getFactory(properties);
-//      try
-//      {
-//         ObjectName mbeanObjectName = new ObjectName((String) properties.get("hibernate.treecache.mbean.object_name"));
-//         TreeCacheMBean mbean = (TreeCacheMBean) MBeanProxyExt.create(TreeCacheMBean.class, mbeanObjectName, MBeanServerLocator.locateJBoss());
-//         cache = mbean.getInstance();
-//      }
-//      catch (Exception e)
-//      {
-//         throw new CacheException(e);
-//      }
    }
 
    public void stop()
    {
    }
+   
+   protected TransactionalCacheFactory getCacheFactory()
+   {
+      return cacheFactory;
+   }
 
 }

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -31,6 +31,8 @@
  */
 public interface EntityTest
 {
+   void getCache(boolean optimistic);
+   
    Customer createCustomer();
 
    Customer findByCustomerId(Integer id);

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -25,6 +25,7 @@
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.annotation.PreDestroy;
 import javax.ejb.Remote;
 import javax.ejb.Remove;
 import javax.ejb.Stateless;
@@ -36,11 +37,10 @@
 import org.jboss.cache.AbstractCacheListener;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.Cache;
-import org.jboss.cache.CacheListener;
 import org.jboss.cache.jmx.CacheJmxWrapperMBean;
+import org.jboss.logging.Logger;
 import org.jboss.mx.util.MBeanProxyExt;
 import org.jboss.mx.util.MBeanServerLocator;
-import org.jgroups.View;
 
 /**
  * Comment
@@ -52,13 +52,28 @@
 @Remote(EntityTest.class)
 public class EntityTestBean implements EntityTest
 {
+   private static final Logger log = Logger.getLogger(EntityTestBean.class);
+   
    @PersistenceContext
    private EntityManager manager;
    
+   private String cacheObjectName;
+   
+   private transient Cache cache;
+   
    static MyListener listener;
 
    public EntityTestBean()
    {
+   }
+   
+   public void getCache(boolean optimistic)
+   {
+      if (optimistic)
+         cacheObjectName = "jboss.cache:service=OptimisticEJB3EntityTreeCache";
+      else
+         cacheObjectName = "jboss.cache:service=EJB3EntityTreeCache";
+
       try
       {
          //Just to initialise the cache with a listener
@@ -106,9 +121,13 @@
          manager.persist(customer);
          return customer;
       }
+      catch (RuntimeException e)
+      {
+         throw e;
+      }
       catch (Exception e)
       {
-         throw new RuntimeException(e); // TODO Auto-generated catch block
+         throw new RuntimeException(e);
       }
       finally
       {
@@ -126,9 +145,13 @@
          
          return customer;
       }
+      catch (RuntimeException e)
+      {
+         throw e;
+      }
       catch (Exception e)
       {
-         throw new RuntimeException(e); // TODO Auto-generated catch block
+         throw new RuntimeException(e);
       }
       finally
       {
@@ -158,26 +181,51 @@
       
    }
    
+   @PreDestroy
    @Remove
    public void cleanup()
    {
-      Customer c = findByCustomerId(1);
-      if (c != null)
+      try
+      {         
+         if (listener != null)
+         {
+            getCache().removeCacheListener(listener);
+         }
+      }
+      catch (Exception e)
       {
-         Set contacts = c.getContacts();
-         for (Iterator it = contacts.iterator(); it.hasNext();)
-            manager.remove(it.next());
-         c.setContacts(null);
-         manager.remove(c);
+         log.error("Caught exception in cleanup", e);
       }
+      
+      try
+      {
+         if (manager != null)
+         {
+            Customer c = findByCustomerId(1);
+            if (c != null)
+            {
+               Set contacts = c.getContacts();
+               for (Iterator it = contacts.iterator(); it.hasNext();)
+                  manager.remove(it.next());
+               c.setContacts(null);
+               manager.remove(c);
+            }
+         }
+      }
+      catch (Exception e)
+      {
+         log.error("Caught exception in cleanup", e);
+      }
    }
 
    private Cache getCache() throws Exception
    {
-      MBeanServer server = MBeanServerLocator.locateJBoss();
-      CacheJmxWrapperMBean proxy = (CacheJmxWrapperMBean)MBeanProxyExt.create(CacheJmxWrapperMBean.class, new ObjectName("jboss.cache:service=EJB3EntityTreeCache"), server);
-      Cache cache = proxy.getCache();
-      
+      if (cache == null)
+      {
+         MBeanServer server = MBeanServerLocator.locateJBoss();
+         CacheJmxWrapperMBean proxy = (CacheJmxWrapperMBean)MBeanProxyExt.create(CacheJmxWrapperMBean.class, new ObjectName(cacheObjectName), server);
+         cache = proxy.getCache();
+      }
       return cache;
    }
 
@@ -199,10 +247,13 @@
             String name = fqn.toString();
             String token = ".clusteredentity.";
             int index = name.indexOf(token);
-            index += token.length();
-            name = name.substring(index);
-            System.out.println(name);
-            visited.add(name);
+            if (index > -1)
+            {
+               index += token.length();
+               name = name.substring(index);
+               System.out.println("MyListener - recording visit to " + name);
+               visited.add(name);
+            }
          }
       }
    }

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTest.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -1,7 +1,35 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.test.clusteredentity.classloader;
 
+/**
+ * Comment
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 60233 $
+ */
 public interface EntityQueryTest
 {
+   public abstract void getCache(boolean optimistic);
 
 //   public abstract void createAccountHolder(AccountHolderPK pk, String postCode);
    

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/classloader/EntityQueryTestBean.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -1,3 +1,24 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.test.clusteredentity.classloader;
 
 import java.util.HashSet;
@@ -6,6 +27,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.PreDestroy;
 import javax.ejb.Remote;
 import javax.ejb.Remove;
 import javax.ejb.Stateful;
@@ -23,6 +45,12 @@
 import org.jboss.mx.util.MBeanProxyExt;
 import org.jboss.mx.util.MBeanServerLocator;
 
+/**
+ * Comment
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 60233 $
+ */
 @Stateful
 @Remote(EntityQueryTest.class)
 public class EntityQueryTestBean implements EntityQueryTest
@@ -32,10 +60,21 @@
    @PersistenceContext
    private EntityManager manager;
    
+   private String cacheObjectName;
+   
    private MyListener listener;
 
    public EntityQueryTestBean()
+   {      
+   }
+   
+   public void getCache(boolean optimistic)
    {
+      if (optimistic)
+         cacheObjectName = "jboss.cache:service=OptimisticEJB3EntityTreeCache";
+      else
+         cacheObjectName = "jboss.cache:service=EJB3EntityTreeCache";
+
       try
       {
          //Just to initialise the cache with a listener
@@ -203,43 +242,60 @@
    }
    
    public void cleanup()
+   {
+      internalCleanup();
+   }
+   
+   private void internalCleanup()
    {  
-      Query query = manager.createQuery("select account from Account as account");
-      List accts = query.getResultList();
-      if (accts != null)
+      if (manager != null)
       {
-         for (Iterator it = accts.iterator(); it.hasNext();)
+         Query query = manager.createQuery("select account from Account as account");
+         List accts = query.getResultList();
+         if (accts != null)
          {
-            try
+            for (Iterator it = accts.iterator(); it.hasNext();)
             {
-               Account acct = (Account) it.next();
-               log.info("Removing " + acct);
-               manager.remove(acct);
+               try
+               {
+                  Account acct = (Account) it.next();
+                  log.info("Removing " + acct);
+                  manager.remove(acct);
+               }
+               catch (Exception ignored) {}
             }
-            catch (Exception ignored) {}
          }
-      }
+      }      
    }
    
+   @PreDestroy
    @Remove
    public void remove()
    {
-      cleanup();
-      listener.clear();
       try
       {
+         internalCleanup();
+      }
+      catch (Exception e)
+      {
+         log.error("Caught exception in remove", e);
+      }
+      
+      try
+      {
+         listener.clear();
          getCache().removeCacheListener(listener);
       }
       catch (Exception e)
       {
-         e.printStackTrace();
+        log.error("Caught exception in remove", e);
       }
    }
 
    private Cache getCache() throws Exception
    {
       MBeanServer server = MBeanServerLocator.locateJBoss();
-      CacheJmxWrapperMBean proxy = (CacheJmxWrapperMBean)MBeanProxyExt.create(CacheJmxWrapperMBean.class, new ObjectName("jboss.cache:service=EJB3EntityTreeCache"), server);
+      CacheJmxWrapperMBean proxy = (CacheJmxWrapperMBean)MBeanProxyExt.create(CacheJmxWrapperMBean.class, new ObjectName(cacheObjectName), server);
       Cache cache = proxy.getCache();
       
       return cache;

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EmbeddedIdClassloaderTestCase.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EmbeddedIdClassloaderTestCase.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EmbeddedIdClassloaderTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -23,18 +23,16 @@
 
 import java.util.List;
 import java.util.Properties;
-import java.util.Set;
 
 import javax.naming.InitialContext;
-import org.jboss.ejb3.test.clusteredentity.Customer;
-import org.jboss.ejb3.test.clusteredentity.EntityTest;
-import org.jboss.ejb3.test.clusteredentity.classloader.EntityQueryTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.ejb3.test.clusteredentity.embeddedid.EmbeddedIdTest;
 import org.jboss.ejb3.test.clusteredentity.embeddedid.MusicianPK;
-import org.jboss.ejb3.test.clusteredentity.embeddedid.EmbeddedIdTest;
 import org.jboss.ejb3.test.common.unit.DBSetup;
 import org.jboss.test.JBossClusteredTestCase;
-import junit.framework.Test;
-import junit.framework.TestSuite;
 
 /**
  * Simple test of replication of entities and related queries with @EmbeddedId 
@@ -103,10 +101,15 @@
       InitialContext ctx1 = new InitialContext(prop1);
    
       log.info("Lookup sfsb from " + nodeJNDIAddress);
-      return (EmbeddedIdTest) ctx1.lookup("clusteredentity-embeddedid-test/EmbeddedIdTestBean/remote");
+      return (EmbeddedIdTest) ctx1.lookup(getEarName() + "/EmbeddedIdTestBean/remote");
       
    }
    
+   protected String getEarName()
+   {
+      return "clusteredentity-embeddedid-test";
+   }
+   
    public void testQuery() throws Exception
    {
       try

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -25,14 +25,10 @@
 import javax.naming.InitialContext;
 
 import org.hibernate.cache.StandardQueryCache;
-import org.jboss.ejb3.test.clusteredentity.classloader.Account;
 import org.jboss.ejb3.test.clusteredentity.classloader.AccountHolderPK;
 import org.jboss.ejb3.test.clusteredentity.classloader.EntityQueryTest;
 import org.jboss.test.JBossClusteredTestCase;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 /**
  * Base class for tests involving clustered entities with a scoped classloader.
  *
@@ -43,6 +39,8 @@
 public class EntityClassloaderTestBase
 extends JBossClusteredTestCase
 {
+   public static final String EAR_NAME = "clusteredentity-classloader-test";
+   
    protected org.jboss.logging.Logger log = getLog();
 
    protected static final long SLEEP_TIME = 300L;
@@ -87,8 +85,10 @@
       InitialContext ctx1 = new InitialContext(prop1);
    
       log.info("Lookup sfsb from " + nodeJNDIAddress);
-      return (EntityQueryTest)ctx1.lookup("clusteredentity-classloader-test/EntityQueryTestBean/remote");
+      EntityQueryTest eqt = (EntityQueryTest)ctx1.lookup(getEarName() + "/EntityQueryTestBean/remote");
+      eqt.getCache(isOptimistic());
       
+      return eqt;
    }
     
    protected void tearDown() throws Exception
@@ -297,4 +297,14 @@
          log.warn("Interrupted while sleeping", e);
       }
    }
+   
+   protected String getEarName()
+   {
+      return EAR_NAME;
+   }
+
+   protected boolean isOptimistic()
+   {
+      return false;
+   }
 }

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -21,13 +21,6 @@
  */
 package org.jboss.ejb3.test.clusteredentity.unit;
 
-import java.util.Properties;
-import javax.naming.InitialContext;
-
-import org.hibernate.cache.StandardQueryCache;
-import org.jboss.ejb3.test.clusteredentity.classloader.Account;
-import org.jboss.ejb3.test.clusteredentity.classloader.AccountHolderPK;
-import org.jboss.ejb3.test.clusteredentity.classloader.EntityQueryTest;
 import org.jboss.ejb3.test.common.unit.DBSetup;
 import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
 
@@ -44,9 +37,6 @@
 public class EntityQueryRedeployUnitTestCase
 extends EntityClassloaderTestBase
 {
-   private static boolean firstNamedRegionTest = true;
-   private static final String EAR_NAME = "clusteredentity-classloader-test.ear";
-   
    public EntityQueryRedeployUnitTestCase(String name)
    {
       super(name);
@@ -59,9 +49,6 @@
       // Now get the named query regions active
       queryTest(false, true, true, true);
       
-      // Don't set this false, as after redeploy it's as if its the first test
-//      firstNamedRegionTest = false;
-      
       redeploy();
       
       // Redo the test, but no entity creation
@@ -72,11 +59,11 @@
    private void redeploy() throws Exception
    {
       RMIAdaptor[] adaptors = getAdaptors();
-      undeploy(adaptors[1], EAR_NAME);
+      undeploy(adaptors[1], getEarName() + ".ear");
       
       sleep(2000);
       
-      deploy(adaptors[1], EAR_NAME);
+      deploy(adaptors[1], getEarName() + ".ear");
       
       sleep(2000);
       
@@ -88,7 +75,7 @@
    public static Test suite() throws Exception
    {
       TestSuite suite = new TestSuite();
-      Test t1 = getDeploySetup(EntityQueryRedeployUnitTestCase.class, EAR_NAME);
+      Test t1 = getDeploySetup(EntityQueryRedeployUnitTestCase.class, EAR_NAME + ".ear");
 
       suite.addTest(t1);
 

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -21,18 +21,11 @@
  */
 package org.jboss.ejb3.test.clusteredentity.unit;
 
-import java.util.Properties;
-import javax.naming.InitialContext;
-
-import org.hibernate.cache.StandardQueryCache;
-import org.jboss.ejb3.test.clusteredentity.classloader.Account;
-import org.jboss.ejb3.test.clusteredentity.classloader.AccountHolderPK;
-import org.jboss.ejb3.test.clusteredentity.classloader.EntityQueryTest;
-import org.jboss.ejb3.test.common.unit.DBSetup;
-
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
+import org.jboss.ejb3.test.common.unit.DBSetup;
+
 /**
  * Tests caching of queries involving custom types.
  *
@@ -100,7 +93,7 @@
    {
       TestSuite suite = new TestSuite();
       Test t1 = getDeploySetup(EntityQueryUnitTestCase.class, 
-                               "clusteredentity-classloader-test.ear");
+                               EAR_NAME + ".ear");
 
       suite.addTest(t1);
 

Modified: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java	2007-03-05 20:14:05 UTC (rev 61095)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -82,6 +82,8 @@
 
       try
       {
+         tester0.getCache(isOptimistic());
+         
          Customer customer = tester0.createCustomer();
          
          //Call finder twice since Hibernate seems to not actually save collections 
@@ -112,6 +114,8 @@
          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());
    
@@ -134,8 +138,13 @@
       }
    }
 
+   protected boolean isOptimistic()
+   {
+      return false;
+   }
+   
    public static Test suite() throws Exception
    {
-      return JBossClusteredTestCase.getDeploySetup(EntityUnitTestCase.class, "clusteredentity-test.jar");
+      return getDeploySetup(EntityUnitTestCase.class, "clusteredentity-test.jar");
    }
 }

Copied: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEmbeddedIdClassloaderTestCase.java (from rev 60862, branches/Branch_4_2/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEmbeddedIdClassloaderTestCase.java)
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEmbeddedIdClassloaderTestCase.java	                        (rev 0)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEmbeddedIdClassloaderTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.test.clusteredentity.unit;
+
+import org.jboss.ejb3.test.common.unit.DBSetup;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Executes the superclass tests, but with Hibernate and JBoss Cache
+ * configured for optimistic locking.
+ * 
+ * @author Brian Stansberry
+ * 
+ * @version $Id: ExtendedPersistenceUnitTestCase.java 60065 2007-01-27 23:05:44Z bstansberry at jboss.com $
+ */
+public class OptimisticEmbeddedIdClassloaderTestCase extends EmbeddedIdClassloaderTestCase
+{
+
+   public OptimisticEmbeddedIdClassloaderTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite() throws Exception
+   {
+
+      TestSuite suite = new TestSuite();
+      // Deploy an optimistic cache before the ear
+      Test t1 = getDeploySetup(OptimisticEmbeddedIdClassloaderTestCase.class, 
+                               "optimistic-entity-cache-beans.xml, clusteredentity-embeddedid-optimistic-test.ear");
+
+      suite.addTest(t1);
+
+      // Create an initializer for the test suite
+      DBSetup wrapper = new DBSetup(suite);
+      return wrapper;
+   }
+   
+   @Override
+   protected String getEarName()
+   {
+      return "clusteredentity-embeddedid-optimistic-test";
+   }   
+}

Copied: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java (from rev 60862, branches/Branch_4_2/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java)
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java	                        (rev 0)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryRedeployUnitTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.test.clusteredentity.unit;
+
+import org.jboss.ejb3.test.common.unit.DBSetup;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Executes the superclass tests, but with Hibernate and JBoss Cache
+ * configured for optimistic locking.
+ * 
+ * @author Brian Stansberry
+ * 
+ * @version $Id: ExtendedPersistenceUnitTestCase.java 60065 2007-01-27 23:05:44Z bstansberry at jboss.com $
+ */
+public class OptimisticEntityQueryRedeployUnitTestCase extends EntityQueryRedeployUnitTestCase
+{
+   private static final String EAR_NAME = "clusteredentity-classloader-optimistic-test";
+   
+   
+   public OptimisticEntityQueryRedeployUnitTestCase(String name)
+   {
+      super(name);
+   }
+   
+   
+   public static Test suite() throws Exception
+   {
+      TestSuite suite = new TestSuite();
+      //  Deploy an optimistic cache before the ear
+      Test t1 = getDeploySetup(OptimisticEntityQueryRedeployUnitTestCase.class, 
+            "optimistic-entity-cache-beans.xml, " + EAR_NAME + ".ear");
+
+      suite.addTest(t1);
+
+      // Create an initializer for the test suite
+      DBSetup wrapper = new DBSetup(suite);
+      return wrapper;
+   }
+   
+   @Override
+   protected String getEarName()
+   {
+      return EAR_NAME;      
+   }
+
+   @Override
+   protected boolean isOptimistic()
+   {
+      return true;
+   }
+
+}

Copied: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java (from rev 60862, branches/Branch_4_2/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java)
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java	                        (rev 0)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityQueryUnitTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.test.clusteredentity.unit;
+
+import org.jboss.ejb3.test.common.unit.DBSetup;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Executes the superclass tests, but with Hibernate and JBoss Cache
+ * configured for optimistic locking.
+ * 
+ * @author Brian Stansberry
+ * @version $Id: ExtendedPersistenceUnitTestCase.java 60065 2007-01-27 23:05:44Z bstansberry at jboss.com $
+ */
+public class OptimisticEntityQueryUnitTestCase extends EntityQueryUnitTestCase
+{
+   private static final String EAR_NAME = "clusteredentity-classloader-optimistic-test";
+   
+   public OptimisticEntityQueryUnitTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public static Test suite() throws Exception
+   {
+      TestSuite suite = new TestSuite();
+      // Deploy an optimistic cache before the ear
+      Test t1 = getDeploySetup(OptimisticEntityQueryUnitTestCase.class, 
+                               "optimistic-entity-cache-beans.xml, " + 
+                               EAR_NAME + ".ear");
+
+      suite.addTest(t1);
+
+      // Create an initializer for the test suite
+      DBSetup wrapper = new DBSetup(suite);
+      return wrapper;
+   }
+   
+   @Override
+   protected String getEarName()
+   {
+      return EAR_NAME;      
+   }
+
+   @Override
+   protected boolean isOptimistic()
+   {
+      return true;
+   }
+}

Copied: trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityUnitTestCase.java (from rev 60862, branches/Branch_4_2/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityUnitTestCase.java)
===================================================================
--- trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityUnitTestCase.java	                        (rev 0)
+++ trunk/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/OptimisticEntityUnitTestCase.java	2007-03-05 20:15:01 UTC (rev 61096)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.test.clusteredentity.unit;
+
+import junit.framework.Test;
+
+/**
+ * Executes the superclass tests, but with Hibernate and JBoss Cache
+ * configured for optimistic locking.
+ * 
+ * @author Brian Stansberry
+ * @version $Id: ExtendedPersistenceUnitTestCase.java 60065 2007-01-27 23:05:44Z bstansberry at jboss.com $
+ */
+public class OptimisticEntityUnitTestCase extends EntityUnitTestCase
+{
+
+   public OptimisticEntityUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite() throws Exception
+   {
+      return getDeploySetup(OptimisticEntityUnitTestCase.class, 
+            "optimistic-entity-cache-beans.xml, clusteredentity-optimistic-test.jar");
+   }
+
+   @Override
+   protected boolean isOptimistic()
+   {
+      return true;
+   }
+
+}




More information about the jboss-cvs-commits mailing list