FileDocCategorySizeDatePackage
ReadOnlyBeanContainer.javaAPI DocGlassfish v2 API36982Fri May 04 22:32:58 BST 2007com.sun.ejb.containers

ReadOnlyBeanContainer

public class ReadOnlyBeanContainer extends EntityContainer implements com.sun.ejb.spi.distributed.ReadOnlyBeanRefreshEventHandler
The Container that manages instances of ReadOnly Beans. This container blocks all calls to ejbStore() and selectively performs ejbLoad()
author
Mahesh Kannan
author
Pramod Gopinath

Fields Summary
private static final Logger
_logger
private long
refreshPeriodInMillis
private int
beanLevelSequenceNum
private long
beanLevelLastRefreshRequestedAt
private volatile long
currentTimeInMillis
private TimerTask
refreshTask
private com.sun.ejb.containers.util.cache.EJBObjectCache
robCache
private com.sun.ejb.spi.distributed.DistributedReadOnlyBeanService
distributedReadOnlyBeanService
private volatile Map
finderResultsCache
private static final int
FINDER_LOCK_SIZE
private Object[]
finderLocks
private boolean
RELATIVE_TIME_CHECK_MODE
Constructors Summary
protected ReadOnlyBeanContainer(EjbDescriptor desc, ClassLoader loader)


        
         
    
        super(desc, loader);

        containerFactory = (ContainerFactoryImpl)
            theSwitch.getContainerFactory();
        EjbEntityDescriptor ed = (EjbEntityDescriptor)desc;
        refreshPeriodInMillis =
            ed.getIASEjbExtraDescriptors().getRefreshPeriodInSeconds() * 1000;

        if( refreshPeriodInMillis > 0 ) {
            long timerFrequency = 1;
            String refreshRateStr =
            System.getProperty("com.sun.ejb.containers.readonly.timer.frequency", "1");
            try {
                timerFrequency = Integer.parseInt(refreshRateStr);
                if (timerFrequency < 0) {
                    timerFrequency = 1;
                }
            } catch (Exception ex) {
                _logger.log(Level.FINE, "Invalid timer frequency " + refreshRateStr);
            }

            try {
                RELATIVE_TIME_CHECK_MODE  = Boolean.valueOf(System.getProperty(
                        "com.sun.ejb.containers.readonly.relative.refresh.mode"));
                _logger.log(Level.FINE, "RELATIVE_TIME_CHECK_MODE: " + RELATIVE_TIME_CHECK_MODE);
            } catch (Exception ex) {
            	_logger.log(Level.FINE, "(Ignorable) Exception while initializing RELATIVE_TIME_CHECK_MODE", ex);
            }

            Timer timer = 
                ContainerFactoryImpl.getContainerService().getTimer();
            if (RELATIVE_TIME_CHECK_MODE) {
                refreshTask = new CurrentTimeRefreshTask ();
                timer.scheduleAtFixedRate(refreshTask, timerFrequency*1000, timerFrequency*1000);
            } else {
                refreshTask = new RefreshTask();
                timer.scheduleAtFixedRate(refreshTask, refreshPeriodInMillis, 
                                      refreshPeriodInMillis);
            }
        } else {
            refreshPeriodInMillis = 0;
        }
        
        for (int i=0; i<FINDER_LOCK_SIZE; i++) {
        	finderLocks[i] = new Object();
        }

        // Create read-only bean cache
        long idleTimeoutInMillis = (cacheProp.cacheIdleTimeoutInSeconds <= 0) ?
            -1 : (cacheProp.cacheIdleTimeoutInSeconds * 1000);

        if( (cacheProp.maxCacheSize <= 0) && (idleTimeoutInMillis <= 0) ) {
            robCache = new UnboundedEJBObjectCache(ejbDescriptor.getName());
            robCache.init(DEFAULT_CACHE_SIZE, cacheProp.numberOfVictimsToSelect,
                          0L, 1.0F, null);
        } else {
            int cacheSize = (cacheProp.maxCacheSize <= 0) ?
                DEFAULT_CACHE_SIZE : cacheProp.maxCacheSize;
            robCache = new FIFOEJBObjectCache(ejbDescriptor.getName());
        
            robCache.init(cacheSize, 
                          cacheProp.numberOfVictimsToSelect, 
                          idleTimeoutInMillis, 1.0F, null);
            // .setEJBObjectCacheListener(
            //     new EJBObjectCacheVictimHandler());
        }
        
        this.distributedReadOnlyBeanService =
            DistributedEJBServiceFactory.getDistributedEJBService()
                .getDistributedReadOnlyBeanService();
        this.distributedReadOnlyBeanService.addReadOnlyBeanRefreshEventHandler(
                getContainerId(), getClassLoader(), this);
        

    
