Re: ERXEnterpriseObjectCache<T> pre-loading cache causes exception
Re: ERXEnterpriseObjectCache<T> pre-loading cache causes exception
- Subject: Re: ERXEnterpriseObjectCache<T> pre-loading cache causes exception
- From: Chuck Hill <email@hidden>
- Date: Tue, 05 Feb 2013 11:19:43 -0800
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@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
--
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@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden