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