Methods Summary
protected ComponentContext_getContext(Invocation inv)

        ComponentContext ctx = super._getContext(inv);

        InvocationInfo info = inv.invocationInfo; // info cannot be null
        if (info.isTxRequiredLocalCMPField) {
            if (! inv.foundInTxCache) {
                EntityContextImpl entityCtx = (EntityContextImpl) ctx;
                super.afterBegin(entityCtx);
                inv.foundInTxCache = true;
            }
        } else {
            //TODO: We can still optimize NonTx access to CMP getters/setters
        }
        return ctx;
    
protected voidaddPooledEJB(EntityContextImpl ctx)

        try {
            ReadOnlyContextImpl readOnlyCtx = (ReadOnlyContextImpl)ctx;
            if( readOnlyCtx.getReadOnlyBeanInfo() != null ) {

                readOnlyCtx.setReadOnlyBeanInfo(null);
                
                robCache.remove(ctx.getPrimaryKey(), true);
            }                                    
        } catch (Exception ex) {

            _logger.log(Level.SEVERE, "ejb.addPooledEJB", ex);
            EJBException ejbEx = new EJBException();
            ejbEx.initCause(ex);
            throw ejbEx;

        } finally {
            super.addPooledEJB(ctx);
        }
    
private ReadOnlyBeanInfoaddToCache(java.lang.Object primaryKey, boolean incrementRefCount)

        
        // Optimize for the cache where the cache item already
        // exists and we have a 2nd, 3rd, 4th, etc. context for
        // the same primary key.  If the item exists, the ref count
        // will be incremented.
        ReadOnlyBeanInfo robInfo = (ReadOnlyBeanInfo) 
            robCache.get(primaryKey, incrementRefCount);

        if( robInfo == null ) {

            // If the item doesn't exist, create a new one.  The cache
            // ensures that the ref count is correct in the face of concurrent
            // puts.

            ReadOnlyBeanInfo newRobInfo = new ReadOnlyBeanInfo();

            newRobInfo.primaryKey = primaryKey;

            // Initialize bean level sequence num so that the first time an
            // instance of this PK goes through callEJBLoad, it will force
            // a refresh.
            newRobInfo.beanLevelSequenceNum = -1;
            newRobInfo.refreshNeeded = true;

            newRobInfo.pkLevelSequenceNum = 1;

            newRobInfo.lastRefreshRequestedAt = 0;
            newRobInfo.lastRefreshedAt = 0;

            // Cache ejbObject/ejbLocalObject within ROB info.
            // This value is used by
            // findByPrimaryKey to avoid a DB access.  Caching here
            // ensures that there will be one DB access for the PK 
            // regardless of the order in which findByPrimaryKey is called
            // with respect to the business method call.  This also covers
            // the case where a business method is invoked through the
            // local view and findByPrimaryKey is invoked through the
            // Remote view (or vice versa).  
            if( ejbDescriptor.isLocalInterfacesSupported() ) {
                newRobInfo.cachedEjbLocalObject = 
                    getEJBLocalObjectForPrimaryKey(primaryKey);
            }
            if( ejbDescriptor.isRemoteInterfacesSupported() ) {
                newRobInfo.cachedEjbObject = 
                    getEJBObjectStub(primaryKey, null);
            }
            
            ReadOnlyBeanInfo otherRobInfo = (ReadOnlyBeanInfo)
                robCache.put(primaryKey, newRobInfo, incrementRefCount);

            // If someone else inserted robInfo for this pk before *our* put(),
            // use that as the pk's robInfo.  Otherwise, the new robInfo we
            // created is the "truth" for this pk.
            robInfo = (otherRobInfo == null) ? newRobInfo : otherRobInfo;
        } 

        return robInfo;
    
protected voidafterNewlyActivated(EntityContextImpl context)

        // In the case of ReadOnlyBean store the Context into the list
        ReadOnlyBeanInfo robInfo = addToCache(context.getPrimaryKey(), true);

        // Set the read-only bean info on the context so we can access it
        // without doing a cache lookup.
        ReadOnlyContextImpl readOnlyContext = (ReadOnlyContextImpl) context;
        readOnlyContext.setReadOnlyBeanInfo(robInfo);       
    
protected voidcallEJBLoad(EntityBean ejb, EntityContextImpl entityCtx, boolean activeTx)

        ReadOnlyContextImpl context = (ReadOnlyContextImpl) entityCtx;
               
        ReadOnlyBeanInfo robInfo = context.getReadOnlyBeanInfo();

        // Grab the pk-specific lock before doing the refresh comparisons.
        // In the common-case, the lock will only be held for a very short
        // amount of time.  In the case where a pk-level refresh is needed,
        // we want to ensure that no concurrent refreshes for the same
        // pk can occur.

        int pkLevelSequenceNum = 0;
        long  pkLastRefreshedAt = 0;

        synchronized(robInfo) {
            
            int currentBeanLevelSequenceNum = beanLevelSequenceNum;

            if( robInfo.beanLevelSequenceNum != currentBeanLevelSequenceNum) { 

                if( _logger.isLoggable(Level.FINE) ) {
                    _logger.log(Level.FINE, "REFRESH DUE TO BEAN-LEVEL UPDATE:"
                                + " Bean-level sequence num = " + 
                                beanLevelSequenceNum + 
                                robInfo + " current time is " + new Date());
                }
                
                robInfo.refreshNeeded = true;
            } else if (RELATIVE_TIME_CHECK_MODE && (refreshPeriodInMillis > 0)) { // 0 implies no time based refresh
                if ((currentTimeInMillis - robInfo.lastRefreshedAt) > refreshPeriodInMillis) {
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.log(Level.FINE, "REFRESH DUE TO STALE PK:"
                                + " robInfo.lastRefreshedAt: " + robInfo.lastRefreshedAt
                                + "; current (approx) time is " + currentTimeInMillis);
                    }

                    robInfo.refreshNeeded = true;
                }
            } 
            
            // Refresh could be true EITHER because time-based refresh
            // occurred or programmatic refresh of this PK.
            if (robInfo.refreshNeeded) {
                
                if( _logger.isLoggable(Level.FINE) ) {
                    _logger.log(Level.FINE, " PK-LEVEL REFRESH : "
                                + robInfo + " current time is " + new Date());
                }
                
                try {

                    if( isContainerManagedPers ) {
                        BeanStateSynchronization beanStateSynch =
                            (BeanStateSynchronization) ejb;

                        beanStateSynch.ejb__refresh(entityCtx.getPrimaryKey());

                        if( _logger.isLoggable(Level.FINE) ) {
                            _logger.log(Level.FINE, " PK-LEVEL REFRESH DONE :"
                                + robInfo + " current time is " + new Date());
                        }

                    } else {

                        if( ejb instanceof BeanStateSynchronization ) {
                            // For debugging purposes, call into ejb__refresh
                            // if it's present on a BMP bean class
                            BeanStateSynchronization beanStateSynch =
                                (BeanStateSynchronization) ejb;
                            
                            beanStateSynch.ejb__refresh
                                (entityCtx.getPrimaryKey());
                        }

                    }
                    
                } finally {                    
                    // Always set refreshNeeded to false 
                    robInfo.refreshNeeded = false;
                }

                // Rob info only updated if no errors so far.

                updateAfterRefresh(robInfo);
            }                     
                        
            pkLevelSequenceNum = robInfo.pkLevelSequenceNum;
            pkLastRefreshedAt = robInfo.lastRefreshedAt;
            
        } // releases lock for pk's read-only bean info
        
        if ((entityCtx.isNewlyActivated())
                || (context.getPKLevelSequenceNum() != pkLevelSequenceNum)) {

            // Now do instance-level refresh check to see if 
            // ejbLoad is warranted.        
            callLoad(ejb, context, pkLevelSequenceNum, 
                    pkLastRefreshedAt, currentTimeInMillis);
        }
    
