[Jboss-cvs] JBossAS SVN: r55928 - in branches/JBoss_3_2_7_CP: server/src/main/org/jboss/ejb/plugins/cmp/jdbc2 server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/bridge server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema testsuite/imports testsuite/src/main/org/jboss/test/cmp2 testsuite/src/main/org/jboss/test/cmp2/ageout testsuite/src/main/org/jboss/test/cmp2/ageout/test testsuite/src/main/org/jboss/test/cmp2/ejbselect testsuite/src/resources/cmp2 testsuite/src/resources/cmp2/ageout testsuite/src/resources/cmp2/ageout/META-INF testsuite/src/resources/cmp2/ejbselect testsuite/src/resources/cmp2/ejbselect/META-INF

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Aug 14 21:45:06 EDT 2006


Author: ryan.campbell at jboss.com
Date: 2006-08-14 21:45:04 -0400 (Mon, 14 Aug 2006)
New Revision: 55928

Added:
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/DynamicQueryCommand.java
   branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/
   branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/
   branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java
   branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ejbselect/JDBC2PmEJBSelectUnitTestCase.java
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml
Removed:
   branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/
   branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/
   branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml
Modified:
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/AbstractQueryCommand.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/JDBCStoreManager2.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PersistentContext.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PkSqlCreateCommand.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/QueryFactory.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/bridge/JDBCCMRFieldBridge2.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/EntityTable.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/PartitionedTableCache.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/Schema.java
   branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/TableCache.java
   branches/JBoss_3_2_7_CP/testsuite/imports/test-jars.xml
Log:
merged JBAS-2361: Need support for dynamic-ql in 3.2.7

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/AbstractQueryCommand.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/AbstractQueryCommand.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/AbstractQueryCommand.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -34,7 +34,7 @@
  */
 public abstract class AbstractQueryCommand implements QueryCommand
 {
-   private static final CollectionFactory COLLECTION_FACTORY = new CollectionFactory()
+   static final CollectionFactory COLLECTION_FACTORY = new CollectionFactory()
    {
       public Collection newCollection()
       {
@@ -42,7 +42,7 @@
       }
    };
 
-   private static final CollectionFactory SET_FACTORY = new CollectionFactory()
+   static final CollectionFactory SET_FACTORY = new CollectionFactory()
    {
       public Collection newCollection()
       {
@@ -55,7 +55,7 @@
    protected JDBCEntityBridge2 entity;
    protected QueryParameter[] params = null;
    private CollectionFactory collectionFactory;
-   private CollectionStrategy collectionStrategy = new EagerCollectionStrategy();
+   private CollectionStrategy collectionStrategy;
    private ResultReader resultReader;
 
    // Protected
@@ -70,24 +70,36 @@
       {
          collectionFactory = COLLECTION_FACTORY;
       }
+      initCollectionStrategy();
    }
 
    protected void setFieldReader(JDBCCMPFieldBridge2 field)
    {
       this.resultReader = new FieldReader(field);
+      initCollectionStrategy();
    }
 
    protected void setFunctionReader(SelectFunction func)
    {
       this.resultReader = new FunctionReader(func);
+      initCollectionStrategy();
    }
 
    protected void setEntityReader(JDBCEntityBridge2 entity)
    {
       this.entity = entity;
       this.resultReader = new EntityReader(entity);
+      initCollectionStrategy();
    }
 
+   private void initCollectionStrategy()
+   {
+      if(collectionFactory != null && resultReader != null)
+      {
+         collectionStrategy = new EagerCollectionStrategy(collectionFactory, resultReader, log);
+      }
+   }
+
    // QueryCommand implementation
 
    public JDBCStoreManager2 getStoreManager()
@@ -98,8 +110,34 @@
    public Collection fetchCollection(Schema schema, GenericEntityObjectFactory factory, Object[] args)
       throws FinderException
    {
+      return fetchCollection(entity, sql, params, collectionStrategy, schema, factory, args, log);
+   }
+
+   public Object fetchOne(Schema schema, GenericEntityObjectFactory factory, Object[] args) throws FinderException
+   {
       schema.flush();
+      return executeFetchOne(args, factory);
+   }
 
+   // Protected
+
+   protected Object executeFetchOne(Object[] args, GenericEntityObjectFactory factory) throws FinderException
+   {
+      return fetchOne(entity, sql, params, resultReader, args, factory, log);
+   }
+
+   static Collection fetchCollection(JDBCEntityBridge2 entity,
+                                     String sql,
+                                     QueryParameter[] params,
+                                     CollectionStrategy collectionStrategy,
+                                     Schema schema,
+                                     GenericEntityObjectFactory factory,
+                                     Object[] args,
+                                     Logger log)
+      throws FinderException
+   {
+      schema.flush();
+
       Collection result;
 
       Connection con = null;
@@ -118,7 +156,6 @@
           catch (SQLException sqle) 
           {
               javax.ejb.EJBException ejbe = new javax.ejb.EJBException("Could not get a connection; " + sqle);
-              //ejbe.initCause(sqle); only for JBoss 4 and +
               throw ejbe;
           } 
       }
@@ -153,24 +190,24 @@
          JDBCUtil.safeClose(con);
 
          log.error("Finder failed: " + e.getMessage(), e);
-         throw new FinderException(e.getMessage());
+         FinderException fe = new FinderException(e.getMessage());
+         throw fe;
       }
 
       result = collectionStrategy.readResultSet(con, ps, rs, factory);
 
       return result;
    }
-
-   public Object fetchOne(Schema schema, GenericEntityObjectFactory factory, Object[] args) throws FinderException
+   
+   static Object fetchOne(JDBCEntityBridge2 entity,
+                          String sql,
+                          QueryParameter[] params,
+                          ResultReader resultReader,
+                          Object[] args,
+                          GenericEntityObjectFactory factory,
+                          Logger log)
+      throws FinderException
    {
-      schema.flush();
-      return executeFetchOne(args, factory);
-   }
-
-   // Protected
-
-   protected Object executeFetchOne(Object[] args, GenericEntityObjectFactory factory) throws FinderException
-   {
       Object pk;
       Connection con = null;
       PreparedStatement ps = null;
@@ -241,7 +278,8 @@
       }
       catch(Exception e)
       {
-         throw new FinderException(e.getMessage());
+          FinderException fe = new FinderException(e.getMessage());
+          throw fe;
       }
       finally
       {
@@ -252,7 +290,7 @@
 
       return pk;
    }
-
+   
    protected void setParameters(List p)
    {
       if(p.size() > 0)
@@ -277,17 +315,17 @@
 
    // Inner
 
-   private static interface CollectionFactory
+   static interface CollectionFactory
    {
       Collection newCollection();
    }
 
-   private static interface ResultReader
+   static interface ResultReader
    {
       Object readRow(ResultSet rs, GenericEntityObjectFactory factory) throws SQLException;
    }
 
-   private static class EntityReader implements ResultReader
+   static class EntityReader implements ResultReader
    {
       private final JDBCEntityBridge2 entity;
 
@@ -303,7 +341,7 @@
       }
    };
 
