[jboss-cvs] JBossAS SVN: r63138 - in branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/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
Thu May 17 22:10:13 EDT 2007


Author: bstansberry at jboss.com
Date: 2007-05-17 22:10:12 -0400 (Thu, 17 May 2007)
New Revision: 63138

Added:
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/DBSetup.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java
Modified:
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/build-test.xml
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/resources/ejb3-entity-cache-service.xml
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java
   branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java
Log:
[EJBTHREE-798] Port to JBoss_4_0_5_GA_CP04_EJBTHREE-798

Modified: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/build-test.xml
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/build-test.xml	2007-05-18 02:09:35 UTC (rev 63137)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/build-test.xml	2007-05-18 02:10:12 UTC (rev 63138)
@@ -143,6 +143,7 @@
       <path refid="quartz.quartz.classpath"/>
       <path refid="jboss.microcontainer.classpath"/>
       <path refid="jboss.jbossxb.classpath"/>
+      <path refid="hsqldb.hsqldb.classpath"/>
    </path>
 
    <!-- ======= -->
@@ -2574,6 +2575,29 @@
             <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"/>
+         </fileset>
+         <fileset dir="${resources}/test/clusteredentity/classloader">
+            <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"/>
+       </fileset>
+       <fileset dir="${resources}/test/clusteredentity/classloader">
+          <include name="META-INF/application.xml"/>
+          <include name="META-INF/jboss-app.xml"/>
+        <include name="clusteredentity-ds.xml"/>
+       </fileset>
+    </jar>
+   	
+	   
    </target>
 
    <target name="clusteredsession"
@@ -2698,6 +2722,9 @@
 
             <!-- EJBTHREE-485 needs javassist -->
             <path refid="javassist.classpath"/>
+            
+            <!-- For clustered entities -->
+            <path refid="hsqldb.hsqldb.classpath"/>
          </classpath>
 
          <formatter type="plain" usefile="true"/>

Copied: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java (from rev 63133, branches/JBoss_4_0_5_GA_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java)
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java	                        (rev 0)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -0,0 +1,319 @@
+//$Id: TreeCache.java 9965 2006-05-30 18:00:28Z steve.ebersole at jboss.com $
+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.hibernate.cache.UpdateTimestampsCache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+
+/**
+ * Subclass of the standard <code>org.hibernate.cache.TreeCache</code> used as
+ * a workaround until issues related to JBCLUSTER-150 are resolved in Hibernate.
+ *
+ * @author Gavin King
+ * @author Brian Stansberry
+ */
+public class JBCCache implements Cache {
+	
+	private static final Log log = LogFactory.getLog(JBCCache.class);
+
+	private static final String ITEM = "item";
+
+	private org.jboss.cache.TreeCache cache;
+	private final String regionName;
+	private final Fqn regionFqn;
+	private final TransactionManager transactionManager;
+    private boolean localWritesOnly;
+
+	public JBCCache(org.jboss.cache.TreeCache cache, String regionName, TransactionManager transactionManager) 
+	throws CacheException {
+		this.cache = cache;
+		this.regionName = regionName;
+		this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
+		this.transactionManager = transactionManager;
+        if (cache.getUseRegionBasedMarshalling())
+        {           
+           localWritesOnly = StandardQueryCache.class.getName().equals(regionName);
+           
+           boolean fetchState = cache.getFetchInMemoryState();
+           try
+           {
+              // We don't want a state transfer for the StandardQueryCache,
+              // as it can include classes from multiple scoped classloaders
+              if (localWritesOnly)
+                 cache.setFetchInMemoryState(false);
+              
+              // We always activate
+              activateCacheRegion(regionFqn.toString());
+           }
+           finally
+           {
+              // Restore the normal state transfer setting
+              if (localWritesOnly)
+                 cache.setFetchInMemoryState(fetchState);              
+           }
+        }
+	}
+
+	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 new CacheException(e);
+		}
+	}
+
+	public void update(Object key, Object value) throws CacheException {
+		try {
+            if (localWritesOnly) {
+               Option option = new Option();
+               option.setCacheModeLocal(true);
+               cache.put( new Fqn( regionFqn, key ), ITEM, value, option );
+            }
+            else {               
+                cache.put( new Fqn( regionFqn, key ), ITEM, value );
+            }
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void put(Object key, Object value) throws CacheException {
+		Transaction tx = suspend();
+		try {
+           if (localWritesOnly) {
+              Option option = new Option();
+              option.setCacheModeLocal(true);
+              // Overloaded method isn't available, so have to use InvocationContext
+              cache.getInvocationContext().setOptionOverrides(option);
+              try {
+                  // do the failfast put outside the scope of the JTA txn
+                  cache.putFailFast( new Fqn( regionFqn, key ), ITEM, value, 0 );
+              }
+              finally {
+                 cache.getInvocationContext().setOptionOverrides(null);
+              }
+           }
+           else {               
+               //do the failfast put outside the scope of the JTA txn
+			   cache.putFailFast( new Fqn( regionFqn, key ), ITEM, value, 0 );
+           }
+		}
+		catch (TimeoutException te) {
+			//ignore!
+			log.debug("ignoring write lock acquisition failure");
+		}
+		catch (Exception e) {
+			throw new CacheException(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.remove( new Fqn( regionFqn, key ), option );
+           }
+           else {               
+               cache.remove( new Fqn( regionFqn, key ) );
+           }
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void clear() throws CacheException {
+		try {
+			cache.remove( regionFqn );
+		}
+		catch (Exception e) {
+			throw new CacheException(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
+			cache.evict( regionFqn );
+            
+            if (cache.getUseRegionBasedMarshalling() && !isSharedClassLoaderRegion(regionName))
+            {
+               inactivateCacheRegion();
+            }
+		}
+        catch (CacheException e)
+        {
+           throw e;
+        }
+		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 = cache.getChildrenNames( regionFqn );
+			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 = cache.getChildrenNames( regionFqn );
+			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);
+		}
+	}
+	
+	public String toString() {
+		return "TreeCache(" + regionName + ')';
+	}
+       
+    private boolean isSharedClassLoaderRegion(String regionName)
+    {
+       return (StandardQueryCache.class.getName().equals(regionName) 
+                || UpdateTimestampsCache.class.getName().equals(regionName));
+    }
+    
+    private void activateCacheRegion(String regionName) throws CacheException
+    {
+       String fqnString = regionFqn.toString();
+       // FIXME -- find a way that doesn't involve this API
+       if (cache.getMarshaller().isInactive(fqnString))
+       {
+          try
+          {
+             // Only register the classloader if it's not a shared region.  
+             // If it's shared, no single classloader is valid
+             if (!isSharedClassLoaderRegion(regionName))
+             {
+                cache.registerClassLoader(fqnString, Thread.currentThread().getContextClassLoader());
+             }
+             cache.activateRegion(fqnString);
+          }
+          catch (Exception e)
+          {
+             throw new CacheException("Problem activating region " + regionName, e);
+          }
+       }
+    }
+    
+    private void inactivateCacheRegion() throws CacheException
+    {
+       String fqnString = regionFqn.toString();
+       // FIXME -- find a way that doesn't involve this API
+       if (!cache.getMarshaller().isInactive(fqnString))
+       {
+          try
+          {
+             cache.inactivateRegion(fqnString);
+             cache.unregisterClassLoader(fqnString);
+          }
+          catch (Exception e)
+          {
+             throw new CacheException("Problem activating region " + fqnString, e);
+          }
+       }        
+    }	
+}

Modified: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2007-05-18 02:09:35 UTC (rev 63137)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -28,7 +28,6 @@
 import org.hibernate.cache.Cache;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.CacheProvider;
-import org.hibernate.cache.TreeCache;
 import org.jboss.cache.TreeCacheMBean;
 import org.jboss.ejb3.tx.TxUtil;
 import org.jboss.mx.util.MBeanProxyExt;
@@ -56,7 +55,7 @@
     */
    public Cache buildCache(String regionName, Properties properties) throws CacheException
    {
-      return new TreeCache(cache, regionName, TxUtil.getTransactionManager());
+      return new JBCCache(cache, regionName, TxUtil.getTransactionManager());
    }
 
    public boolean isMinimalPutsEnabledByDefault()

Modified: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/resources/ejb3-entity-cache-service.xml
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/resources/ejb3-entity-cache-service.xml	2007-05-18 02:09:35 UTC (rev 63137)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/resources/ejb3-entity-cache-service.xml	2007-05-18 02:10:12 UTC (rev 63138)
@@ -38,6 +38,11 @@
              to find each other -->
     <attribute name="ClusterName">EJB3-entity-cache</attribute>
 
+    <!-- Must be true if any entity deployment uses a scoped classloader -->
+    <attribute name="UseRegionBasedMarshalling">true</attribute>
+    <!-- Must match the value of "UseRegionBasedMarshalling" -->
+    <attribute name="InactiveOnStartup">true</attribute>
+    
     <attribute name="ClusterConfig">
       <config>
         <!-- UDP: if you have a multihomed machine,

Modified: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java	2007-05-18 02:09:35 UTC (rev 63137)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTest.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -36,4 +36,6 @@
    Customer findByCustomerId(Integer id);
    
    void loadedFromCache();
+   
+   void cleanup();
 }

Modified: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java	2007-05-18 02:09:35 UTC (rev 63137)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/EntityTestBean.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -22,9 +22,11 @@
 package org.jboss.ejb3.test.clusteredentity;
 
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
 import javax.ejb.Remote;
+import javax.ejb.Remove;
 import javax.ejb.Stateless;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
@@ -154,6 +156,20 @@
       }
       
    }
