Hello Folks,
    Took a wild shot at the Option D, timed cache invalidation. Have put it in a separate interceptor that sits before the EntitySynchronizationInterceptor and invalidates the EntityEnterpriseContext at regular preset intervals.
 
1. There is an invalidation timer task per entity bean [I persum per-EntityEnterpriseContext maps to per bean and not per bean instance]
2. The refersh rate is currently set at 60secs but could be moved elsewhere to the jboss config xml
3. The Configuration Metadat now has an entry for option D.
4. The interceptor does NOT reload the entity. It just invalidates the cache. The entity reload is managed by the EntitySynchronizationInterceptor.
 
Does anyone want to go thru this and get back to me? It is a first cut code using this method [the previous one had some code that was junked!]. What I'd like someone to point out is
 
1. Do we need to take care of any transaction related issues in the invoke method?
2. Am adding to a hashset. Now the Context object is removed from the hashset only when the if(ctx.getId()) evaluates to null. Do we need to have any other place where we remove the context from the list of items to be invalidated? We will have the underlying database updated by other programs that are not linked into Jboss.
 
If the code is a complete pile of crap let me know and would appreciate if you could give some pointers as well as to what is incorrect and how it could be improved. At the moment it is pretty much a crude piece of code!
 
Regards
 
Vinay
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.ejb.plugins;
 
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.rmi.ServerException;
 
import java.util.Timer;
import java.util.TimerTask;
import java.util.HashSet;
import java.util.Iterator;
 
import javax.ejb.EJBObject;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.NoSuchEntityException;
import javax.ejb.RemoveException;
import javax.ejb.EntityBean;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
 
import org.jboss.ejb.Container;
import org.jboss.ejb.EntityContainer;
import org.jboss.ejb.EntityPersistenceManager;
import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.EnterpriseContext;
import org.jboss.ejb.InstanceCache;
import org.jboss.ejb.InstancePool;
import org.jboss.ejb.MethodInvocation;
import org.jboss.metadata.ConfigurationMetaData;
import org.jboss.logging.Logger;
 
public class SoftBallInterceptor
extends AbstractInterceptor
{
    protected int commitOption;
    protected EntityContainer container;
    protected HashSet ctxToInvalidate = new HashSet();
    private static int REFRESH_RATE = 60000;
 
    public void setContainer(Container container)
    {
       this.container = (EntityContainer)container;
    }
 
    public void init()
    throws Exception
    {
       commitOption = container.getBeanMetaData().getContainerConfiguration().getCommitOption();
 
       if(commitOption == ConfigurationMetaData.D_COMMIT_OPTION)
       {
           //Start Timer Task Now!
           new Timer().schedule(new ForceSynchronization(),0,REFRESH_RATE);
        }
    }
 
    public Container getContainer()
    {
       return container;
    }
 
    private void register(EntityEnterpriseContext ctx, Transaction tx)
    {
    }
 
    private void deregister(EntityEnterpriseContext ctx)
    {
    }
 
    // Interceptor implementation --------------------------------------
 
    public Object invokeHome(MethodInvocation mi)
    throws Exception
    {
       try {
         return getNext().invokeHome(mi);
       } finally {
         // Anonymous was sent in, so if it has an id it was created
         EntityEnterpriseContext ctx = (EntityEnterpriseContext)mi.getEnterpriseContext();
         if (ctx.getId() != null) {
          Transaction tx = mi.getTransaction();
 
          if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE)
              register(ctx, tx); // Set tx
 
          // Currently synched with underlying storage
          ctx.setValid(true);
         }
       }
    }
 
    public Object invoke(MethodInvocation mi)
    throws Exception
    {
       if(commitOption == ConfigurationMetaData.D_COMMIT_OPTION)
       {
           EntityEnterpriseContext ctx = (EntityEnterpriseContext)mi.getEnterpriseContext();
 

           if(ctx.getId()!=null)
           {
               synchronized(ctxToInvalidate)
               {
                 this.ctxToInvalidate.add(ctx);
               }
           }
           else
           {
               synchronized(ctxToInvalidate)
               {
                 this.ctxToInvalidate.remove(ctx);
               }
            }
       }
 
       return getNext().invoke(mi);
    }
 

    private class ForceSynchronization
    extends TimerTask
    {
       ForceSynchronization()
       {
       }
 
        public void run()
        {
           synchronized(ctxToInvalidate)
           {
                Iterator it = ctxToInvalidate.iterator();
 
                while(it.hasNext())
                {
                   EntityEnterpriseContext ctx = (EntityEnterpriseContext)it.next();
                   ctx.setValid(false);
                }
            }
        }
    }
}
 
 

Reply via email to