Reconciling DataContexts

From: Kevin Menard (kmenar..ervprise.com)
Date: Mon Oct 15 2007 - 18:25:40 EDT

  • Next message: Andrus Adamchik: "Re: Reconciling DataContexts"

    So, if there is one thing that drives me nuts about Cayenne, it's managing
    ObjectContexts. In particular, you cannot relate two Persistent objects
    without first putting them into an ObjectContext. If one is committed and
    the other is not, you can have them in different contexts, but for newly
    created objects, this is a major pain in the neck.

    Since I've been complaining about it for probably close to three years now,
    I'd like to finally do something about it.

    Here are my rough notes from the airport:

    OK Cases:

    - Objects in same context
    - Objects in different contexts, but objects are committed already

    Don't work, but should:

    - Objects in null contexts
    - Objects in different contexts, but same data maps and domains

    Very hard to say, probably okay if don't work:

    - Objects in different contexts, contexts have different data maps
    - Objects in different contexts, contexts have different data domains

    As I started actually digging into the code, I ran into a lot of NPE issues
    trying to associate two Persistent objects with no context with one another.
    In an attempt to prevent adding special null-logic handling, I thought about
    applying the Null Object pattern to the problem. The basic idea is rather
    than use null as the default objectContext for CDO, use an instance of
    DelayedContext. The problem here is having objects in different contexts.
    So, it appears by fixing one, you can essentially fix the other.

    To address the latter, I was looking to have a Set of ObjectContexts stored
    in either BaseContext or DataContext. When willConnect() is called, you'd
    have something like the following:

    else if (this.getObjectContext().getEntityResolver() ==
    object.getObjectContext().getEntityResolver()) {
                ((DataContext)
    this.getObjectContext()).addContextToMergeWith(object.getObjectContext());
                ((DataContext)
    object.getObjectContext()).addContextToMergeWith(this.getObjectContext());
            }
            else {
                throw new CayenneRuntimeException(
                        "Cannot set object as destination of relationship "
                                + relationshipName
                                + " because it is in a different DataMap or
    DataDomain.");
            }

    (Casts are just an artifact of me screwing around).

    What I'm thinking would happen is that when commitChanges() is called, the
    set of contexts to be merged with will be iterated and any changes applied
    to the current object store / object store graph diff. The relationship is
    bidirectional so that the user can initiate the commit from any object
    registered with any context.

    Here is about where I lose it. I'm not as well-versed in the internal
    going-ons of Cayenne as I would like to be. It appears Cayenne goes to
    great efforts to essentially cache the graph manipulations so as to avoid a
    full traversal. I really don't know, though.

    Caching ordering of operations could make this tricky, but in principal
    should be wholly doable.

    If anyone has any thoughts on this or can fill in any missing pieces, I'd
    appreciate it. This is really something I'd like to see fixed sooner rather
    than later. I think it may be a requisite for JPA compliance as well.

    -- 
    Kevin
    



    This archive was generated by hypermail 2.0.0 : Mon Oct 15 2007 - 18:26:15 EDT