+   
+   @Remove
+   public void cleanup()
+   {
+      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);
+      }
+   }
 
    private TreeCache getCache() throws Exception
    {

Copied: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/DBSetup.java (from rev 63133, branches/JBoss_4_0_5_GA_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/DBSetup.java)
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/DBSetup.java	                        (rev 0)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/DBSetup.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -0,0 +1,154 @@
+/*
+ * 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 java.sql.DriverManager;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+
+/** A TestSetup that starts hypersonic before the testcase with a tcp
+ * listening port at 1701.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revison:$
+ */
+public class DBSetup extends TestSetup
+{
+   public DBSetup(Test test)
+   {
+      super(test);
+   }
+
+   protected void setUp() throws Exception
+   {
+         File hypersoniDir = new File("output/hypersonic");
+         if (!hypersoniDir.exists())
+         {
+            hypersoniDir.mkdirs();
+         }
+
+         if (!hypersoniDir.isDirectory())
+         {
+            throw new IOException("Failed to create directory: " + hypersoniDir);
+         }
+      
+         File dbPath = new File(hypersoniDir, "clusteredentity-db");
+
+         // Start DB in new thread, or else it will block us
+         DBThread serverThread = new DBThread(dbPath);
+         serverThread.start();
+         
+         int elapsed = 0;
+         while (!serverThread.isStarted() && elapsed < 15000)
+         {
+            try 
+            {
+               Thread.sleep(100);
+               elapsed += 100;
+            }
+            catch (InterruptedException ie)
+            {
+               System.out.println("Interrupted while waiting for Hypersonic");
+            }
+         }
+         
+         if (!serverThread.isStarted())
+            System.out.println("Hypersonic failed to start in a timely fashion");
+   }
+
+   protected void tearDown() throws Exception
+   {
+      Class.forName("org.hsqldb.jdbcDriver");
+      String dbURL = "jdbc:hsqldb:hsql://" + System.getProperty("jbosstest.server.host", "localhost") + ":1701";
+      Connection conn = DriverManager.getConnection(dbURL, "sa", "");
+      Statement statement = conn.createStatement();      
+      statement.executeQuery("SHUTDOWN COMPACT");
+      
+   }
+
+   public static void main(String[] args) throws Exception
+   {
+      DBSetup setup = new DBSetup(null);
+      setup.setUp();
+      Thread.sleep(120*1000);
+      setup.tearDown();
+   }
+   
+   class DBThread extends Thread
+   {
+      boolean started;
+      File dbPath;
+      
+      DBThread(File dbPath)
+      {
+         super("hypersonic");
+         this.dbPath = dbPath;
+      }
+      
+      boolean isStarted()
+      {
+         return started;
+      }
+      
+      public void run()
+      {
+         try
+         {
+            // Create startup arguments
+            String[] args = {
+                  "-database",
+                  dbPath.toString(),
+                  "-port",
+                  String.valueOf(1701),
+                  "-silent",
+                  "false",
+                  "-trace",
+                  "false",
+                  "-no_system_exit",
+                  "true",
+             };
+            System.out.println("Starting hsqldb");
+            // HACK Do this by reflection for now until we determine how 
+            // we want to handle this in EJB3
+            Class clazz = Thread.currentThread().getContextClassLoader().loadClass("org.hsqldb.Server");
+            Method main = clazz.getDeclaredMethod("main", new Class[] { String[].class });
+            main.invoke(null, new Object[] { args });
+//            org.hsqldb.Server.main(args);
+            System.out.println("Done");
+         }
+         catch (Exception e)
+         {
+            e.printStackTrace();
+         }
+         finally
+         {
+            started = true;
+         }
+      }
+   }
+}

Copied: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java (from rev 63133, branches/JBoss_4_0_5_GA_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java)
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java	                        (rev 0)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityClassloaderTestBase.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -0,0 +1,298 @@
+/*
+ * 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 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.test.JBossClusteredTestCase;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Base class for tests involving clustered entities with a scoped classloader.
+ *
+ * @author Brian Stansberry
+ * @version $Id: EntityUnitTestCase.java 57207 2006-09-26 12:06:13Z dimitris at jboss.org $
+ */
+
+public class EntityClassloaderTestBase
+extends JBossClusteredTestCase
+{
+   protected org.apache.log4j.Category log = getLog();
+
+   protected static final long SLEEP_TIME = 300L;
+   
+   
+   static boolean deployed0 = true;
+   static boolean deployed1 = true;
+
+   protected static final AccountHolderPK SMITH = new AccountHolderPK("Smith", "1000");
+   protected static final AccountHolderPK JONES = new AccountHolderPK("Jones", "2000");
+   protected static final AccountHolderPK BARNEY = new AccountHolderPK("Barney", "3000");
+   
+   protected EntityQueryTest sfsb0;
+
+   protected EntityQueryTest sfsb1;
+   
+   public EntityClassloaderTestBase(String name)
+   {
+      super(name);
+   }
+   
+   protected void setUp() throws Exception
+   {
+      sfsb0 = getEntityQueryTest(System.getProperty("jbosstest.cluster.node0"));
+      sfsb1 = getEntityQueryTest(System.getProperty("jbosstest.cluster.node1"));  
+      sfsb0.cleanup();
+      sfsb1.cleanup();
+   }
+   
+   protected EntityQueryTest getEntityQueryTest(String nodeJNDIAddress) throws Exception
+   {
+      Properties prop1 = new Properties();
+      prop1.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
+      prop1.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
+      prop1.put("java.naming.provider.url", "jnp://" + nodeJNDIAddress + ":1099");
+   
+      log.info("===== Naming properties for " + nodeJNDIAddress + ": ");
+      log.info(prop1);
+      log.info("Create InitialContext for " + nodeJNDIAddress);
+      InitialContext ctx1 = new InitialContext(prop1);
+   
+      log.info("Lookup sfsb from " + nodeJNDIAddress);
+      return (EntityQueryTest)ctx1.lookup("clusteredentity-classloader-test/EntityQueryTestBean/remote");
+      
+   }
+    
+   protected void tearDown() throws Exception
+   {
+      if (sfsb0 != null)
+      {
+         try
+         {
+            sfsb0.remove();
+         }
+         catch (Exception e) {}
+      }
+      if (sfsb1 != null)
+      {
+         try
+         {
+            sfsb1.remove();
+         }
+         catch (Exception e) {}
+      }
+      
+      sfsb0 = sfsb1 = null;
+   }
+   
+   protected void standardEntitySetup()
+   {
+//      sfsb0.createAccountHolder(SMITH, "94536");
+      sfsb0.createAccount(SMITH, new Integer(1001), new Integer(5), "94536");
+      sfsb0.createAccount(SMITH, new Integer(1002), new Integer(15), "94536");
+      sfsb0.createAccount(SMITH, new Integer(1003), new Integer(20), "94536");
+      
+//      sfsb0.createAccountHolder(JONES, "63088");
+      sfsb0.createAccount(JONES, new Integer(2001), new Integer(5), "63088");
+      sfsb0.createAccount(JONES, new Integer(2002), new Integer(15), "63088");
+      sfsb0.createAccount(JONES, new Integer(2003), new Integer(20), "63088");
+      
+//      sfsb0.createAccountHolder(BARNEY, "63088");
+      sfsb0.createAccount(BARNEY, new Integer(3001), new Integer(5), "63088");
+      sfsb0.createAccount(BARNEY, new Integer(3002), new Integer(15), "63088");
+      sfsb0.createAccount(BARNEY, new Integer(3003), new Integer(20), "63088");
+      
+      log.info("Standard entities created");
+   }
+   
+   protected void resetRegionUsageState()
+   {  
+      sfsb0.getSawRegionModification(StandardQueryCache.class.getName());
+      sfsb0.getSawRegionModification("AccountRegion");
+      
+      sfsb0.getSawRegionAccess(StandardQueryCache.class.getName());
+      sfsb0.getSawRegionAccess("AccountRegion");
+
+      
+      sfsb1.getSawRegionModification(StandardQueryCache.class.getName());
+      sfsb1.getSawRegionModification("AccountRegion");
+      
+      sfsb1.getSawRegionAccess(StandardQueryCache.class.getName());
+      sfsb1.getSawRegionAccess("AccountRegion");
+      
+      log.info("Region usage state cleared");
+      
+   }
+   
+   protected void modifyEntities(EntityQueryTest bean)
+   {
+      bean.updateAccountBranch(1001, "63088");
+      bean.updateAccountBalance(2001, 15);
+      
+      log.info("Entities modified");
+   }
+   
+   protected void restoreEntities(EntityQueryTest bean)
+   {
+      // Undo the mods done in queryTest
+      bean.updateAccountBranch(1001, "94536");
+      bean.updateAccountBalance(2001, 5);
+      
+      log.info("Standard entities restored to initial state");
+   }
+
+   protected void queryTest(boolean setupEntities, boolean useNamedQuery, boolean useNamedRegion, boolean checkEmptyRegion)
+   {
+      if (setupEntities)
+         standardEntitySetup();
+      else
+         restoreEntities(sfsb0);
+      
+      resetRegionUsageState();
+      
+      // Initial ops on node 0
+      
+      String regionName = useNamedRegion ? "AccountRegion" : StandardQueryCache.class.getName();
+      
+      // Query on post code count
+      assertEquals("63088 has correct # of accounts", 6, sfsb0.getCountForBranch("63088", useNamedQuery, useNamedRegion));
+      
+      assertTrue("Query cache used", sfsb0.getSawRegionModification(regionName));
+      // Clear the access state
+      sfsb0.getSawRegionAccess(regionName);
+      
+      log.info("First query on node0 done");
+      
+      // Do it again from node 1
+      // Sleep a bit to allow async repl to happen
+      sleep(SLEEP_TIME);
+      
+      // If region isn't activated yet, should not have been modified      
+      if (checkEmptyRegion)
+      {
+         assertFalse("Query cache remotely modified", sfsb1.getSawRegionModification(regionName));
+         // Clear the access state
+         sfsb1.getSawRegionAccess(regionName);
+      }
+      else if (useNamedRegion)
+      {
+         assertTrue("Query cache remotely modified", sfsb1.getSawRegionModification(regionName));
+         // Clear the access state
+         sfsb1.getSawRegionAccess(regionName);         
+      }
+      
+      assertEquals("63088 has correct # of accounts", 6, sfsb1.getCountForBranch("63088", useNamedQuery, useNamedRegion));
+      
+      if (checkEmptyRegion)
+      {
+         // Query should have been inserted
+         assertTrue("Query cache modified", 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.
+      
+      // Sleep a bit to allow async repl to happen
+      sleep(SLEEP_TIME);
+      
+      // Do some more queries on node 0
+      
+      assertEquals("Correct branch for Smith", "94536", sfsb0.getBranch(SMITH, useNamedQuery, useNamedRegion));
+      
+      assertEquals("Correct high balances for Jones", 40, sfsb0.getTotalBalance(JONES, useNamedQuery, useNamedRegion));
+      
+      assertTrue("Query cache used", sfsb0.getSawRegionModification(regionName));
+      // Clear the access state
+      sfsb0.getSawRegionAccess(regionName);
+      
+      log.info("Second set of queries on node0 done");
+      
+      // Sleep a bit to allow async repl to happen
+      sleep(SLEEP_TIME);
+      
+      // Do it again from node 1
+      
+      // First check if the previous queries replicated (if the region is replicable)
+      
+      if (useNamedRegion)
+      {
+         assertTrue("Query cache remotely modified", sfsb1.getSawRegionModification(regionName));
+         // Clear the access state
+         sfsb1.getSawRegionAccess(regionName);
+      }
+      
+      assertEquals("Correct branch for Smith", "94536", sfsb1.getBranch(SMITH, useNamedQuery, useNamedRegion));
+      
+      assertEquals("Correct high balances for Jones", 40, sfsb1.getTotalBalance(JONES, useNamedQuery, useNamedRegion));
+      
+      if (useNamedRegion)
+      {
+         // Should be no change; query was already there
+         assertFalse("Query cache modified", sfsb1.getSawRegionModification(regionName));
+         assertTrue("Query cache accessed", sfsb1.getSawRegionAccess(regionName));
+      }
+      else
+      {
+         // Query should have been inserted
+         assertTrue("Query cache modified", sfsb1.getSawRegionModification(regionName));
+         // Clear the access state
+         sfsb1.getSawRegionAccess(regionName);
+      }      
+      
+      log.info("Second set of queries on node1 done");
+      
+      // Modify underlying data on node 1
+      modifyEntities(sfsb1);
+      
+      // Confirm query results are correct on node 0
+      
+      assertEquals("63088 has correct # of accounts", 7, sfsb0.getCountForBranch("63088", useNamedQuery, useNamedRegion));
+      
+      assertEquals("Correct branch for Smith", "63088", sfsb0.getBranch(SMITH, useNamedQuery, useNamedRegion));
+      
+      assertEquals("Correct high balances for Jones", 50, sfsb0.getTotalBalance(JONES, useNamedQuery, useNamedRegion));
+      
+      log.info("Third set of queries on node0 done");
+   }
+   
+   protected void sleep(long millis)
+   {
+      try
+      {
+         Thread.sleep(millis);
+      }
+      catch (InterruptedException e)
+      {
+         log.warn("Interrupted while sleeping", e);
+      }
+   }
+}

Copied: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java (from rev 63133, branches/JBoss_4_0_5_GA_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java)
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java	                        (rev 0)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryRedeployUnitTestCase.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -0,0 +1,98 @@
+/*
+ * 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 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.jmx.adaptor.rmi.RMIAdaptor;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Sample client for the jboss container.
+ *
+ * @author <a href="mailto:bill at burkecentral.com">Bill Burke</a>
+ * @version $Id: EntityUnitTestCase.java 57207 2006-09-26 12:06:13Z dimitris at jboss.org $
+ */
+
+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);
+   }
+   
+   public void testRedeploy() throws Exception
+   {
+      // Set things up with the default region
+      queryTest(true, true, false, true);
+      // 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
+      queryTest(false, true, false, true);
+      queryTest(false, true, true, true);
+   }
+   
+   private void redeploy() throws Exception
+   {
+      RMIAdaptor[] adaptors = getAdaptors();
+      undeploy(adaptors[1], EAR_NAME);
+      
+      sleep(2000);
+      
+      deploy(adaptors[1], EAR_NAME);
+      
+      sleep(2000);
+      
+      // Get the SFSB again
+      sfsb1 = getEntityQueryTest(System.getProperty("jbosstest.cluster.node1"));
+   }
+   
+   
+   public static Test suite() throws Exception
+   {
+      TestSuite suite = new TestSuite();
+      Test t1 = getDeploySetup(EntityQueryRedeployUnitTestCase.class, EAR_NAME);
+
+      suite.addTest(t1);
+
+      // Create an initializer for the test suite
+      DBSetup wrapper = new DBSetup(suite);
+      return wrapper;
+   }
+}

