I am not sure, but here is how I have been using it:

    /**
     * Creates a standard EO cache object for the passed entity name and 
keypath for all  objects of
     * the entity that match restrictingQualifier.  If restrictingQualifier is 
null, all objects of this entity are
     * cached.
     *
     * @param entityName name of the EOEntity for the instances that will be in 
the cache
     * @param keyPath key path of unique value in EOs
     * @param restrictingQualifier EOQualifier restricting the set of objects 
in the cache
     * @param shouldFetchInitialValues true if the cache should be fully 
populated on first access
     * @return a Cadre standard EO cache object for the passed entity name and 
keypath
     */
    public static ERXEnterpriseObjectCache createCache(String entityName, 
String keyPath, EOQualifier restrictingQualifier, boolean 
shouldFetchInitialValues)    {
        /** require [valid_entityName] entityName != null;
                    [valid_keyPath] keyPath != null;
         **/

        EOEditingContext ec = new CadreEditingContext();
        ec.lock();
        try
        {
            EOObjectStoreCoordinator osc = (EOObjectStoreCoordinator) 
ec.rootObjectStore();
            osc.lock();

            try
            {
                long timeout = 
WOApplication.appProperties().longPropertyForKey(CadreApplication.ERXEnterpriseObjectCacheTimeoutInMinutes)
 * 60 * 1000;
                boolean shouldRetainObjects = true;
                boolean shouldReturnUnsavedObjects = true;  // Needed for 
imports where new objects reference other new objects
                ERXEnterpriseObjectCache cache = new 
ERXEnterpriseObjectCache(entityName, keyPath, restrictingQualifier, timeout,
                                                                              
shouldRetainObjects, shouldFetchInitialValues, shouldReturnUnsavedObjects);

                /**
                 * OK, things get nasty here.  You HAVE been warned!
                 *
                 * The cache has an interaction with the EOEditingContext 
fetchTimestamp()/defaultFetchTimestampLag().  After
                 * the objects have been fetched into the cache, if the 
defaultFetchTimestampLag() passes before they are
                 * re-fetched, when they are faulted into a new editing context 
(localInstanceOfObject), the snapshot will be discarded
                 * and the objects re-fetched, one by one.  This rather 
eliminates the value of the cache.
                 *
                 * There are a few options to fix this:
                 * - use a large defaultFetchTimestampLag() and ensure that all 
the places that need fresh data use
                 *   a fetch specification that refreshes re-fetched objects.  
This also means that you must pre-fetch all
                 *   the objects that need fresh data.  This makes the 
defaultFetchTimestampLag() rather useless to control
                 *   data freshness.
                 *
                 * - use a large defaultFetchTimestampLag() and implement 
ERChangeNotification to keep all the EOF stacks
                 *   in sync.  This ensures current data without needing to use 
defaultFetchTimestampLag().
                 *
                 * - use a custom EODatabaseContext.delegate and implement the 
delegate method
                 *   databaseContextShouldFetchObjectFault(EODatabaseContext, 
Object) to use the existing snapshot regardless of age.
                 *   To implement this, the delegate will need to know that the 
entity is being cached.  This can be done by setting
                 *   a flag in EOEntity.userInfo in this method.
                 *
                 * - make the objects as "Cache in Memory" in the EOModel.  The 
large drawback of this is that the objects will never
                 *   be refreshed.  Refreshing fetch specifications do not 
affect entities cached in memory.
                 *
                 * - mark the snapshots of the cached objects as expiring at 
some time in the distant future.  As they expire from the
                 *   cache they will be re-fetched and refreshed from the 
database.  This option was chosen as it more closely matches
                 *   what should happen.  It does require access to a protected 
method in EODatabase.  It is possible that future
                 *   versions of WebObjects will break this implementation, but 
there should be some way of achieving the result.
                 */
                EOEntity entity = EOUtilities.entityNamed(ec, entityName);
                EODatabaseContext dbContext = 
EOUtilities.databaseContextForModelNamed(ec, entity.model().name());
                EODatabase database = dbContext.database();
                NSArray objectsInCache = cache.allObjects(ec);
                for (int i = 0; i < objectsInCache.count(); i++)
                {
                    EOEnterpriseObject eo = (EOEnterpriseObject) 
objectsInCache.objectAtIndex(i);
                    // Sets the expiration timestamp for the snapshot to 
NSTimestamp.DistantFuture.getTime()
                    _setTimestampForCachedGlobalID().invoke(database, 
ec.globalIDForObject(eo));
                }

                return cache;
            }
            catch (Exception e)
            {
                throw new ExceptionConverter(e);
            }
            finally
            {
                osc.unlock();
            }
        }
        finally
        {
            ec.unlock();
            ec.dispose();
        }

        /** ensure [valid_result] Result != null;  **/
    }


