Re: How to handle "system" preferences?
Re: How to handle "system" preferences?
- Subject: Re: How to handle "system" preferences?
- From: Pascal Robert <email@hidden>
- Date: Thu, 24 Nov 2011 18:35:30 -0500
Man, does Wonder also have a method to find the meaning of life since it have something for everything else? :-)
> No question, put them in the database. Use ERXEnterpriseObjectCache to avoid needless repeated database trips.
>
> Using the standard WO classes:
>
> /**
> * 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 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 EOEditingContext();
> ec.lock();
> try
> {
> EOObjectStoreCoordinator osc = (EOObjectStoreCoordinator) ec.rootObjectStore();
> osc.lock();
>
> try
> {
> long timeout = // get this from a property
> 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; **/
> }
>
>
> private static Method _setTimestampForCachedGlobalID = null;
> /**
> * Hack to access protected method in EODatabase.
> * @return Method for protected void _setTimestampForCachedGlobalID(EOGlobalID gid)
> */
> private static Method _setTimestampForCachedGlobalID()
> {
> synchronized (GenericRecord.class)
> {
> if (_setTimestampForCachedGlobalID == null)
> {
> try
> {
> _setTimestampForCachedGlobalID = EODatabase.class.getDeclaredMethod("_setTimestampForCachedGlobalID",
> new Class[] {EOGlobalID.class});
> _setTimestampForCachedGlobalID.setAccessible(true);
> }
> catch (Exception e)
> {
> throw new ExceptionConverter(e);
> }
> }
> }
>
> return _setTimestampForCachedGlobalID;
> }
>
> Chuck
>
>
>
> On 2011-11-24, at 12:45 PM, Pascal Robert wrote:
>
>> I want to add some "system preferences" to SimpleBlog, for things like number of comments per page, if comments are moderated or not, etc. I'm wondering what's the best way to handle that. I was thinking of using a plist and read it at "boot time" so that the preferences are in memory, and writing the file when a pref changes. The problem with this solution is that the file will have to be outside the .woa since the preferences have to survive a upgrade. And if a server have more than one SimpleBlog instance (e.g., "multi tenants"), it would have to be different files.
>>
>> The other solution would be to store the preferences in the database. In the case of multi tenants, each instance would have to have it own databases. The potential problem would be a performance one, we would need to call EOF every time a preference is needed (for display groups, etc.). Sure, I'm not talking about high performance system here, but it would be great to show best practices.
>>
>> So, how would you manage this?
>> _______________________________________________
>> 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/products/practical_webobjects
>
>
>
>
>
>
>
_______________________________________________
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