Copied: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java (from rev 63133, branches/JBoss_4_0_5_GA_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java)
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java	                        (rev 0)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityQueryUnitTestCase.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -0,0 +1,111 @@
+/*
+ * 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 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 junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Sample client for the jboss container.
+ *
+ * @author <a href="mailto:bill at burkecentral.com">Bill Burke</a>
+ * @version $Id: EntityUnitTestCase.java 57207 2006-09-26 12:06:13Z dimitris at jboss.org $
+ */
+
+public class EntityQueryUnitTestCase
+extends EntityClassloaderTestBase
+{
+   private static boolean firstNamedRegionTest = true;
+   
+   public EntityQueryUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public void testManualQueryDefaultRegion() throws Exception
+   {
+      log.info("+++ start testManualQueryDefaultRegion");
+      queryTest(false, false);
+      log.info("+++ end testManualQueryDefaultRegion");
+   }
+   
+   public void testManualQueryNamedRegion() throws Exception
+   {      
+      log.info("+++ start testManualQueryNamedRegion");
+      try
+      {
+         queryTest(false, true);
+      }
+      finally
+      {
+         firstNamedRegionTest = false;
+      }
+      log.info("+++ end testManualQueryNamedRegion");
+   }
+   
+   public void testNamedQueryDefaultRegion() throws Exception
+   {    
+      log.info("+++ start testNamedQueryDefaultRegion");
+      queryTest(true, false);
+      log.info("+++ end testNamedQueryDefaultRegion");
+   }
+   
+   public void testNamedQueryNamedRegion() throws Exception
+   {      
+      log.info("+++ start testNamedQueryNamedRegion");
+      try
+      {
+         queryTest(true, true);
+      }
+      finally
+      {
+         firstNamedRegionTest = false;
+      }
+      log.info("+++ start testNamedQueryNamedRegion");
+   }
+
+   private void queryTest(boolean useNamedQuery, boolean useNamedRegion)
+   {
+      queryTest(true, useNamedQuery, useNamedRegion, firstNamedRegionTest);
+   }
+   
+   public static Test suite() throws Exception
+   {
+      TestSuite suite = new TestSuite();
+      Test t1 = getDeploySetup(EntityQueryUnitTestCase.class, 
+                               "clusteredentity-classloader-test.ear");
+
+      suite.addTest(t1);
+
+      // Create an initializer for the test suite
+      DBSetup wrapper = new DBSetup(suite);
+      return wrapper;
+   }
+}

Modified: branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java
===================================================================
--- branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java	2007-05-18 02:09:35 UTC (rev 63137)
+++ branches/JBoss_4_0_5_GA_CP04_EJBTHREE-798/ejb3/src/test/org/jboss/ejb3/test/clusteredentity/unit/EntityUnitTestCase.java	2007-05-18 02:10:12 UTC (rev 63138)
@@ -40,6 +40,8 @@
 {
    org.apache.log4j.Category log = getLog();
 
+   protected static final long SLEEP_TIME = 300L;
+
    static boolean deployed = false;
    static int test = 0;
 
@@ -77,31 +79,43 @@
       
       System.out.println("Create node 0");
       EntityTest tester0 = (EntityTest)ctx0.lookup("EntityTestBean/remote");
-      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");
-      tester0.loadedFromCache();
-
-      //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");
-      System.out.println("Find node 1");
-      customer = tester1.findByCustomerId(customer.getId());
-
-      //Check everything was in cache
-      System.out.println("Check cache 1");
-      tester1.loadedFromCache();
-      
+      try
+      {
+         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");
+         tester0.loadedFromCache();
+   
+         // 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");
+         System.out.println("Find node 1");
+         customer = tester1.findByCustomerId(customer.getId());
+   
+         //Check everything was in cache
+         System.out.println("Check cache 1");
+         tester1.loadedFromCache();
+      }
+      finally
+      {
+         // cleanup the db so we can run this test multiple times w/o restarting the cluster
+         tester0.cleanup();
+      }
    }
 
    public static Test suite() throws Exception




More information about the jboss-cvs-commits mailing list