Re: Lifecycle Design

From: Lawrence Gerstley (lawger..mail.com)
Date: Sun Apr 12 2009 - 03:17:40 EDT

  • Next message: Andrus Adamchik: "Re: Lifecycle Design"

    I'm feeling thick, but I'm really stuck with what is becoming an
    increasingly simple attempt to convince myself that I can get the simplest
    of caching examples working.
    My attempt now is to get two machines on two separate JVMs to have a
    force-reload. To do this, I'm re-running the query that populates on Content
    Provider. The Cayenne Controller has these settings:

    /******************************************/
    DataSource dataSource = new
    PoolManager("com.mysql.jdbc.Driver", server, 1, 5, userId, password);
    Configuration config = Configuration.getSharedConfiguration();
    DataDomain domain = config.getDomain();
    domain.setSharedCacheEnabled(false);
    DataNode node = domain.getNode("AmerigoDomainNode");
    node.setDataSource(dataSource);
    DataMap dataMap = domain.getMap("AmerigoDomainMap");
    /******************************************/

    All queries follow this pattern, roughly:
    /******************************************/
    Expression express =
    ExpressionFactory.likeIgnoreCaseExp( MisysDict.TEST_NAME_PROPERTY, nameMatch);
    SelectQuery sq = new SelectQuery(MisysDict.class, express);
    sq.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE_REFRESH);
    sq.setCacheGroups("grp1", "grp2", "grp3");
    this.clearMisysDictEntries();
    misysDictEntries.addAll(dContext.performQuery(sq));
    /******************************************/

    Now, I can update a row from either application, and see the change commit
    in the data store. However, when I rerun the query above, the objects
    attached to the returned objects remain in their old state. For example, the
    entity MisysDict can return a list of Xrefs (MisysDict.getMisysRecToXREF():
    <List>XREF). When I examine one of these XREFs, I cannot see any change made
    to it from the other application. However, I *can* see changes made to the
    MisysDict record itself.

    I know I'm going to feel foolish for asking, but can you tell me what simple
    thing(s) I'm off on here?

    Thanks, as always,

    Lawrence

    On Sat, Apr 11, 2009 at 2:16 AM, Andrus Adamchik <andru..bjectstyle.org>wrote:

    > The caching docs are embarrassingly out of date. It's been requested a
    > number of times to fix them. Maybe finally I'll do it...
    >
    > As for the cache strategy, you'd usually pick one of LOCAL_CACHE or
    > SHARED_CACHE (or NO_CACHE for no caching, but that's the default already).
    > Javadocs for QueryCacheStrategy explain each one of the strategies. Let me
    > point to the differences between "LOCAL" and "SHARED" here. "Local" means
    > attached to your ObjectContext, "Shared" - shared by all ObjectContext
    > produced by a given Cayenne stack (usually this means shared by all contexts
    > in a given JVM). Accessing shared cache is somewhat slower than local, so if
    > you have a singleton DataContext (so DataContext is already shared by
    > itself), select local cache.
    >
    > Andrus
    >
    >
    > On Apr 11, 2009, at 3:31 AM, Joe Baldwin wrote:
    >
    >> Lawrence,
    >>
    >> I am still struggling to understand Andrus' setCacheStrategy() approach in
    >> his previous email (he claims it is simple and I am all for that :) ). I am
    >> attempting some black box testing to figure out exactly where my data object
    >> is getting cached (and not updated properly). In my case I am initializing
    >> a class variable with DB data via Cayenne into a singleton when the class is
    >> initially loaded. I am not sure whether it is my design or execution of my
    >> design that is at fault.
    >>
    >> strategies, but a simple Refresh All would get me across the line for the
    >>> moment. Is there any info on this?
    >>>
    >>
    >> WRT your issue, I found this class in the 3.0 API:
    >>
    >>
    >> http://cayenne.apache.org/doc/api/org/apache/cayenne/query/RefreshQuery.html
    >>
    >> The docs assert:
    >> "A query that allows to explicitly clear both object and list
    >> caches either via refetch (eager refresh) or invalidate (lazy refresh)."
    >> This may be the ticket for you.
    >>
    >> Unfortunately, my singleton appears to be attached to the Tomcat app and
    >> not the session so I can't find an elegant way for it to refresh.
    >>
    >> Please let me know if you get this working.
    >> Joe
    >>
    >>
    >> On Apr 10, 2009, at 5:28 PM, Lawrence Gerstley wrote:
    >>
    >> So, in my knowledge-gaining journey with this topic, I ran across this
    >>> page: http://cayenne.apache.org/doc/refreshquery.html, which looks like
    >>> a list of items yet to be done or at least yet to be documented (and boy,
    >>> when I have things really understood, I want to volunteer some documentation
    >>> time to the project). There is a topic headline of "Refresh All", and an
    >>> indication in the links posted as to the "RefreshQuery", but the pertinent
    >>> part of the links are broken, and I can't track down the resolution of the
    >>> items. However, this is exactly what I need to do for a first step. My
    >>> application's environment will be (mandated by the customer), a thick client
    >>> running on a Citrix instance, and some of the challenges posed by JGroups
    >>> will take me awhile to understand. In the meantime, I want to provide a
    >>> simple "Refresh All" button that will provide for a dumb refresh without
    >>> leaving the application. I'm struggling with different caching strategies,
    >>> but a simple Refresh All would get me across the line for the moment. Is
    >>> there any info on this?
    >>>
    >>> Cheers,
    >>>
    >>> Lawrence
    >>>
    >>>
    >>>
    >>> On Apr 10, 2009, at 6:09 AM, Andrus Adamchik wrote:
    >>>
    >>> As mentioned in the quoted docs, there are ways to receive immediate
    >>>> notifications on the individual objects updates (if they are updated via
    >>>> Cayenne). This approach, while the most powerful on the surface, is least
    >>>> practical, especially across the VM. It suffers from a number of
    >>>> shortcomings (as also have been mentioned here):
    >>>>
    >>>> * It has a potential to generate too much network traffic
    >>>> * As all update events are broadcast, it has a potential to DDOS the
    >>>> apps who may not care about 90% of the updates (as all incoming events incur
    >>>> processing overhead), so some manual event channel filtering may be needed.
    >>>> * It does not correctly refresh cached query lists. E.g. if you have a
    >>>> cached fetch for "documents that are in draft mode", and then received an
    >>>> event saying that one of the drafts has changed to "not a draft", the object
    >>>> will be refreshed, the list will become stale, as its composition no longer
    >>>> matches the search criteria.
    >>>> * Finally, the data can change in DB by non Cayenne clients...
    >>>>
    >>>> So I am very much in favor of the Query Cache approach that is not
    >>>> documented that well, but is really simple to use:
    >>>>
    >>>> query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE); // or
    >>>> SHARED_CACHE...
    >>>> query.setCacheGroups("g1", "g2", ...);
    >>>>
    >>>> Once you start doing that for your queries, you can perform further
    >>>> cache configuration in a semi-declarative manner. E.g. I am successfully
    >>>> using OSQueryCacheFactory:
    >>>>
    >>>> dataDomain.setQueryCacheFactory(new OSQueryCacheFactory());
    >>>>
    >>>> This ties Cayenne query cache to OSCache which allows time based
    >>>> expiration of entries, cron like expressions, and forced invalidation,
    >>>> including remote invalidation via JGroups. All of that incurs nearly zero
    >>>> overhead, as the entries are not actively purged from cache, but rather
    >>>> marked as invalid by "group" (see 'setCacheGroups' above). Cross-VM events
    >>>> are also sent as the names of the groups to invalidate, not full object
    >>>> snapshots. This is very powerful and easy to use stuff.
    >>>>
    >>>> Andrus
    >>>>
    >>>>
    >>>>
    >>>> On Apr 10, 2009, at 10:17 AM, Andrey Razumovsky wrote:
    >>>>
    >>>>> The proposed way is to use JGroups or JMS for synchronization:
    >>>>> http://cayenne.apache.org/doc/configuring-caching-behavior.html
    >>>>>
    >>>>> 2009/4/10 Lawrence Gerstley <lawger..cn.com>
    >>>>>
    >>>>> So, I have the same question here--multiple thick clients (desktop RCP
    >>>>>> applications), each with a DataContext tied to the same backend, and
    >>>>>> potential database access (direct or otherwise) from other toolsets
    >>>>>> out of
    >>>>>> my control. Is there a recommended strategy for refreshing each
    >>>>>> applications
    >>>>>> singleton DataContext to stay in synch, or manually a supplying
    >>>>>> refresh
    >>>>>> command to the DataContext to periodically update (and, if so, with
    >>>>>> what/how)?
    >>>>>>
    >>>>>> Kind regards,
    >>>>>>
    >>>>>> Lawrence
    >>>>>> ===================================
    >>>>>> Lawrence Gerstley, Ph.D.
    >>>>>> PSMI Consulting
    >>>>>> lawger..mail.com
    >>>>>> Cel: (415) 694-0844
    >>>>>>
    >>>>>>
    >>>>>> On Apr 8, 2009, at 4:22 PM, Malcolm Edgar wrote:
    >>>>>>
    >>>>>> Hi Joe,
    >>>>>>
    >>>>>>>
    >>>>>>> Your singleton cache is going to need to be update periodically if
    >>>>>>> there are changes to the under lying database from other sources.
    >>>>>>>
    >>>>>>> regards Malcolm Edgar
    >>>>>>>
    >>>>>>> On Thu, Apr 9, 2009 at 7:45 AM, Joe Baldwin <jfbaldwi..arthlink.net
    >>>>>>> >
    >>>>>>> wrote:
    >>>>>>>
    >>>>>>> I *think* this is a life-cycle question, but there may be more to
    >>>>>>>> it.
    >>>>>>>>
    >>>>>>>> Proposed Design:
    >>>>>>>>
    >>>>>>>> 1. Standard Web page JSP using Tomcat server.
    >>>>>>>> 2. One of the JSP's accesses a singleton.
    >>>>>>>> 3. The singleton accesses and stores a database field via Cayenne
    >>>>>>>> (presumably when the class is initially loaded) and should never
    >>>>>>>> need to
    >>>>>>>> access the field again.
    >>>>>>>> 4. I would prefer it if the database field change would be
    >>>>>>>> propagated to
    >>>>>>>> the
    >>>>>>>> singleton upon the next new client-Session.
    >>>>>>>>
    >>>>>>>> Problem
    >>>>>>>> 1. Here is the odd bit: the database field can be modified via
    >>>>>>>> direct
    >>>>>>>> access
    >>>>>>>> to the database (SQL, etc).
    >>>>>>>> 2. Cayenne appears not to see this change even when a new
    >>>>>>>> client-Session
    >>>>>>>> is
    >>>>>>>> initialized.
    >>>>>>>> 3. I can *force* the singleton to recognize the change by restarting
    >>>>>>>> Tomcat
    >>>>>>>> (but that is totally lame :) )
    >>>>>>>> 4. Unless I have made a mistake (which is possible), the singleton
    >>>>>>>> should
    >>>>>>>> be
    >>>>>>>> only associated with JSP session scope. But if I am wrong, this
    >>>>>>>> could be
    >>>>>>>> the problem.
    >>>>>>>>
    >>>>>>>> Obviously, I have a misunderstanding about either Cayenne or Tomcat
    >>>>>>>> caching
    >>>>>>>> or perhaps its a combo of the two. It appears from my tests that
    >>>>>>>> the
    >>>>>>>> singleton class may be constructed the first time after Tomcat is
    >>>>>>>> restarted
    >>>>>>>> and then remains persistent even across different sessions.
    >>>>>>>>
    >>>>>>>> Are there any suggestions as to a simple design in which my
    >>>>>>>> singleton
    >>>>>>>> forces
    >>>>>>>> re-initialized (i.e. refresh the Cayenne object from the DBMS data)
    >>>>>>>> upon
    >>>>>>>> each new session?
    >>>>>>>>
    >>>>>>>> Thanks,
    >>>>>>>> Joe
    >>>>>>>>
    >>>>>>>>
    >>>>>>>>
    >>>>>>>>
    >>>>>>>>
    >>>>>>>>
    >>>>>>
    >>>>
    >>>
    >>
    >

    -- 
    ============================
    Lawrence Gerstley, Ph.D.
    PSMI Consulting
    

    Cel: 415.694-0844



    This archive was generated by hypermail 2.0.0 : Sun Apr 12 2009 - 03:18:16 EDT