localObject() behavior

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

localObject() behavior

Michael Gentry
I'm converting an application from 3.0 to 3.1 and was fixing all the
localObject() calls to be the simpler version introduced in 3.1.  One thing
I encountered was a utility method:

    public static <T extends CayenneDataObject> T copyToContext(T
cayenneObject, DataContext dataContext)
    {
        T copiedObject =
dataContext.localObject(cayenneObject.getObjectId(), cayenneObject);

        // The returned copy is HOLLOW, make the copy NEW if the original
is NEW.
        if (cayenneObject.getPersistenceState() == PersistenceState.NEW)
            copiedObject.setPersistenceState(PersistenceState.NEW);

        return copiedObject;
    }

I tried removing this utility method and just use the new localObject(),
but exceptions (such as FaultFailureException) started being thrown.  (I
won't even try to explain why so many local object copies of non-persisted
objects are being used.)

Anyone know why making a local object copy of a NEW object will set the
copy to HOLLOW which will try to trigger faults later?

Thanks,

mrg
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: localObject() behavior

Andrus Adamchik
> Anyone know why making a local object copy of a NEW object will set the
> copy to HOLLOW which will try to trigger faults later?

This is a valid situation in case of nested contexts. If you use 'localObject' on an object from a parent context, copying it to a child context, it will resolve from HOLLOW by checking the parent.

Andrus


> On Apr 10, 2017, at 7:38 AM, Michael Gentry <[hidden email]> wrote:
>
> I'm converting an application from 3.0 to 3.1 and was fixing all the
> localObject() calls to be the simpler version introduced in 3.1.  One thing
> I encountered was a utility method:
>
>    public static <T extends CayenneDataObject> T copyToContext(T
> cayenneObject, DataContext dataContext)
>    {
>        T copiedObject =
> dataContext.localObject(cayenneObject.getObjectId(), cayenneObject);
>
>        // The returned copy is HOLLOW, make the copy NEW if the original
> is NEW.
>        if (cayenneObject.getPersistenceState() == PersistenceState.NEW)
>            copiedObject.setPersistenceState(PersistenceState.NEW);
>
>        return copiedObject;
>    }
>
> I tried removing this utility method and just use the new localObject(),
> but exceptions (such as FaultFailureException) started being thrown.  (I
> won't even try to explain why so many local object copies of non-persisted
> objects are being used.)
>
> Anyone know why making a local object copy of a NEW object will set the
> copy to HOLLOW which will try to trigger faults later?
>
> Thanks,
>
> mrg

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: localObject() behavior

Michael Gentry
Well, these are all peer contexts and rely heavily on the old behavior of
the prototype values being copied over ...


On Tue, Apr 11, 2017 at 2:49 PM, Andrus Adamchik <[hidden email]>
wrote:

> > Anyone know why making a local object copy of a NEW object will set the
> > copy to HOLLOW which will try to trigger faults later?
>
> This is a valid situation in case of nested contexts. If you use
> 'localObject' on an object from a parent context, copying it to a child
> context, it will resolve from HOLLOW by checking the parent.
>
> Andrus
>
>
> > On Apr 10, 2017, at 7:38 AM, Michael Gentry <[hidden email]> wrote:
> >
> > I'm converting an application from 3.0 to 3.1 and was fixing all the
> > localObject() calls to be the simpler version introduced in 3.1.  One
> thing
> > I encountered was a utility method:
> >
> >    public static <T extends CayenneDataObject> T copyToContext(T
> > cayenneObject, DataContext dataContext)
> >    {
> >        T copiedObject =
> > dataContext.localObject(cayenneObject.getObjectId(), cayenneObject);
> >
> >        // The returned copy is HOLLOW, make the copy NEW if the original
> > is NEW.
> >        if (cayenneObject.getPersistenceState() == PersistenceState.NEW)
> >            copiedObject.setPersistenceState(PersistenceState.NEW);
> >
> >        return copiedObject;
> >    }
> >
> > I tried removing this utility method and just use the new localObject(),
> > but exceptions (such as FaultFailureException) started being thrown.  (I
> > won't even try to explain why so many local object copies of
> non-persisted
> > objects are being used.)
> >
> > Anyone know why making a local object copy of a NEW object will set the
> > copy to HOLLOW which will try to trigger faults later?
> >
> > Thanks,
> >
> > mrg
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: localObject() behavior

Andrus Adamchik
Yes, this was a breaking change. The old "localObject" was used by the internal code, but was also exposed as public API. So it tried to be everything to everybody. Calling it required checking a bunch of preconditions, and it was generally hard to understand what it would do in any given situation.

