Re: Cleaning up ROP

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Wed Nov 07 2007 - 03:53:24 EST

  • Next message: Andrus Adamchik (JIRA): "[JIRA] Closed: (CAY-900) Create CayenneModeler Swing UI for managing callbacks and lifecycle listeners"

    Hi Kevin,

    CayenneDataObject approach is fundamentally different from other
    persistent object implementations that are all variations of POJO. So
    I think a different approach may work better - using current client
    objects on the server (instead of using current server objects on the
    client).

    Andrus

    On Nov 7, 2007, at 8:07 AM, Kevin Menard wrote:

    > I just spent the better part of this evening trying to get
    > something going.
    > Unfortunately, I'm stuck at the moment and it's getting pretty late
    > (or
    > early) here. So, I'm just posting what I tried and what my results
    > were.
    > If anyone else wants to suggest something, great, if not, I'll prod
    > at it
    > more when I can get some time. I'll likely have to defer it and
    > come up
    > with some workaround, because I need this portion of the app
    > relying on the
    > fix done.
    >
    > Anyway . . .
    >
    > I took a really naïve approach to start because I just wanted to get
    > something going.
    >
    > * Made CayenneDataObject extends PersistentObject
    > ** Removed any code duplication
    >
    > * Updated my data map to use the same class name for the server and
    > client
    > classes for all obj entities.
    >
    > * Modified the velocity template to combine both server and client
    > class
    > info:
    >
    > * Static property name fields appear as before
    > * All client fields appear
    > * All methods perform an instanceof check on the context to choose the
    > appropriate code to call like so:
    >
    > public BillingInfo getDefaultBillingInfo() {
    > if (objectContext instanceof CayenneContext) {
    > if(objectContext != null) {
    > objectContext.prepareForAccess(this,
    > "defaultBillingInfo",
    > true);
    > }
    >
    > return (BillingInfo) defaultBillingInfo.getValue();
    > }
    > else {
    > return (BillingInfo)readProperty("defaultBillingInfo");
    > }
    > }
    >
    >
    > Problems:
    >
    > * Retrieving data from client fails during deep merge on toMany
    > relationships. The read property is null causing most of the rest
    > of the
    > method to fail.
    >
    > * Adding NPE checks for the above gets me to a workable state, but the
    > generated class does not work as expected. In particular, all the
    > values
    > are in the map (like they should for a server) and all the fields
    > are blank
    > (which should not be the case for the client).
    >
    > My initial thoughts were that the failures were due to the above code
    > snippet failing to do the right thing if the context is null (is
    > there a
    > better way to tell if we're executing on the client?). But, the first
    > failure occurs well before any of those accessors are called. So,
    > I am a
    > bit at a loss.
    >
    > Anyway, if Ari or someone else wants to help out with this, I'd
    > certainly
    > welcome it.
    >
    > --
    > Kevin
    >
    >
    > On 10/27/07 1:01 PM, "Andrus Adamchik" <andru..bjectstyle.org> wrote:
    >
    >> Would be nice if we could make it work... IIRC back in the day when
    >> ROP was first implemented there were a number of limitations
    >> preventing DataContext and CayenneDataObject from being used on the
    >> client, mostly related to the fact that both had direct dependencies
    >> on the structure of the underlying stack (e.g. referencing DataDomain
    >> and DataNode). Now we are *mostly* free of those. So I'd be curious
    >> to try and use DataContext on the client.
    >>
    >> A few issues to pay attention to:
    >>
    >> * Serialization. Current client objects are more lightweight as they
    >> store their properties in Java fields, vs. a Map used by
    >> CayenneDataObject. So probably a custom serializer is needed.
    >>
    >> * While supporting a single class hierarchy is a good idea,
    >> preserving the ability for separate hierarchies is very important -
    >> users may not want to expose some server methods to the client, and
    >> generally may want to have two sets of objects with different
    >> behavior.
    >>
    >> In any event it is a good idea to reevaluate our options now.
    >>
    >> Andrus
    >>
    >>
    >>
    >> On Oct 27, 2007, at 7:20 PM, Kevin Menard wrote:
    >>
    >>> Hi all,
    >>>
    >>> I've just gone back to work on a ROP application I have and am
    >>> again running
    >>> into the issue of having to duplicate code between the server model
    >>> subclasses and the client model subclasses. I've got a way of
    >>> working
    >>> around that, but I'm thinking this is probably best handled by
    >>> Cayenne. In
    >>> particular, I really don't think that there should be two class
    >>> hierarchies
    >>> for what amounts to a boolean field (remote/not remote).
    >>>
    >>> I think the generated superclass should perform the duty of calling
    >>> the
    >>> appropriate method for reading and writing properties. I think
    >>> this would
    >>> advocate adding an isRemote() method to the ObjectContext interface
    >>> to avoid
    >>> having to do instanceof operations.
    >>>
    >>> There would have to be some sort of unification between
    >>> PersistentObject and
    >>> CayenneDataObject as well. My naïve guess is that the latter could
    >>> extend
    >>> the former, but I haven't investigated whether or not they are
    >>> compatible.
    >>>
    >>> Does this sound like a reasonable approach? If so, I'll probably
    >>> dig in on
    >>> that.
    >>>
    >>> Thanks,
    >>> Kevin



    This archive was generated by hypermail 2.0.0 : Wed Nov 07 2007 - 03:54:00 EST