protected voidcallEJBRemove(EntityBean ejb, EntityContextImpl context)


        // This will only be called for BMP read-only beans since AS 7
        // allowed the client to make this call.  Calls to remove 
        // CMP read-only beans result in a runtime exception.

        Object pk = context.getPrimaryKey();                
        robCache.removeAll(pk);
        
    
protected voidcallEJBStore(EntityBean ejb, EntityContextImpl context)

        // this method in the ReadOnlyBean case should be a no-op 
        // and should not throw any exception.
    
private voidcallLoad(EntityBean ejb, EntityContextImpl entityCtx, int pkLevelSequenceNum, long pkLastRefreshedAt, long currentTime)


        ReadOnlyContextImpl context = (ReadOnlyContextImpl) entityCtx;
        
        if( _logger.isLoggable(Level.FINE) ) {
            _logger.log(Level.FINE, 
                        "Calling ejbLoad for read-only bean " +
                        ejbDescriptor.getName() + " primary key " + 
                        entityCtx.getPrimaryKey() + " at " + 
                        new Date(currentTime));
        }

        try {
            context.setInEjbLoad(true);
            ejb.ejbLoad();

            if( pkLevelSequenceNum > 0 ) {
                // Synch up pk-level sequence num after successful load
                context.setPKLevelSequenceNum(pkLevelSequenceNum);
            }

            // Set last refresh time after successful load
            context.setLastRefreshedAt(pkLastRefreshedAt);       
        } finally {
            context.setInEjbLoad(false);
        }        

    
protected EntityContextImplcreateEntityContextInstance(EntityBean ejb, EntityContainer entityContainer)

        return new ReadOnlyContextImpl(ejb, entityContainer);
    
protected voidforceDestroyBean(EJBContextImpl context)

        
        try {
            ReadOnlyContextImpl readOnlyCtx = (ReadOnlyContextImpl) context;
            if( readOnlyCtx.getReadOnlyBeanInfo() != null ) {

                readOnlyCtx.setReadOnlyBeanInfo(null);

                robCache.remove(readOnlyCtx.getPrimaryKey(), true);
            }
            
        } catch (Exception ex) {            

            _logger.log(Level.SEVERE, "ejb.forceDestroyBean", ex);            
            EJBException ejbEx = new EJBException();
            ejbEx.initCause(ex);
            throw ejbEx;        
    
        } finally {
            super.forceDestroyBean(context);
        }
    
public voidhandleRefreshAllRequest()

    	_logger.log(Level.FINE, "Received refreshAll request...");
        updateBeanLevelRefresh();
    