The current "localObject" is arguably easier to understand as it deals with a very specific case: mapping an object from one context to the *same* object in the other. This necessarily limits us to creating a HOLLOW object (that will throw if it can't resolve its state from parent), as doing anything else would violate two objects equality expectations:

T t1 = c1.newObject(T.class);
T t2 = c2.localObject(t1);

c1.commitChanges();

// t1 no longer corresponds to t2 under the old "localObject" ; under the new it will throw on access.

So yeah, if you need a different flavor of this operation that copies uncommitted state, you will need to implement it on your own. If it is a common enough case, and we can clearly define what it does, perhaps we'll find a place for it in Cayenne core.

Andrus



> On Apr 12, 2017, at 4:50 AM, Michael Gentry <[hidden email]> wrote:
>
> Well, these are all peer contexts and rely heavily on the old behavior of
> the prototype values being copied over ...
>
>
> On Tue, Apr 11, 2017 at 2:49 PM, Andrus Adamchik <[hidden email]>
> wrote:
>
>>> Anyone know why making a local object copy of a NEW object will set the
>>> copy to HOLLOW which will try to trigger faults later?
>>
>> This is a valid situation in case of nested contexts. If you use
>> 'localObject' on an object from a parent context, copying it to a child
>> context, it will resolve from HOLLOW by checking the parent.
>>
>> Andrus
>>
>>
>>> On Apr 10, 2017, at 7:38 AM, Michael Gentry <[hidden email]> wrote:
>>>
>>> I'm converting an application from 3.0 to 3.1 and was fixing all the
>>> localObject() calls to be the simpler version introduced in 3.1.  One
>> thing
>>> I encountered was a utility method:
>>>
>>>   public static <T extends CayenneDataObject> T copyToContext(T
>>> cayenneObject, DataContext dataContext)
>>>   {
>>>       T copiedObject =
>>> dataContext.localObject(cayenneObject.getObjectId(), cayenneObject);
>>>
>>>       // The returned copy is HOLLOW, make the copy NEW if the original
>>> is NEW.
>>>       if (cayenneObject.getPersistenceState() == PersistenceState.NEW)
>>>           copiedObject.setPersistenceState(PersistenceState.NEW);
>>>
>>>       return copiedObject;
>>>   }
>>>
>>> I tried removing this utility method and just use the new localObject(),
>>> but exceptions (such as FaultFailureException) started being thrown.  (I
>>> won't even try to explain why so many local object copies of
>> non-persisted
>>> objects are being used.)
>>>
>>> Anyone know why making a local object copy of a NEW object will set the
>>> copy to HOLLOW which will try to trigger faults later?
>>>
>>> Thanks,
>>>
>>> mrg
>>
>>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: localObject() behavior

Michael Gentry
To be honest, I have no idea why the original developers chose to make all
of these "micro-context" copies.  A new peer DC will be created and a
single or just a few objects copied over into it as part of the validation
process and then those "micro-context" DCs are allowed to be garbage
collected after the validation completes.  Given that the original
developers are gone, kind of hard to ask for their reasoning.  My instinct
is that you should be able to run the validations with the original
context/objects and not need to create new ones (especially when you have
potentially 1000s of objects in the original DC).

Thanks for the input,

mrg


On Thu, Apr 13, 2017 at 10:51 AM, Andrus Adamchik <[hidden email]>
wrote:

> Yes, this was a breaking change. The old "localObject" was used by the
> internal code, but was also exposed as public API. So it tried to be
> everything to everybody. Calling it required checking a bunch of
> preconditions, and it was generally hard to understand what it would do in
> any given situation.
>
> The current "localObject" is arguably easier to understand as it deals
> with a very specific case: mapping an object from one context to the *same*
> object in the other. This necessarily limits us to creating a HOLLOW object
> (that will throw if it can't resolve its state from parent), as doing
> anything else would violate two objects equality expectations:
>
> T t1 = c1.newObject(T.class);
> T t2 = c2.localObject(t1);
>
> c1.commitChanges();
>
> // t1 no longer corresponds to t2 under the old "localObject" ; under the
> new it will throw on access.
>
> So yeah, if you need a different flavor of this operation that copies
> uncommitted state, you will need to implement it on your own. If it is a
> common enough case, and we can clearly define what it does, perhaps we'll
> find a place for it in Cayenne core.
>
> Andrus
>
>
>
> > On Apr 12, 2017, at 4:50 AM, Michael Gentry <[hidden email]> wrote:
> >
> > Well, these are all peer contexts and rely heavily on the old behavior of
> > the prototype values being copied over ...
> >
> >
> > On Tue, Apr 11, 2017 at 2:49 PM, Andrus Adamchik <[hidden email]
> >
> > wrote:
> >
> >>> Anyone know why making a local object copy of a NEW object will set the
> >>> copy to HOLLOW which will try to trigger faults later?
> >>
> >> This is a valid situation in case of nested contexts. If you use
> >> 'localObject' on an object from a parent context, copying it to a child
> >> context, it will resolve from HOLLOW by checking the parent.
> >>
> >> Andrus
> >>
> >>
> >>> On Apr 10, 2017, at 7:38 AM, Michael Gentry <[hidden email]>
> wrote:
> >>>
> >>> I'm converting an application from 3.0 to 3.1 and was fixing all the
> >>> localObject() calls to be the simpler version introduced in 3.1.  One
> >> thing
> >>> I encountered was a utility method:
> >>>
> >>>   public static <T extends CayenneDataObject> T copyToContext(T
> >>> cayenneObject, DataContext dataContext)
> >>>   {
> >>>       T copiedObject =
> >>> dataContext.localObject(cayenneObject.getObjectId(), cayenneObject);
> >>>
> >>>       // The returned copy is HOLLOW, make the copy NEW if the original
> >>> is NEW.
> >>>       if (cayenneObject.getPersistenceState() == PersistenceState.NEW)
> >>>           copiedObject.setPersistenceState(PersistenceState.NEW);
> >>>
> >>>       return copiedObject;
> >>>   }
> >>>
> >>> I tried removing this utility method and just use the new
> localObject(),
> >>> but exceptions (such as FaultFailureException) started being thrown.
> (I
> >>> won't even try to explain why so many local object copies of
> >> non-persisted
> >>> objects are being used.)
> >>>
> >>> Anyone know why making a local object copy of a NEW object will set the
> >>> copy to HOLLOW which will try to trigger faults later?
> >>>
> >>> Thanks,
> >>>
> >>> mrg
> >>
> >>
>
>
Loading...