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







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