public voidhandleRefreshRequest(java.lang.Object primaryKey)

    
        // Lookup the read-only bean info for this pk. 
        // If there is no entry for this pk, do nothing.
        // If there is a cache hit we *don't* want to increment the
        // ref count.
        ReadOnlyBeanInfo robInfo = (ReadOnlyBeanInfo) 
            robCache.get(primaryKey, false);
        if( robInfo != null ) {
           
            synchronized(robInfo) {
                
                robInfo.refreshNeeded = true;
                robInfo.lastRefreshRequestedAt = this.currentTimeInMillis;
                
                if( _logger.isLoggable(Level.FINE) ) {
                    _logger.log(Level.FINE, 
                        "Updating refresh time for read-only bean " +
                        ejbDescriptor.getName() + " primary key " + primaryKey 
                        + " at " + new Date(robInfo.lastRefreshRequestedAt) +
                        " pkLevelSequenceNum = " + robInfo.pkLevelSequenceNum);
                }
            }
        } else {
            _logger.log(Level.FINE,
                        "Refresh event for unknown read-only bean PK = " +
                        primaryKey + " at " + new Date());
        }
    
protected voidinitializeHome()

        super.initializeHome();

        if (isRemote) {
            ((ReadOnlyEJBHomeImpl) this.ejbHomeImpl).
                setReadOnlyBeanContainer(this);
        } 
        
        if (isLocal) {
            ReadOnlyEJBLocalHomeImpl readOnlyLocalHomeImpl =
                (ReadOnlyEJBLocalHomeImpl) ejbLocalHomeImpl;
            readOnlyLocalHomeImpl.setReadOnlyBeanContainer(this);
        }
    
protected java.lang.ObjectinvokeFindByPrimaryKey(java.lang.reflect.Method method, Invocation inv, java.lang.Object[] args)

	Object returnValue = null;
	ReadOnlyBeanInfo robInfo = addToCache(args[0], false);
	synchronized (robInfo) {
	    returnValue = inv.isLocal
		? robInfo.cachedEjbLocalObject : robInfo.cachedEjbObject;

	    if ( robInfo.refreshNeeded ) {
		_logger.log(Level.FINE, "ReadOnlyBeanContainer calling ejb.ejbFindByPK... for pk=" + args[0]);
		returnValue = super.invokeFindByPrimaryKey(method, inv, args);
		robInfo.refreshNeeded = false;

		//set the seq numbers so that the subsequent business method calls 
		//  (if within expiration time) do not have to call ejb__refresh!!
		updateAfterRefresh(robInfo);

	    }
	}

	return returnValue;
    
java.lang.ObjectinvokeTargetBeanMethod(java.lang.reflect.Method beanClassMethod, Invocation inv, java.lang.Object target, java.lang.Object[] params, com.sun.enterprise.SecurityManager mgr)


        Object returnValue = null;

        if( inv.invocationInfo.startsWithFind ) {

            FinderResultsKey key = new FinderResultsKey(inv.method, params);

            FinderResultsValue value = finderResultsCache.get(key);
            if (value != null) {
                if (RELATIVE_TIME_CHECK_MODE && (refreshPeriodInMillis > 0)) {
                    long timeLeft = currentTimeInMillis - value.lastRefreshedAt;
                    if (timeLeft >=  refreshPeriodInMillis) {
                        returnValue = value.value;
                    }
                } else {
                	//Use even if !RELATIVE_MODE or if refreshTime == 0
                    returnValue = value.value;
                }
            }

            if (returnValue == null) {
            	int hashCode = key.getExtendedHC();
            	if (hashCode < 0) {
            		hashCode = -hashCode;
            	}
            	int index = hashCode & (FINDER_LOCK_SIZE - 1);
            	synchronized (finderLocks[index]) {
            	    value = finderResultsCache.get(key);
	                if (value == null) {
	                    returnValue = super.invokeTargetBeanMethod(
	                        beanClassMethod, inv, target, params, mgr);
	                    finderResultsCache.put(key, new FinderResultsValue(returnValue,
	                        currentTimeInMillis));
	                } else {
                            returnValue = value.value;
	                }
            	    }
                }

        } else {
            returnValue =  super.invokeTargetBeanMethod(beanClassMethod, inv,
                                                        target, params, mgr);
        }

        return returnValue;
    
