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