Yes, but I am not going to tell you the name of that class, you have to find it 
for yourself.  :-P

There might also be a model with preferences in it, maybe that was user 
preferences?


Chuck

On 2011-11-24, at 3:35 PM, Pascal Robert wrote:

> 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 protected])
>>> Help/Unsubscribe/Update your Subscription:
>>> http://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/products/practical_webobjects
>> 
>> 
>> 
>> 
>> 
>> 
>> 
> 

-- 
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







Attachment: smime.p7s
Description: S/MIME cryptographic signature

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

This email sent to [email protected]

Reply via email to