public java.lang.ObjectpostFind(Invocation inv, java.lang.Object primaryKeys, java.lang.Object[] findParams)


        // Always call parent to convert pks to ejbobjects/ejblocalobjects.
        Object returnValue = super.postFind(inv, primaryKeys, findParams);

        // Only proceed if this is not a findByPK method.  FindByPK
        // processing is special since it's possible to actually
        // skip the db access for the query itself.  The caching requirements
        // to actually skip nonFindByPK queries are extremely complex, but
        // the next best thing to skipping the query is to populate the
        // RobInfo cache with an entry for each pk in the result set.  If
        // a PK is part of the result set for a nonFindByPK query before
        // it is accessed through some other means, no new refresh will be
        // required.  This will have the largest benefits for large result
        // sets since it's possible for a query to return N beans from one
        // db access, which would otherwise require N db accesses if the
        // refresh were done upon business method invocation or findByPK.
        // If a PK has been accessed before appearing in the result set of 
        // a nonFindByPK finder, there is no performance gain.
        if( !inv.method.getName().equals("findByPrimaryKey") ) {
            if ( primaryKeys instanceof Enumeration ) {
                 Enumeration e = (Enumeration) primaryKeys;
                 while ( e.hasMoreElements() ) {
                     Object primaryKey = e.nextElement();
                     if( primaryKey != null ) {
                         updateRobInfoAfterFinder(primaryKey);
                     }
                 }
            } else if ( primaryKeys instanceof Collection ) {
                Collection c = (Collection)primaryKeys;
                Iterator it = c.iterator();
                while ( it.hasNext() ) {
                    Object primaryKey = it.next();
                    if( primaryKey != null ) {
                        updateRobInfoAfterFinder(primaryKey);
                    }
                }
            } else {
                if( primaryKeys != null ) {
                    updateRobInfoAfterFinder(primaryKeys);
                }
            }
        }

        return returnValue;
    
public voidpreInvoke(Invocation inv)


        // Overriding preInvoke is the best way to interpose on the 
        // create early enough to throw an exception or eat the
        // request before too much setup work is done by the container.
        // It's better to keep this logic in the Read-Only Bean container
        // than to put it in the InvocationHandlers.  Note that 
        // interposition for the remove operation is handled below
        // by overriding the removeBean method.
        if( (inv.invocationInfo != null) &&
            inv.invocationInfo.startsWithCreate ) {

            String msg = "Error for ejb " + ejbDescriptor.getName() +
                ". create is not allowed for read-only entity beans";

            if( isContainerManagedPers ) {
                // EJB team decided that throwing a runtime exception was more
                // appropriate in this case since creation is not a
                // supported operation for read-only beans.  If the application
                // is coded this way, it's best to throw a system exception
                // to signal that the application is broken.  NOTE that this 
                // only applies to the CMP 1.x and 2.x read-only bean 
                // functionality added starting with AS 8.1.  

                throw new EJBException(msg);
                                       
            } else {
                // Preserve AS 7 BMP ROB create behavior 
                CreateException ce = new CreateException(msg);
                throw new PreInvokeException(ce);
            }

        } else {
            super.preInvoke(inv);                
        }
    
voidpreInvokeNoTx(Invocation inv)

        EntityContextImpl context = (EntityContextImpl)inv.context;
        
        if ( context.getState() == DESTROYED )
            return;
        
        if ( !inv.invocationInfo.isCreateHomeFinder ) {
            // follow EJB2.0 section 12.1.6.1
            EntityBean e = (EntityBean)context.getEJB();
            try {
                callEJBLoad(e, context, false);
            } catch ( NoSuchEntityException ex ) {
                _logger.log(Level.FINE, "Exception in preInvokeNoTx()", ex);
                // Error during ejbLoad, so discard bean: EJB2.0 18.3.3
                forceDestroyBean(context);
                
                throw new NoSuchObjectLocalException(
                    "NoSuchEntityException thrown by ejbLoad, " +
                    "EJB instance discarded");
            } catch ( Exception ex ) {
                // Error during ejbLoad, so discard bean: EJB2.0 18.3.3
                forceDestroyBean(context);
                
                throw new EJBException(ex);
            }
            context.setNewlyActivated(false);
        }
    