-   private static class FieldReader implements ResultReader
+   static class FieldReader implements ResultReader
    {
       private final JDBCCMPFieldBridge2 field;
 
@@ -318,7 +356,7 @@
       }
    }
 
-   private static class FunctionReader implements ResultReader
+   static class FunctionReader implements ResultReader
    {
       private final SelectFunction function;
 
@@ -333,15 +371,27 @@
       }
    }
 
-   private interface CollectionStrategy
+   interface CollectionStrategy
    {
       Collection readResultSet(Connection con, PreparedStatement ps, ResultSet rs, GenericEntityObjectFactory factory)
          throws FinderException;
    }
 
-   private class EagerCollectionStrategy
+   static class EagerCollectionStrategy
       implements CollectionStrategy
    {
+      private final CollectionFactory collectionFactory;
+      private final ResultReader resultReader;
+      private final Logger log;
+
+      public EagerCollectionStrategy(CollectionFactory collectionFactory,
+                     ResultReader resultReader, Logger log)
+      {
+         this.collectionFactory = collectionFactory;
+         this.resultReader = resultReader;
+         this.log = log;
+      }
+
       public Collection readResultSet(Connection con,
                                       PreparedStatement ps,
                                       ResultSet rs,

Copied: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/DynamicQueryCommand.java (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/DynamicQueryCommand.java)

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/JDBCStoreManager2.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/JDBCStoreManager2.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/JDBCStoreManager2.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -82,7 +82,7 @@
 
    public Schema getSchema()
    {
-      schema = (Schema) getApplicationData(SCHEMA);
+      schema = (Schema)getApplicationData(SCHEMA);
       if(schema == null)
       {
          schema = new Schema();
@@ -93,7 +93,7 @@
 
    public Catalog getCatalog()
    {
-      Catalog catalog = (Catalog) getApplicationData(CATALOG);
+      Catalog catalog = (Catalog)getApplicationData(CATALOG);
       if(catalog == null)
       {
          catalog = new Catalog();
@@ -129,7 +129,7 @@
 
    public void setContainer(Container con)
    {
-      this.container = (EntityContainer) con;
+      this.container = (EntityContainer)con;
       if(container != null)
       {
          ejbModule = container.getEjbModule();
@@ -146,7 +146,7 @@
 
    public void create() throws Exception
    {
-      HashMap managersMap = (HashMap) getApplicationData(CREATED_MANAGERS);
+      HashMap managersMap = (HashMap)getApplicationData(CREATED_MANAGERS);
       if(managersMap == null)
       {
          managersMap = new HashMap();
@@ -159,28 +159,31 @@
    {
       initStoreManager();
 
-      HashMap managersMap = (HashMap) getApplicationData(CREATED_MANAGERS);
+      HashMap managersMap = (HashMap)getApplicationData(CREATED_MANAGERS);
       Catalog catalog = getCatalog();
       if(catalog.getEntityCount() == managersMap.size() && catalog.getEJBNames().equals(managersMap.keySet()))
       {
          // Make a copy of the managers (for safty)
          List managers = new ArrayList(managersMap.values());
 
-         //
-         //
          // Start Phase 2: resolve relationships
          for(int i = 0; i < managers.size(); ++i)
          {
-            JDBCStoreManager2 manager = (JDBCStoreManager2) managers.get(i);
+            JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
             manager.resolveRelationships();
          }
 
-         //
-         //
-         // Start Phase 3: create tables and compile queries
+         // Start Phase 3: init cmr loaders
          for(int i = 0; i < managers.size(); ++i)
          {
-            JDBCStoreManager2 manager = (JDBCStoreManager2) managers.get(i);
+            JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
+            manager.startEntity();
+         }
+
+         // Start Phase 4: create tables and compile queries
+         for(int i = 0; i < managers.size(); ++i)
+         {
+            JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
             manager.startStoreManager();
          }
 
@@ -326,14 +329,20 @@
       return null;
    }
 
-   public Object findEntity(Method finderMethod, Object[] args, EntityEnterpriseContext instance, GenericEntityObjectFactory factory)
+   public Object findEntity(Method finderMethod,
+                            Object[] args,
+                            EntityEnterpriseContext instance,
+                            GenericEntityObjectFactory factory)
       throws FinderException
    {
       QueryCommand query = queryFactory.getQueryCommand(finderMethod);
       return query.fetchOne(schema, factory, args);
    }
 
-   public Collection findEntities(Method finderMethod, Object[] args, EntityEnterpriseContext instance, GenericEntityObjectFactory factory)
+   public Collection findEntities(Method finderMethod,
+                                  Object[] args,
+                                  EntityEnterpriseContext instance,
+                                  GenericEntityObjectFactory factory)
       throws FinderException
    {
       QueryCommand query = queryFactory.getQueryCommand(finderMethod);
@@ -355,14 +364,13 @@
       }
       catch(EJBException e)
       {
+         log.error("Failed to load instance of " + entityBridge.getEntityName() + " with pk=" + ctx.getId(), e);
          throw e;
       }
       catch(Exception e)
       {
          throw new EJBException(
-            "Failed to load instance of "
-            + entityBridge.getEntityName() +
-            " with pk=" + ctx.getId(), e
+            "Failed to load instance of " + entityBridge.getEntityName() + " with pk=" + ctx.getId(), e
          );
       }
    }
@@ -372,7 +380,7 @@
       return entityBridge.isStoreRequired(instance);
    }
 
-   public boolean isModified (EntityEnterpriseContext instance) throws Exception
+   public boolean isModified(EntityEnterpriseContext instance) throws Exception
    {
       return entityBridge.isModified(instance);
    }
@@ -390,7 +398,7 @@
    public void removeEntity(EntityEnterpriseContext ctx) throws RemoveException
    {
       entityBridge.remove(ctx);
-      PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+      PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
       pctx.remove();
    }
 
@@ -406,8 +414,7 @@
       metaData = loadJDBCEntityMetaData();
 
       // setup the type factory, which is used to map java types to sql types.
-      typeFactory = new JDBCTypeFactory(
-         metaData.getTypeMapping(),
+      typeFactory = new JDBCTypeFactory(metaData.getTypeMapping(),
          metaData.getJDBCApplication().getValueClasses(),
          metaData.getJDBCApplication().getUserTypeMappings()
       );
@@ -428,8 +435,6 @@
 
    protected void startStoreManager() throws Exception
    {
-      entityBridge.start();
-
       queryFactory = new QueryFactory(entityBridge);
       queryFactory.init();
 
@@ -448,12 +453,14 @@
          final Class cmdClass = entityCommand.getCommandClass();
          if(cmdClass == null)
          {
-            throw new DeploymentException("entity-command class name is not specified for entity " + entityBridge.getEntityName());
+            throw new DeploymentException(
+               "entity-command class name is not specified for entity " + entityBridge.getEntityName()
+            );
          }
 
          try
          {
-            createCmd = (CreateCommand) cmdClass.newInstance();
+            createCmd = (CreateCommand)cmdClass.newInstance();
          }
          catch(ClassCastException cce)
          {
@@ -464,20 +471,25 @@
       createCmd.init(this);
    }
 
+   private void startEntity()
+      throws DeploymentException
+   {
+      entityBridge.start();
+   }
+
    private JDBCEntityMetaData loadJDBCEntityMetaData()
       throws DeploymentException
    {
       ApplicationMetaData amd = container.getBeanMetaData().getApplicationMetaData();
 
       // Get JDBC MetaData
-      JDBCApplicationMetaData jamd = (JDBCApplicationMetaData) amd.getPluginData(CMP_JDBC);
+      JDBCApplicationMetaData jamd = (JDBCApplicationMetaData)amd.getPluginData(CMP_JDBC);
 
       if(jamd == null)
       {
          // we are the first cmp entity to need jbosscmp-jdbc.
          // Load jbosscmp-jdbc.xml for the whole application
-         JDBCXmlFileLoader jfl = new JDBCXmlFileLoader(
-            amd,
+         JDBCXmlFileLoader jfl = new JDBCXmlFileLoader(amd,
             container.getClassLoader(),
             container.getLocalClassLoader(),
             log

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PersistentContext.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PersistentContext.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PersistentContext.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -69,6 +69,11 @@
       row.setDirty();
    }
 
+   public void setDirtyRelations()
+   {
+      row.setDirtyRelations();
+   }
+
    public void remove()
    {
       row.delete();

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PkSqlCreateCommand.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PkSqlCreateCommand.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/PkSqlCreateCommand.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -86,6 +86,7 @@
 
             pk = pkField.loadArgumentResults(rs, 1);
             pctx.setFieldValue(pkField.getRowIndex(), pk);
+            pk = entityBridge.extractPrimaryKeyFromInstance(ctx);
          }
          catch(SQLException e)
          {

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/QueryFactory.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/QueryFactory.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/QueryFactory.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -12,6 +12,7 @@
 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCJBossQLQueryMetaData;
 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCQlQueryMetaData;
 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCDeclaredQueryMetaData;
+import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCDynamicQLQueryMetaData;
 import org.jboss.deployment.DeploymentException;
 
 import javax.ejb.FinderException;
@@ -106,6 +107,11 @@
                QueryCommand queryCommand = new DeclaredSQLQueryCommand(entity, (JDBCDeclaredQueryMetaData)q);
                queriesByMethod.put(q.getMethod(), queryCommand);
             }
+            else if(q instanceof JDBCDynamicQLQueryMetaData)
+            {
+               QueryCommand queryCommand = new DynamicQueryCommand(entity, (JDBCDynamicQLQueryMetaData)q);
+               queriesByMethod.put(q.getMethod(), queryCommand);
+            }
             else
             {
                throw new DeploymentException("Unsupported query metadata: method=" + q.getMethod().getName() +

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/bridge/JDBCCMRFieldBridge2.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/bridge/JDBCCMRFieldBridge2.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/bridge/JDBCCMRFieldBridge2.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -114,8 +114,8 @@
       String relatedEntityName = metadata.getRelatedRole().getEntity().getName();
 
       // Related Entity
-      Catalog catalog = (Catalog) manager.getApplicationData("CATALOG");
-      relatedEntity = (JDBCEntityBridge2) catalog.getEntityByEJBName(relatedEntityName);
+      Catalog catalog = (Catalog)manager.getApplicationData("CATALOG");
+      relatedEntity = (JDBCEntityBridge2)catalog.getEntityByEJBName(relatedEntityName);
       if(relatedEntity == null)
       {
          throw new DeploymentException("Related entity not found: "
@@ -131,11 +131,12 @@
             getFieldName()
             +
             ", " +
-            "relatedEntity=" + relatedEntityName);
+            "relatedEntity=" + relatedEntityName
+         );
       }
 
       // Related CMR Field
-      JDBCCMRFieldBridge2[] cmrFields = (JDBCCMRFieldBridge2[]) relatedEntity.getCMRFields();
+      JDBCCMRFieldBridge2[] cmrFields = (JDBCCMRFieldBridge2[])relatedEntity.getCMRFields();
       for(int i = 0; i < cmrFields.length; ++i)
       {
          JDBCCMRFieldBridge2 cmrField = cmrFields[i];
@@ -192,7 +193,7 @@
          Map pkFieldsToFKFields = new HashMap(tableKeys.size());
          for(Iterator i = tableKeys.iterator(); i.hasNext();)
          {
-            JDBCCMPFieldMetaData cmpFieldMetaData = (JDBCCMPFieldMetaData) i.next();
+            JDBCCMPFieldMetaData cmpFieldMetaData = (JDBCCMPFieldMetaData)i.next();
             FieldBridge pkField = entity.getFieldByName(cmpFieldMetaData.getFieldName());
             if(pkField == null)
             {
@@ -212,7 +213,7 @@
             }
             keyFieldsList.add(fkField);
          }
-         tableKeyFields = (JDBCCMPFieldBridge2[]) keyFieldsList.toArray(new JDBCCMPFieldBridge2[keyFieldsList.size()]);
+         tableKeyFields = (JDBCCMPFieldBridge2[])keyFieldsList.toArray(new JDBCCMPFieldBridge2[keyFieldsList.size()]);
       }
       else
       {
@@ -438,16 +439,16 @@
       Map fkFieldsByRelatedPKFields = new HashMap();
       for(Iterator i = foreignKeys.iterator(); i.hasNext();)
       {
-         JDBCCMPFieldMetaData fkFieldMetaData = (JDBCCMPFieldMetaData) i.next();
+         JDBCCMPFieldMetaData fkFieldMetaData = (JDBCCMPFieldMetaData)i.next();
          JDBCCMPFieldBridge2 relatedPKField =
-            (JDBCCMPFieldBridge2) relatedEntity.getFieldByName(fkFieldMetaData.getFieldName());
+            (JDBCCMPFieldBridge2)relatedEntity.getFieldByName(fkFieldMetaData.getFieldName());
 
          // now determine whether the fk is mapped to a pk column
          String fkColumnName = fkFieldMetaData.getColumnName();
          JDBCCMPFieldBridge2 fkField = null;
 
          // look among the CMP fields for the field with the same column name
-         JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[]) entity.getTableFields();
+         JDBCCMPFieldBridge2[] tableFields = (JDBCCMPFieldBridge2[])entity.getTableFields();
          for(int tableInd = 0; tableInd < tableFields.length && fkField == null; ++tableInd)
          {
             JDBCCMPFieldBridge2 cmpField = tableFields[tableInd];
@@ -491,13 +492,13 @@
          for(int i = 0; i < pkFields.length; ++i)
          {
             JDBCFieldBridge relatedPKField = pkFields[i];
-            JDBCFieldBridge fkField = (JDBCCMPFieldBridge2) fkFieldsByRelatedPKFields.remove(relatedPKField);
+            JDBCFieldBridge fkField = (JDBCCMPFieldBridge2)fkFieldsByRelatedPKFields.remove(relatedPKField);
             fkList.add(fkField);
             relatedPKList.add(relatedPKField);
          }
-         foreignKeyFields = (JDBCCMPFieldBridge2[]) fkList.toArray(new JDBCCMPFieldBridge2[fkList.size()]);
+         foreignKeyFields = (JDBCCMPFieldBridge2[])fkList.toArray(new JDBCCMPFieldBridge2[fkList.size()]);
          relatedPKFields =
-            (JDBCCMPFieldBridge2[]) relatedPKList.toArray(new JDBCCMPFieldBridge2[relatedPKList.size()]);
+            (JDBCCMPFieldBridge2[])relatedPKList.toArray(new JDBCCMPFieldBridge2[relatedPKList.size()]);
 
          if(metadata.hasForeignKeyConstraint())
          {
@@ -513,7 +514,7 @@
 
    private FieldState getFieldState(EntityEnterpriseContext ctx)
    {
-      PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+      PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
       FieldState state = pctx.getCMRState(cmrIndex);
       if(state == null)
       {
@@ -535,7 +536,7 @@
       try
       {
          Transaction tx = getTransaction();
-         EntityCache instanceCache = (EntityCache) manager.getContainer().getInstanceCache();
+         EntityCache instanceCache = (EntityCache)manager.getContainer().getInstanceCache();
 
          /*
          RelationInterceptor.RelationInvocation invocation =
@@ -577,7 +578,7 @@
       try
       {
          Transaction tx = getTransaction();
-         EntityCache instanceCache = (EntityCache) manager.getContainer().getInstanceCache();
+         EntityCache instanceCache = (EntityCache)manager.getContainer().getInstanceCache();
          /*
          RelationInterceptor.RelationInvocation invocation =
             new RelationInterceptor.RelationInvocation(RelationInterceptor.CMRMessage.ADD_RELATED_ID);
@@ -638,7 +639,7 @@
          throw new IllegalArgumentException("Argument must be of type " + entity.getLocalInterface().getName());
       }
 
-      EJBLocalObject local = (EJBLocalObject) o;
+      EJBLocalObject local = (EJBLocalObject)o;
       try
       {
          return local.getPrimaryKey();
@@ -685,7 +686,7 @@
             Object relatedId = getPrimaryKey(value);
             addRelatedId(ctx, relatedId);
             relatedCMRField.invokeAddRelatedId(relatedId, ctx.getId());
-            localObject = (EJBLocalObject) value;
+            localObject = (EJBLocalObject)value;
          }
          else
          {
@@ -697,7 +698,7 @@
       {
          if(manager.registerCascadeDelete(ctx.getId(), ctx.getId()))
          {
-            EJBLocalObject value = (EJBLocalObject) getValue(ctx);
+            EJBLocalObject value = (EJBLocalObject)getValue(ctx);
             if(value != null)
             {
                changeValue(null);
@@ -771,7 +772,8 @@
                getFieldName()
                +
                " single-valued CMR field is already loaded. Check the database for consistancy. "
-               + " current value=" + value + ", loaded value=" + pk);
+               + " current value=" + value + ", loaded value=" + pk
+            );
          }
 
          changeValue(pk);
@@ -793,7 +795,7 @@
 
       public void cacheValue(EntityEnterpriseContext ctx)
       {
-         PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+         PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
          pctx.cacheRelations(cmrIndex, this);
       }
 
@@ -815,7 +817,7 @@
       {
          if(!loaded)
          {
-            PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+            PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
             pctx.loadCachedRelations(cmrIndex, this);
             if(!loaded)
             {
@@ -860,12 +862,13 @@
          if(value == null)
          {
             throw new IllegalArgumentException("Can't set collection-valued CMR field to null: " +
-               entity.getEntityName() + "." + getFieldName());
+               entity.getEntityName() + "." + getFieldName()
+            );
          }
 
          destroyExistingRelationships(ctx);
 
-         Collection newValue = (Collection) value;
+         Collection newValue = (Collection)value;
          if(!newValue.isEmpty())
          {
             Set copy = new HashSet(newValue);
@@ -881,10 +884,10 @@
 
       public void cascadeDelete(EntityEnterpriseContext ctx) throws RemoveException
       {
-         Collection value = (Collection) getValue(ctx);
+         Collection value = (Collection)getValue(ctx);
          if(!value.isEmpty())
          {
-            EJBLocalObject[] locals = (EJBLocalObject[]) value.toArray();
+            EJBLocalObject[] locals = (EJBLocalObject[])value.toArray();
             for(int i = 0; i < locals.length; ++i)
             {
                locals[i].remove();
@@ -921,11 +924,28 @@
          }
          else
          {
-            removed = removeWhileNotLoaded(relatedId);
+            loadOnlyFromCache(ctx);
+            if(loaded)
+            {
+               Set value = getLoadedValue(ctx);
+               if(!value.isEmpty())
+               {
+                  removed = value.remove(relatedId);
+               }
+            }
+            else
+            {
+               removed = removeWhileNotLoaded(relatedId);
+            }
          }
 
          modified = true;
 
+         if(removed)
+         {
+            ((PersistentContext)ctx.getPersistenceContext()).setDirtyRelations();
+         }
+
          return removed;
       }
 
@@ -939,11 +959,25 @@
          }
          else
          {
-            added = addWhileNotLoaded(relatedId);
+            loadOnlyFromCache(ctx);
+            if(loaded)
+            {
+               Set value = getLoadedValue(ctx);
+               added = value.add(relatedId);
+            }
+            else
+            {
+               added = addWhileNotLoaded(relatedId);
+            }
          }
 
          modified = true;
 
+         if(added)
+         {
+            ((PersistentContext)ctx.getPersistenceContext()).setDirtyRelations();
+         }
+
          return added;
       }
 
@@ -958,7 +992,8 @@
                getFieldName()
                +
                " collection-valued CMR field is already loaded. Check the database for consistancy. "
-               + " current value=" + value + ", loaded value=" + pk);
+               + " current value=" + value + ", loaded value=" + pk
+            );
          }
 
          if(pk != null)
@@ -971,7 +1006,7 @@
       {
          if(value != null)
          {
-            value = this.value = new HashSet((Set) value);
+            value = this.value = new HashSet((Set)value);
             loaded = true;
          }
          return value;
@@ -984,7 +1019,7 @@
 
       public void cacheValue(EntityEnterpriseContext ctx)
       {
-         PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+         PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
          pctx.cacheRelations(cmrIndex, this);
       }
 
@@ -999,8 +1034,7 @@
       {
          if(!loaded)
          {
-            PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
-            pctx.loadCachedRelations(cmrIndex, this);
+            loadOnlyFromCache(ctx);
 
             if(!loaded)
             {
@@ -1030,6 +1064,12 @@
          return value;
       }
 
+      private void loadOnlyFromCache(EntityEnterpriseContext ctx)
+      {
+         PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
+         pctx.loadCachedRelations(cmrIndex, this);
+      }
+
       private boolean removeWhileNotLoaded(Object relatedId)
       {
          boolean removed = false;
@@ -1120,16 +1160,17 @@
          String relatedTable = relatedEntity.getQualifiedTableName();
          String relationTable = metadata.getRelationMetaData().getDefaultTableName();
 
-         relatedEntity.getTable().appendColumnNames((JDBCCMPFieldBridge2[]) relatedEntity.getTableFields(),
+         relatedEntity.getTable().appendColumnNames((JDBCCMPFieldBridge2[])relatedEntity.getTableFields(),
             relatedTable,
-            sql);
+            sql
+         );
          sql.append(" from ")
             .append(relatedTable)
             .append(" inner join ")
             .append(relationTable)
             .append(" on ");
 
-         JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[]) relatedEntity.getPrimaryKeyFields();
+         JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])relatedEntity.getPrimaryKeyFields();
          for(int i = 0; i < pkFields.length; ++i)
          {
             if(i > 0)
@@ -1199,7 +1240,7 @@
             con = relatedTable.getDataSource().getConnection();
             ps = con.prepareStatement(loadSql);
 
-            JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[]) entity.getPrimaryKeyFields();
+            JDBCCMPFieldBridge2[] pkFields = (JDBCCMPFieldBridge2[])entity.getPrimaryKeyFields();
 
             Object myPk = ctx.getId();
             int paramInd = 1;
@@ -1225,11 +1266,13 @@
             log.error("Failed to load related role: ejb-name="
                +
                entity.getEntityName() +
-               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e);
+               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e
+            );
             throw new EJBException("Failed to load related role: ejb-name="
                +
                entity.getEntityName() +
-               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e);
+               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e
+            );
          }
          finally
          {
@@ -1259,7 +1302,7 @@
       {
          StringBuffer sql = new StringBuffer();
          sql.append("select ");
-         relatedEntity.getTable().appendColumnNames((JDBCCMPFieldBridge2[]) relatedEntity.getTableFields(), null, sql);
+         relatedEntity.getTable().appendColumnNames((JDBCCMPFieldBridge2[])relatedEntity.getTableFields(), null, sql);
          sql.append(" from ").append(relatedEntity.getQualifiedTableName()).append(" where ");
 
          JDBCCMPFieldBridge2[] relatedFkFields = relatedCMRField.foreignKeyFields;
@@ -1323,11 +1366,13 @@
             log.error("Failed to load related role: ejb-name="
                +
                entity.getEntityName() +
-               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e);
+               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e
+            );
             throw new EJBException("Failed to load related role: ejb-name="
                +
                entity.getEntityName() +
-               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e);
+               ", cmr-field=" + getFieldName() + ": " + e.getMessage(), e
+            );
          }
          finally
          {
@@ -1377,7 +1422,7 @@
 
          if(fkConstraint != null)
          {
-            PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+            PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
             pctx.nullForeignKey(fkConstraint);
          }
       }
@@ -1394,7 +1439,7 @@
 
          if(fkConstraint != null)
          {
-            PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
+            PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
             if(relatedId == null)
             {
                pctx.nullForeignKey(fkConstraint);
@@ -1416,7 +1461,8 @@
       void addRelatedId(EntityEnterpriseContext ctx, Object relatedId);
    }
 
-   private class CMRSet implements Set
+   private class CMRSet
+      implements Set
    {
       private final EntityEnterpriseContext ctx;
       private final CollectionValuedFieldState state;
@@ -1599,7 +1645,7 @@
       {
          Set value = state.getLoadedValue(ctx);
 
-         Object[] result = (Object[]) Array.newInstance(relatedEntity.getLocalInterface(), value.size());
+         Object[] result = (Object[])Array.newInstance(relatedEntity.getLocalInterface(), value.size());
 
          LocalProxyFactory relatedPF = relatedContainer.getLocalProxyFactory();
          int i = 0;
@@ -1617,7 +1663,7 @@
          Set value = state.getLoadedValue(ctx);
          if(a == null || a.length < value.size())
          {
-            a = (Object[]) Array.newInstance(entity.getLocalInterface(), value.size());
+            a = (Object[])Array.newInstance(entity.getLocalInterface(), value.size());
          }
 
          LocalProxyFactory relatedPF = relatedContainer.getLocalProxyFactory();

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/EntityTable.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/EntityTable.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/EntityTable.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -63,6 +63,7 @@
    private static final byte DIRTY = 2;
    private static final byte CREATED = 4;
    private static final byte DELETED = 8;
+   private static final byte DIRTY_RELATIONS = 16;
 
    private JDBCEntityBridge2 entity;
    private String tableName;
@@ -158,8 +159,53 @@
          invalidable = false;
       }
 
-      cache = cacheConf == null ? Cache.NONE : new PartitionedTableCache(minCapacity, maxCapacity, partitionsTotal);
+      if(cachePolicy != null)
+      {
+         cache = new PartitionedTableCache(minCapacity, maxCapacity, partitionsTotal);
 
+         String periodStr = MetaData.getOptionalChildContent(cachePolicy, "overager-period");
+         String maxAgeStr = MetaData.getOptionalChildContent(cachePolicy, "max-bean-age");
+         if(periodStr != null && maxAgeStr == null || maxAgeStr != null && periodStr == null)
+         {
+            throw new DeploymentException(
+               "Failed to initialize age-out thread for entity " + entity.getEntityName() +
+               ": overager-period or max-bean-age is missing!");
+         }
+         else if(periodStr != null && maxAgeStr != null)
+         {
+            long period = Long.parseLong(periodStr);
+            long maxAge = Long.parseLong(maxAgeStr);
+            ((PartitionedTableCache)cache).initOverager(period, maxAge, entity.getEntityName() + " overager");
+
+            if(log.isTraceEnabled())
+            {
+               log.trace("initialized age-out thread for " + entity.getEntityName() +
+                  ": overager-period=" + period + ", max-bean-age=" + maxAge);
+            }
+         }
+
+         final MBeanServer server = MBeanServerLocator.locateJBoss();
+         serviceController = (ServiceControllerMBean)
+            MBeanProxyExt.create(ServiceControllerMBean.class,
+               ServiceControllerMBean.OBJECT_NAME,
+               server);
+         try
+         {
+            cacheName =
+               new ObjectName("jboss.cmp:service=tablecache,ejbname=" + metadata.getName() + ",table=" + tableName);
+            server.registerMBean(cache, cacheName);
+            serviceController.create(cacheName);
+         }
+         catch(Exception e)
+         {
+            throw new DeploymentException("Failed to register table cache for " + tableName, e);
+         }
+      }
+      else
+      {
+         cache = Cache.NONE;
+      }
+
       if(invalidable)
       {
          String groupName = entityMetaData.getDistributedCacheInvalidationConfig().getInvalidationGroupName();
@@ -179,31 +225,11 @@
       }
       else
       {
-         log.debug("batch-commit-strategy");
+         log.debug("batch-commit-strategy enabled");
          insertStrategy = BATCH_UPDATE;
          deleteStrategy = BATCH_UPDATE;
          updateStrategy = BATCH_UPDATE;
       }
-
-      if(cache != Cache.NONE)
-      {
-         final MBeanServer server = MBeanServerLocator.locateJBoss();
-         serviceController = (ServiceControllerMBean)
-            MBeanProxyExt.create(ServiceControllerMBean.class,
-               ServiceControllerMBean.OBJECT_NAME,
-               server);
-         try
-         {
-            cacheName =
-               new ObjectName("jboss.cmp:service=tablecache,ejbname=" + metadata.getName() + ",table=" + tableName);
-            server.registerMBean(cache, cacheName);
-            serviceController.create(cacheName);
-         }
-         catch(Exception e)
-         {
-            throw new DeploymentException("Failed to register table cache for " + tableName, e);
-         }
-      }
    }
 
    public void start() throws DeploymentException
@@ -790,6 +816,7 @@
       private Row created;
       private Row deleted;
       private Row dirty;
+      private Row dirtyRelations;
       private Row clean;
 
       private Row cacheUpdates;
@@ -1146,6 +1173,15 @@
 
       public void flushUpdated() throws SQLException
       {
+         if(dirtyRelations != null)
+         {
+            while(dirtyRelations != null)
+            {
+               Row row = dirtyRelations;
+               row.flushStatus();
+            }
+         }
+
          if(dirty == null)
          {
             if(log.isTraceEnabled())
@@ -1407,20 +1443,28 @@
 
       public boolean isDirty()
       {
-         return state != CLEAN;
+         return state != CLEAN && state != DIRTY_RELATIONS;
       }
 
       public void setDirty()
       {
-         if(state == CLEAN)
+         if(state == CLEAN || state == DIRTY_RELATIONS)
          {
             updateState(DIRTY);
          }
       }
 
+      public void setDirtyRelations()
+      {
+         if(state == CLEAN)
+         {
+            updateState(DIRTY_RELATIONS);
+         }
+      }
+
       public void delete()
       {
-         if(state == CLEAN || state == DIRTY)
+         if(state == CLEAN || state == DIRTY || state == DIRTY_RELATIONS)
          {
             updateState(DELETED);
          }
@@ -1465,6 +1509,10 @@
          {
             dereference();
          }
+         else if(state == DIRTY_RELATIONS)
+         {
+            updateState(CLEAN);
+         }
 
          scheduleCacheUpdate();
       }
@@ -1526,6 +1574,15 @@
             }
             view.deleted = this;
          }
+         else if(state == DIRTY_RELATIONS)
+         {
+            if(view.dirtyRelations != null)
+            {
+               next = view.dirtyRelations;
+               view.dirtyRelations.prev = this;
+            }
+            view.dirtyRelations = this;
+         }
          else
          {
             throw new IllegalStateException("Can't update to state: " + state);
@@ -1552,6 +1609,10 @@
          {
             view.deleted = next;
          }
+         else if(state == DIRTY_RELATIONS && view.dirtyRelations == this)
+         {
+            view.dirtyRelations = next;
+         }
 
          if(next != null)
          {

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/PartitionedTableCache.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/PartitionedTableCache.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/PartitionedTableCache.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -28,6 +28,8 @@
 
    private final TableCache[] partitions;
 
+   private Overager overager;
+
    public PartitionedTableCache(int minCapacity, int maxCapacity, int partitionsTotal)
    {
       this.minCapacity = minCapacity;
@@ -47,12 +49,32 @@
       }
    }
 
+   public void stopService()
+   {
+      if(overager != null)
+      {
+         overager.stop();
+      }
+   }
+
+   public void initOverager(long period, long maxAge, String threadName)
+   {
+      final long periodMs = period * 1000;
+      final long maxAgeMs = maxAge * 1000;
+      overager = new Overager(maxAgeMs, periodMs);
+      new Thread(overager, threadName).start();
+   }
+
    /**
     * @jmx.managed-operation
     */
    public void registerListener(Cache.Listener listener)
    {
-      log.debug("Registered listener for " + getServiceName());
+      if(log.isTraceEnabled())
+      {
+         log.trace("registered listener for " + getServiceName());
+      }
+
       this.listener = listener;
       for(int i = 0; i < partitions.length; ++i)
       {
@@ -204,11 +226,51 @@
          }
       }
    }
-
+   
    // Private
 
    private int getPartitionIndex(Object key)
    {
       return Math.abs(key.hashCode()) % partitions.length;
    }
+
+   // Inner
+
+   private class Overager implements Runnable
+   {
+      private final long maxAgeMs;
+      private final long periodMs;
+      private boolean run = true;
+
+      public Overager(long maxAgeMs, long periodMs)
+      {
+         this.maxAgeMs = maxAgeMs;
+         this.periodMs = periodMs;
+      }
+
+      public void stop()
+      {
+         run = false;
+      }
+
+      public void run()
+      {
+         while(run)
+         {
+            long lastUpdated = System.currentTimeMillis() - maxAgeMs;
+            for(int i = 0; i < partitions.length; ++i)
+            {
+               partitions[i].ageOut(lastUpdated);
+            }
+
+            try
+            {
+               Thread.sleep(periodMs);
+            }
+            catch(InterruptedException e)
+            {
+            }
+         }
+      }
+   }
 }

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/Schema.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/Schema.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/Schema.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -34,6 +34,12 @@
       protected Object initialValue()
       {
          Transaction tx = getTransaction();
+
+         if(tx == null)
+         {
+            throw new IllegalStateException("An operation requires an active transaction!");
+         }
+
          Views views = new Views(tx);
          Synchronization sync = new SchemaSynchronization(views);
 

Modified: branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/TableCache.java
===================================================================
--- branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/TableCache.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/server/src/main/org/jboss/ejb/plugins/cmp/jdbc2/schema/TableCache.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -63,7 +63,10 @@
     */
    public void registerListener(Cache.Listener listener)
    {
-      log.debug("Registered listener for " + getServiceName());
+      if(log.isTraceEnabled() && getServiceName() != null)
+      {
+         log.trace("registered listener for " + getServiceName());
+      }
       this.listener = listener;
    }
 
@@ -228,6 +231,7 @@
             System.arraycopy(relations, 0, row.relations, 0, relations.length);
          }
 
+         row.lastUpdated = System.currentTimeMillis();
          row.locker = null;
       }
 
@@ -245,6 +249,22 @@
       }
    }
 
+   public void ageOut(long lastUpdated)
+   {
+      CachedRow victim = tail;
+      while(victim != null && victim.lastUpdated < lastUpdated)
+      {
+         CachedRow nextVictim = victim.prev;
+         if(victim.locker == null)
+         {
+            dereference(victim);
+            rowsById.remove(victim.pk);
+            listener.eviction(partitionIndex, victim.pk, rowsById.size());
+         }
+         victim = nextVictim;
+      }
+   }
+
    public void remove(Transaction tx, Object pk)
    {
       CachedRow row = (CachedRow) rowsById.remove(pk);
@@ -307,7 +327,7 @@
       this.head = null;
       this.tail = null;
    }
-
+   
    public String toString()
    {
       StringBuffer buf = new StringBuffer();
@@ -432,6 +452,8 @@
       private CachedRow next;
       private CachedRow prev;
 
+      public long lastUpdated = System.currentTimeMillis();
+
       public CachedRow(Object pk, Object[] fields)
       {
          this.pk = pk;

Modified: branches/JBoss_3_2_7_CP/testsuite/imports/test-jars.xml
===================================================================
--- branches/JBoss_3_2_7_CP/testsuite/imports/test-jars.xml	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/testsuite/imports/test-jars.xml	2006-08-15 01:45:04 UTC (rev 55928)
@@ -882,7 +882,47 @@
          <zipfileset src="${junit.junit.lib}/junit.jar"
             includes="junit/**/*.*"/>
       </jar>
+      <copy file="${build.resources}/cmp2/ejbselect/META-INF/jboss.xml"
+         tofile="${build.resources}/cmp2/ejbselect/META-INF/original-jboss.xml"/>
+      <copy file="${build.resources}/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml"
+         tofile="${build.resources}/cmp2/ejbselect/META-INF/jboss.xml" overwrite="true"/>
+      <jar jarfile="${build.lib}/cmp2-jdbc2pm-ejbselect.jar">
+         <fileset dir="${build.classes}">
+            <patternset refid="common.test.client.classes"/>
+            <include name="org/jboss/test/cmp2/ejbselect/**"/>
+         </fileset>
+         <fileset dir="${build.resources}/cmp2/ejbselect">
+            <include name="**/*.*"/>
+         </fileset>
+         <zipfileset src="${junitejb.junitejb.lib}/junitejb.jar"
+            includes="net/**/*.*"/>
+         <zipfileset src="${junit.junit.lib}/junit.jar"
+            includes="junit/**/*.*"/>
+      </jar>
+      <copy file="${build.resources}/cmp2/ejbselect/META-INF/original-jboss.xml"
+         tofile="${build.resources}/cmp2/ejbselect/META-INF/jboss.xml" overwrite="true"/>
 
+      <!-- build cmp2-jdbc2pm-ageout.jar -->
+      <copy file="${build.resources}/cmp2/ejbselect/META-INF/ejb-jar.xml"
+         tofile="${build.resources}/cmp2/ageout/META-INF/ejb-jar.xml" overwrite="true"/>
+      <copy file="${build.resources}/cmp2/ejbselect/META-INF/jbosscmp-jdbc.xml"
+         tofile="${build.resources}/cmp2/ageout/META-INF/jbosscmp-jdbc.xml" overwrite="true"/>
+      <jar destfile="${build.lib}/cmp2-jdbc2pm-ageout.jar">
+         <fileset dir="${build.classes}">
+            <patternset refid="common.test.client.classes"/>
+            <include name="org/jboss/test/cmp2/ageout/**"/>
+            <include name="org/jboss/test/cmp2/ejbselect/**"/>
+            <exclude name="org/jboss/test/cmp2/ejbselect/**/*TestCase.class"/>
+         </fileset>
+         <fileset dir="${build.resources}/cmp2/ageout">
+            <include name="**/*.*"/>
+         </fileset>
+         <zipfileset src="${junitejb.junitejb.lib}/junitejb.jar"
+            includes="net/**/*.*"/>
+         <zipfileset src="${junit.junit.lib}/junit.jar"
+            includes="junit/**/*.*"/>
+      </jar>
+
       <!-- build cmr-postcreateswritten.jar -->
       <jar destfile="${build.lib}/cmr-postcreateswritten.jar">
          <fileset dir="${build.classes}">
@@ -1019,6 +1059,7 @@
       <jar destfile="${build.lib}/cmp2-keygen.jar">
          <fileset dir="${build.classes}">
             <include name="org/jboss/test/cmp2/keygen/**"/>
+            <include name="org/jboss/test/util/ejb/**"/>
          </fileset>
          <fileset dir="${build.resources}/cmp2/keygen">
             <include name="**/*.*"/>

Copied: branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/main/org/jboss/test/cmp2/ageout)

Copied: branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/main/org/jboss/test/cmp2/ageout/test)

Deleted: branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java
===================================================================
--- branches/JBoss_3_2_7_JBAS-2361/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java	2006-08-15 01:45:04 UTC (rev 55928)
@@ -1,246 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.test.cmp2.ageout.test;
-
-import java.sql.Connection;
-import java.sql.Statement;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.sql.DataSource;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
-import org.jboss.ejb.plugins.cmp.jdbc2.schema.Cache;
-import org.jboss.test.JBossTestCase;
-import org.jboss.test.cmp2.ejbselect.ALocal;
-import org.jboss.test.cmp2.ejbselect.ALocalHome;
-import org.jboss.test.cmp2.ejbselect.AUtil;
-import org.jboss.mx.util.MBeanServerLocator;
-import junit.framework.Test;
-import net.sourceforge.junitejb.EJBTestCase;
-
-/**
- * @author <a href="mailto:alex at jboss.org">Alexey Loubyansky</a>
- * @version <tt>$Revision$</tt>
- */
-public class JDBC2PmAgeOutUnitTestCase
-   extends EJBTestCase
-{
-   private int maxAgeMs = 3000;
-   private int overagerPeriodMs = 1000;
-   private DataSource ds;
-   private TransactionManager tm;
-   private CacheListener cacheListener;
-
-   public JDBC2PmAgeOutUnitTestCase(String methodName)
-   {
-      super(methodName);
-   }
-
-   public static Test suite() throws Exception
-   {
-      return JBossTestCase.getDeploySetup(JDBC2PmAgeOutUnitTestCase.class, "cmp2-jdbc2pm-ageout.jar");
-   }
-
-   public void setUpEJB() throws Exception
-   {
-      MBeanServer server = MBeanServerLocator.locateJBoss();
-      cacheListener = new CacheListener();
-      server.invoke(new ObjectName("jboss.cmp:ejbname=A,service=tablecache,table=TEST_A"),
-         "registerListener", new Object[]{
-            cacheListener
-         }, new String[]{Cache.Listener.class.getName()});
-   }
-
-   public void testAgeOut() throws Exception
-   {
-      Transaction tx = suspendTx();
-      String id = "a1";
-
-      try
-      {
-         beginTx();
-         ALocalHome ah = AUtil.getLocalHome();
-         ALocal a = ah.create(id);
-         a.setIntField(1);
-         commitTx();
-         long lastUpdated = System.currentTimeMillis();
-
-         checkAge(lastUpdated);
-         assertValue(id, 1);
-
-         checkAge(lastUpdated);
-         jdbcUpdate(id, 2);
-
-         checkAge(lastUpdated);
-         assertValue(id, 1);
-
-         sleepUntilEvicted();
-         long lastEvicted = cacheListener.lastEvicted;
-         assertValue(id, 2);
-
-         // test ejb update
-         try
-         {
-            Thread.sleep(1000);
-         }
-         catch(InterruptedException e)
-         {
-            e.printStackTrace();
-         }
-
-         beginTx();
-         a = ah.findByPrimaryKey(id);
-         a.setIntField(3);
-         commitTx();
-
-         sleepUntilEvicted();
-         assertTrue(cacheListener.lastEvicted - lastEvicted >= maxAgeMs + 1000);
-      }
-      finally
-      {
-         resumeTx(tx);
-      }
-   }
-
-   private void sleepUntilEvicted()
-   {
-      int sleepTime = 0;
-      while(!cacheListener.evicted)
-      {
-         try
-         {
-            Thread.sleep(1000);
-            sleepTime += 1000;
-         }
-         catch(InterruptedException e)
-         {
-            e.printStackTrace();
-         }
-
-         if(!cacheListener.evicted && sleepTime > maxAgeMs + overagerPeriodMs)
-         {
-            fail("The instance must have been evicted!");
-         }
-      }
-      cacheListener.evicted = false;      
-   }
-
-   private void checkAge(long lastUpdated)
-      throws Exception
-   {
-      if(System.currentTimeMillis() - lastUpdated > maxAgeMs)
-      {
-         throw new Exception("maxAgeMs should be increased for this test to work.");
-      }
-   }
-
-   private void assertValue(String id, int value) throws Exception
-   {
-      beginTx();
-      try
-      {
-         ALocalHome ah = AUtil.getLocalHome();
-         ALocal a = ah.findByPrimaryKey(id);
-         assertEquals(value, a.getIntField());
-      }
-      finally
-      {
-         commitTx();
-      }
-   }
-
-   private void jdbcUpdate(String id, int value) throws Exception
-   {
-      DataSource ds = getDS();
-      Connection con = null;
-      Statement st = null;
-      try
-      {
-         con = ds.getConnection();
-         st = con.createStatement();
-         int rows = st.executeUpdate("update TEST_A set INT_FIELD=" +
-            value + " where ID='" + id + "'"
-         );
-         if(rows != 1)
-         {
-            throw new Exception("Expected one updated row but got " + rows);
-         }
-      }
-      finally
-      {
-         JDBCUtil.safeClose(st);
-         JDBCUtil.safeClose(con);
-      }
-   }
-
-   private DataSource getDS() throws NamingException
-   {
-      if(ds == null)
-      {
-         ds = (DataSource)new InitialContext().lookup("java:/DefaultDS");
-      }
-      return ds;
-   }
-
-   private Transaction suspendTx() throws Exception
-   {
-      return getTM().suspend();
-   }
-
-   private void resumeTx(Transaction tx) throws Exception
-   {
-      getTM().resume(tx);
-   }
-
-   private Transaction beginTx() throws Exception
-   {
-      getTM().begin();
-      return getTM().getTransaction();
-   }
-
-   private void commitTx() throws Exception
-   {
-      getTM().commit();
-   }
-
-   private TransactionManager getTM()
-      throws NamingException
-   {
-      if(tm == null)
-      {
-         tm = (TransactionManager)new InitialContext().lookup("java:/TransactionManager");
-      }
-      return tm;
-   }
-
-   private static class CacheListener implements Cache.Listener
-   {
-      public long lastEvicted;
-      public boolean evicted;
-
-      public void contention(int partitionIndex, long time)
-      {
-      }
-
-      public void eviction(int partitionIndex, Object pk, int size)
-      {
-         lastEvicted = System.currentTimeMillis();
-         evicted = true;
-      }
-
-      public void hit(int partitionIndex)
-      {
-      }
-
-      public void miss(int partitionIndex)
-      {
-      }
-   }
-}

Copied: branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/main/org/jboss/test/cmp2/ageout/test/JDBC2PmAgeOutUnitTestCase.java)

Copied: branches/JBoss_3_2_7_CP/testsuite/src/main/org/jboss/test/cmp2/ejbselect/JDBC2PmEJBSelectUnitTestCase.java (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/main/org/jboss/test/cmp2/ejbselect/JDBC2PmEJBSelectUnitTestCase.java)

Copied: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ageout)

Copied: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ageout/META-INF)

Deleted: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml
===================================================================
--- branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml	2006-08-15 01:45:04 UTC (rev 55928)
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd">
-
-<jboss>
-
-   <enterprise-beans>
-
-        <session>
-         <ejb-name>EJBTestRunnerEJB</ejb-name>
-         <jndi-name>ejb/EJBTestRunner</jndi-name>
-      </session>
-
-      <entity>
-         <ejb-name>B</ejb-name>
-         <local-jndi-name>BLocal</local-jndi-name>
-         <configuration-name>cmp2.x jdbc2 pm</configuration-name>
-      </entity>
-      <entity>
-         <ejb-name>A</ejb-name>
-         <local-jndi-name>ALocal</local-jndi-name>
-         <configuration-name>cmp2.x jdbc2 pm with overager</configuration-name>
-      </entity>
-   </enterprise-beans>
-
-   <container-configurations>
-    <container-configuration extends="cmp2.x jdbc2 pm">
-      <container-name>cmp2.x jdbc2 pm with overager</container-name>
-      <container-cache-conf>
-         <cache-policy-conf>
-            <min-capacity>500</min-capacity>
-            <max-capacity>10000</max-capacity>
-            <overager-period>1</overager-period>
-            <max-bean-age>3</max-bean-age>
-         </cache-policy-conf>
-         <cache-policy-conf-other>
-            <partitions>10</partitions>
-         </cache-policy-conf-other>
-      </container-cache-conf>
-    </container-configuration>
-   </container-configurations>
-</jboss>

Copied: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ageout/META-INF/jboss.xml)

Copied: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ejbselect)

Copied: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ejbselect/META-INF)

Deleted: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml
===================================================================
--- branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml	2006-08-15 01:38:54 UTC (rev 55927)
+++ branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml	2006-08-15 01:45:04 UTC (rev 55928)
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.2//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd">
-
-<jboss>
-
-   <enterprise-beans>
-
-        <session>
-         <ejb-name>EJBTestRunnerEJB</ejb-name>
-         <jndi-name>ejb/EJBTestRunner</jndi-name>
-      </session>
-
-      <entity>
-         <ejb-name>B</ejb-name>
-         <local-jndi-name>BLocal</local-jndi-name>
-         <container-name>cmp2.x jdbc2 pm</container-name>
-      </entity>
-      <entity>
-         <ejb-name>A</ejb-name>
-         <local-jndi-name>ALocal</local-jndi-name>
-         <container-name>cmp2.x jdbc2 pm</container-name>
-      </entity>
-   </enterprise-beans>
-</jboss>

Copied: branches/JBoss_3_2_7_CP/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml (from rev 55927, branches/JBoss_3_2_7_JBAS-2361/testsuite/src/resources/cmp2/ejbselect/META-INF/jdbc2pm-jboss.xml)




More information about the jboss-cvs-commits mailing list