On 2013-02-05, at 10:57 AM, JR Ruggentaler wrote:

> I added a ERXEnterpriseObjectCache to my entity and when some of my old code 
> tries to query the database instead of using the cache EOF throws the 
> following exception. If I defer loading the cache 
> (shouldFetchInitialValues=false) everything works. Is this a Wonder, EOF,… 
> bug?
> 
> [2013-02-04 15:41:16,593] <performWork> ERROR Exception: 
> java.lang.NullPointerException - null
> NullPointerException
> at 
> com.webobjects.eoaccess.EODatabaseContext._objectFaultWithSnapshotRelationshipEditingContext(EODatabaseContext.java:2356)
> ... skipped 2 stack elements
> at 
> com.webobjects.eocontrol.EOObjectStoreCoordinator.initializeObject(EOObjectStoreCoordinator.java:597)
> at 
> com.webobjects.eocontrol.EOEditingContext.initializeObject(EOEditingContext.java:3768)
> at er.extensions.eof.ERXEC.initializeObject(ERXEC.java:1141)
> ... skipped 3 stack elements
> at 
> com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsWithFetchSpecification(EOObjectStoreCoordinator.java:488)
> at 
> com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecification(EOEditingContext.java:4069)
> at er.extensions.eof.ERXEC.objectsWithFetchSpecification(ERXEC.java:1206)
> at 
> com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecification(EOEditingContext.java:4444)
> at com.mpv.mapload.Handler.loadingContextWillLoadObject(Handler.java:312)
> at com.mpv.mapload.LoadingContext.willLoadObject(LoadingContext.java:930)
> at com.mpv.mapload.LoadingContext.load(LoadingContext.java:737)
> at com.mpv.agent.loaderagent.LoaderAgent.performWork(LoaderAgent.java:154)
> at com.mpv.agent.MPVAgent._performWork(MPVAgent.java:310)
> at com.mpv.agent.MPVAgent$MPVAgentTask._run(MPVAgent.java:198)
> at er.extensions.concurrency.ERXTimerTask.run(ERXTimerTask.java:25)
> at java.util.TimerThread.mainLoop(Timer.java:512)
> at java.util.TimerThread.run(Timer.java:462)
> 
> Here is the code that adds the cache to the entity.
> 
> public static class Util<T extends UserGroup> extends _UserGroup.Util<T> {
> /** 
> * UserGroup are static and stored in a lookup table. We use a cache
> * to provide quick access to them. The cache is keyed by the userGroupID
> * property.
> */
> ERXEnterpriseObjectCache<T> _userGroupIDCache = new 
> ERXEnterpriseObjectCache<T>(
> UserGroup.ENTITY_NAME, UserGroup.USER_GROUP_ID_KEY);
> 
> /**
> * Returns the UserGroup instance whose userGroupID property is equal to 
> <code>value</code>.
> * The UserGroup is localized into the provided editing context.
> * 
> * @param ec
> * 
> editing context in which the returned UserGroup instance is to live
> * @param value
> * 
> UserGroup that is sought
> * @return the UserGroup instance whose userGroupID property matches 
> <code>userGroupID</code>
> */
> public T findUserGroupForUserGroupID(EOEditingContext ec, Integer value) {
> return _userGroupIDCache.objectForKey(ec, value);
> }
> 
> }
> 
> JR
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list      ([email protected])
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/webobjects-dev/chill%40global-village.net
> 
> This email sent to [email protected]

-- 
Chuck Hill             Senior Consultant / VP Development

Practical WebObjects - for developers who want to increase their overall 
knowledge of WebObjects or who are trying to solve specific problems.    
http://www.global-village.net/gvc/practical_webobjects

Global Village Consulting ranks 13th in 2012 in BIV's Top 100 Fastest Growing 
Companies in B.C! 
Global Village Consulting ranks 76th in 24th annual PROFIT 200 ranking of 
Canada’s Fastest-Growing Companies by PROFIT Magazine!









 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to