Re: Lifecycle Design

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Sun Apr 12 2009 - 08:28:42 EDT

  • Next message: Paul Logasa Bogen II: "Slow Return on Paginated SelectQuery"

    The query refreshes the root entity, but not the relationships. So
    MisysDict will be refreshed, while related Xrefs will not. To ensure a
    refresh of specific relationships, you can use prefetching:

    http://cayenne.apache.org/doc/prefetching.html

    In the documentation it is presented as a performance optimization
    technique, but it is also happens to be an object graph cache control
    technique.

    Andrus

    On Apr 12, 2009, at 10:17 AM, Lawrence Gerstley wrote:

    > 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 - 08:29:18 EDT