voidrefreshAll()
invoked when application calls refreshAll()

        try {
            handleRefreshAllRequest();
        } finally {
            distributedReadOnlyBeanService.notifyRefreshAll(getContainerId());
        }
    
protected voidremoveBean(EJBLocalRemoteObject ejbo, java.lang.reflect.Method removeMethod, boolean local)


        String msg = "Error for ejb " + ejbDescriptor.getName() +
            ". remove is not allowed for read-only entity beans";

        if( isContainerManagedPers ) {
            
            // EJB team decided that throwing a runtime exception was more
            // appropriate in this case since removal is not a
            // supported operation for read-only beans.  If the application
            // is coded this way, it's best to throw a system exception
            // to signal that the application is broken.  NOTE that this 
            // only applies to the CMP 1.x and 2.x read-only bean 
            // functionality added starting with AS 8.1.  
            
            // There's no post-invoke logic to convert local exceptions
            // to remote, so take care of that here.
            if (local) {                
                throw new EJBException(msg);
            } else {
                throw new RemoteException(msg);
            }

        } else {
            // Preserve AS 7 BMP ROB removal behavior.
            // Calls to ejbRemove on BMP read-only beans in AS 7
            // were silently "eaten" by the ejb container.   The
            // client didn't receive any exception, but ejbRemove
            // was not called on the container.
        }        
    
public voidsetRefreshFlag(java.lang.Object primaryKey)

        
        try {
            handleRefreshRequest(primaryKey);
        } finally {
            distributedReadOnlyBeanService.notifyRefresh(
                    getContainerId(), primaryKey);
        }
    
public voidundeploy()

        this.distributedReadOnlyBeanService.removeReadOnlyBeanRefreshEventHandler(
                getContainerId());
        super.undeploy();
        
        if( refreshTask != null ) {
            refreshTask.cancel();
        }

        robCache.clear();
    
private voidupdateAfterRefresh(ReadOnlyBeanInfo robInfo)

	robInfo.beanLevelSequenceNum = beanLevelSequenceNum;
	robInfo.pkLevelSequenceNum++;
	robInfo.lastRefreshedAt = this.currentTimeInMillis;
    
private voidupdateBeanLevelRefresh()

               
        beanLevelSequenceNum++;
        beanLevelLastRefreshRequestedAt = this.currentTimeInMillis;

        if( _logger.isLoggable(Level.FINE) ) {
            _logger.log(Level.FINE, "updating bean-level refresh for " + 
                        " read-only bean " + ejbDescriptor.getName() + 
                        " at " + new Date(beanLevelLastRefreshRequestedAt) + 
                        " beanLevelSequenceNum = " + beanLevelSequenceNum);

            
        }

        // Clear out bean-level finder results cache.
        if( _logger.isLoggable(Level.FINE) ) {
            _logger.log(Level.FINE, "Clearing " + 
            		finderResultsCache.size() + " items from " + 
                        "finder results cache");
        }

        finderResultsCache =
            new ConcurrentHashMap<FinderResultsKey, FinderResultsValue>();

        
    
private voidupdateRobInfoAfterFinder(java.lang.Object primaryKey)

        ReadOnlyBeanInfo robInfo = addToCache(primaryKey, false);
        /*
        synchronized (robInfo) {
            if( robInfo.refreshNeeded ) {
                robInfo.refreshNeeded = false;
                updateAfterRefresh(robInfo);
            }
        }
        */