Re: Shared EC woes (was: Flattened one-side M:N fails wildly with SharedEC)

2018-10-02 Thread ocs@ocs
g4j.logger.er...something to get that for free?

> I have found that the culprit object is one of those changed in the step (c), 
> and I have found that touching the shared EO in the SEC before the fetch 
> helps: the shared EO gets re-loaded, and the fetch works as presumed 
> (returning the shared EO in the SEC). Now, I do this:
>  
> - whenever the SharedEditingContextInitializedObjectsNotification comes, I 
> record the SEC;
> - after the shared EOs are changed (in an EC with null SEC) and saved, I go 
> through all the SECs recorded; for each of them I get all its 
> registeredObjects, and for each of them call eo.storedValueForKey(anyKey). If 
> the object has been changed, this re-loads it in SEC, and subsequent fetching 
> works properly.
>  
> This seems to me extremely weird. Can you understand what the heck happens 
> there and why?
>  
> No, not with any certainty.  It feels like an EOF bug.  Your usage is 
> probably different from most, so you may be the first to find this.

Actually, I feel I must be doing something wrong at my side. Or is really the 
workflow

- do something which inits and loads SEC
- load a shared EO into an EC with null SEC, update it, save
- in a normal EC (with SEC), do a fetch whose fetchspec fits some shared EOs

that unique? That seems surprising.

Thanks a lot and all the best,
OC

>   
> From: "o...@ocs.cz <mailto:o...@ocs.cz>" mailto:o...@ocs.cz>>
> Date: Friday, September 28, 2018 at 6:56 PM
> To: Chuck Hill mailto:ch...@gevityinc.com>>
> Cc: WebObjects-Dev Mailing List  <mailto:webobjects-dev@lists.apple.com>>
> Subject: Shared EC woes (was: Flattened one-side M:N fails wildly with 
> SharedEC)
>  
> Chuck, 
>  
> well, so far, I have found two problems with SEC. One of them is boringly 
> self-evident, but a hell to find: very simply, my legacy code did contain 
> something like
>  
> Foo something() {
>   ...
>   
> EOUtilities.objectWithPrimaryKeyValue(this.editingContext(),'NonSharedFooEntity',pk)
> }
>  
> Which, of course, if this was shared, loads the object into SEC, and hilarity 
> ensues. I wonder how many similar traps there are in my legacy code...
>  
> The other case though is weird. You might recall that my code
> - first does some special initialisations without a SEC (all the ECs I use 
> has their SEC immediately upon creation set to nulls)
> - when done, I change the connection dictionary, re-connect using 
> EODatabaseContext.forceConnectionWithModel, and run on normally with SECs.
>  
> The problem is that during the special init code I happen to need a DBC; and 
> it seems that the code
>  
> def 
> ctxt=ERXEOAccessUtilities.databaseContextForEntityNamed(ec.rootObjectStore(),someEntity.name)
>  
> always initialises the default SEC and loads the shared EOs into it — 
> regardless the fact that the ec does not have a SEC at all.
>  
> Subsequently, I change (in the EC without a SEC) some shared EOs. The 
> documentation says that SEC would observe such changes and would refetch 
> those shared EOs into a SEC; well, it does, but not when they happen, nor 
> when the EC is saved, nor when it is unlocked — far as I was able to find, it 
> happens only when the EO in the SEC is touched (i.e., its attribute is read).
>  
> If this does not happen, i.e., if the previously changed shared EO is not 
> touched in the SEC, a first fetch into a normal EC (with SEC) whose fetch 
> spec happens to include a changed shared EO crashes. In other words, it goes 
> like this:
>  
> (a) init-time, I am consistently using ECs with null SEC;
> (b) with one of those, I call databaseContextForEntityNamed, which 
> initializes and populates the default SEC;
> (c) later, in the EC with null SEC, I fetch and change a couple of shared EOs 
> (they do not get re-loaded in SEC!)
> (d) later, normal-run-time, I fetch objects into an EC with SEC; the fetch 
> spec happens to fit some shared EOs...
>  
> ... and it results in a EOEditingContext: initializeObject: attempt to 
> initialize object ... that exists in a shared context via a non-shared 
> context. [1]
>  
> I have found that the culprit object is one of those changed in the step (c), 
> and I have found that touching the shared EO in the SEC before the fetch 
> helps: the shared EO gets re-loaded, and the fetch works as presumed 
> (returning the shared EO in the SEC). Now, I do this:
>  
> - whenever the SharedEditingContextInitializedObjectsNotification comes, I 
> record the SEC;
> - after the shared EOs are changed (in an EC with null SEC) and saved, I go 
> through all the SECs recorded; for each of them I get all its 
> registeredObjects, and for each of them call eo.storedValueForKey(anyKey). If 
> t

Re: Shared EC woes (was: Flattened one-side M:N fails wildly with SharedEC)

2018-10-02 Thread Chuck Hill
Hi OC!

I am using Microsoft Outlook which does not believe that in-line quoting is 
useful.  So email salad:

Your second problem seems mostly like what I would expect.

The other case though is weird. You might recall that my code
- first does some special initialisations without a SEC (all the ECs I use has 
their SEC immediately upon creation set to nulls)
- when done, I change the connection dictionary, re-connect using 
EODatabaseContext.forceConnectionWithModel, and run on normally with SECs.

The problem is that during the special init code I happen to need a DBC; and it 
seems that the code

def 
ctxt=ERXEOAccessUtilities.databaseContextForEntityNamed(ec.rootObjectStore(),someEntity.name)

always initialises the default SEC and loads the shared EOs into it — 
regardless the fact that the ec does not have a SEC at all.

I think the author of this may have not quite understood what setting the ec 
SEC to null does.  It does not prevent SEC creation or loading, it just affects 
that particular EC and prevents it from getting/seeing objects in the SEC.  So 
you can fetch shared objects into it, edit them and save them.

Note that the call to  ERXEOAccessUtilities.databaseContextForEntityNamed does 
not actually take the EC, it takes the root object store (aka 
EOObjectStoreCoordinator in most cases).   So that ec.sharedEditingContext() == 
null is wholly irrelevant.

Subsequently, I change (in the EC without a SEC) some shared EOs. The 
documentation says that SEC would observe such changes and would refetch those 
shared EOs into a SEC; well, it does, but not when they happen, nor when the EC 
is saved, nor when it is unlocked — far as I was able to find, it happens only 
when the EO in the SEC is touched (i.e., its attribute is read).

Your apps change the shared Eos when they launch and save them?  Every time?  
That seems… counter intuitive.   Without looking, I’d interpret “that SEC would 
observe such change” as it will refault the shared objects when it gets the 
ObjectChangedInObjectStore notification.  So the update to new values would 
naturally happen when willRead() is called on a shared EO.


If this does not happen, i.e., if the previously changed shared EO is not 
touched in the SEC, a first fetch into a normal EC (with SEC) whose fetch spec 
happens to include a changed shared EO crashes. In other words, it goes like 
this:

(a) init-time, I am consistently using ECs with null SEC;
(b) with one of those, I call databaseContextForEntityNamed, which initializes 
and populates the default SEC;
(c) later, in the EC with null SEC, I fetch and change a couple of shared EOs 
(they do not get re-loaded in SEC!)
(d) later, normal-run-time, I fetch objects into an EC with SEC; the fetch spec 
happens to fit some shared EOs...

... and it results in a EOEditingContext: initializeObject: attempt to 
initialize object ... that exists in a shared context via a non-shared context. 
[1]

Do the editing contexts from a...c still exist at this time?

I have found that the culprit object is one of those changed in the step (c), 
and I have found that touching the shared EO in the SEC before the fetch helps: 
the shared EO gets re-loaded, and the fetch works as presumed (returning the 
shared EO in the SEC). Now, I do this:

- whenever the SharedEditingContextInitializedObjectsNotification comes, I 
record the SEC;
- after the shared EOs are changed (in an EC with null SEC) and saved, I go 
through all the SECs recorded; for each of them I get all its 
registeredObjects, and for each of them call eo.storedValueForKey(anyKey). If 
the object has been changed, this re-loads it in SEC, and subsequent fetching 
works properly.

This seems to me extremely weird. Can you understand what the heck happens 
there and why?

No, not with any certainty.  It feels like an EOF bug.  Your usage is probably 
different from most, so you may be the first to find this.

Chuck



From: "o...@ocs.cz" 
Date: Friday, September 28, 2018 at 6:56 PM
To: Chuck Hill 
Cc: WebObjects-Dev Mailing List 
Subject: Shared EC woes (was: Flattened one-side M:N fails wildly with SharedEC)

Chuck,

well, so far, I have found two problems with SEC. One of them is boringly 
self-evident, but a hell to find: very simply, my legacy code did contain 
something like

Foo something() {
  ...
  
EOUtilities.objectWithPrimaryKeyValue(this.editingContext(),'NonSharedFooEntity',pk)
}

Which, of course, if this was shared, loads the object into SEC, and hilarity 
ensues. I wonder how many similar traps there are in my legacy code...

The other case though is weird. You might recall that my code
- first does some special initialisations without a SEC (all the ECs I use has 
their SEC immediately upon creation set to nulls)
- when done, I change the connection dictionary, re-connect using 
EODatabaseContext.forceConnectionWithModel, and run on normally with SECs.

The problem is that during the special init code I happen to need a DBC; and

Shared EC woes (was: Flattened one-side M:N fails wildly with SharedEC)

2018-09-28 Thread o...@ocs.cz
Chuck,

well, so far, I have found two problems with SEC. One of them is boringly 
self-evident, but a hell to find: very simply, my legacy code did contain 
something like

Foo something() {
  ...
  
EOUtilities.objectWithPrimaryKeyValue(this.editingContext(),'NonSharedFooEntity',pk)
}

Which, of course, if this was shared, loads the object into SEC, and hilarity 
ensues. I wonder how many similar traps there are in my legacy code...

The other case though is weird. You might recall that my code
- first does some special initialisations without a SEC (all the ECs I use has 
their SEC immediately upon creation set to nulls)
- when done, I change the connection dictionary, re-connect using 
EODatabaseContext.forceConnectionWithModel, and run on normally with SECs.

The problem is that during the special init code I happen to need a DBC; and it 
seems that the code

def 
ctxt=ERXEOAccessUtilities.databaseContextForEntityNamed(ec.rootObjectStore(),someEntity.name)

always initialises the default SEC and loads the shared EOs into it — 
regardless the fact that the ec does not have a SEC at all.

Subsequently, I change (in the EC without a SEC) some shared EOs. The 
documentation says that SEC would observe such changes and would refetch those 
shared EOs into a SEC; well, it does, but not when they happen, nor when the EC 
is saved, nor when it is unlocked — far as I was able to find, it happens only 
when the EO in the SEC is touched (i.e., its attribute is read).

If this does not happen, i.e., if the previously changed shared EO is not 
touched in the SEC, a first fetch into a normal EC (with SEC) whose fetch spec 
happens to include a changed shared EO crashes. In other words, it goes like 
this:

(a) init-time, I am consistently using ECs with null SEC;
(b) with one of those, I call databaseContextForEntityNamed, which initializes 
and populates the default SEC;
(c) later, in the EC with null SEC, I fetch and change a couple of shared EOs 
(they do not get re-loaded in SEC!)
(d) later, normal-run-time, I fetch objects into an EC with SEC; the fetch spec 
happens to fit some shared EOs...

... and it results in a EOEditingContext: initializeObject: attempt to 
initialize object ... that exists in a shared context via a non-shared context. 
[1]

I have found that the culprit object is one of those changed in the step (c), 
and I have found that touching the shared EO in the SEC before the fetch helps: 
the shared EO gets re-loaded, and the fetch works as presumed (returning the 
shared EO in the SEC). Now, I do this:

- whenever the SharedEditingContextInitializedObjectsNotification comes, I 
record the SEC;
- after the shared EOs are changed (in an EC with null SEC) and saved, I go 
through all the SECs recorded; for each of them I get all its 
registeredObjects, and for each of them call eo.storedValueForKey(anyKey). If 
the object has been changed, this re-loads it in SEC, and subsequent fetching 
works properly.

This seems to me extremely weird. Can you understand what the heck happens 
there and why?

Thanks and all the best,
OC

[1] it looks like this: with fetch code like

println "FETCH $ec SEC:$ec.sharedEditingContext 
RELS:${EOModelGroup.defaultGroup.entityNamed(fs.entityName).relationships}"
found=ec.objectsWithFetchSpecification(fs)
println "FETCH $ec SEC:$ec.sharedEditingContext got $found"

it quite consistently crashes like this:

FETCH er.extensions.eof.ERXEC@11a11fbb 
SEC:com.webobjects.eocontrol.EOSharedEditingContext@79c3f01f RELS:[]
9301 [WorkerThread5] INFO er.transaction.adaptor.Exceptions  - Database 
Exception occured ...
... ...
Caused by: java.lang.IllegalArgumentException: EOEditingContext: 
initializeObject: attempt to initialize object with global ID 
_EOIntegralKeyGlobalID[DBDFList (java.lang.Integer)100] that exists in a shared 
context via a non-shared context. The object model may have a relationship from 
a shared entity to a non-shared entity. Disable or remove the relationship from 
the model.
at 
com.webobjects.eocontrol.EOEditingContext.initializeObject(EOEditingContext.java:3760)
at er.extensions.eof.ERXEC.initializeObject(ERXEC.java:1237)
at 
com.webobjects.eoaccess.EODatabaseChannel$_EODatabaseChannelFetchResult.initializeObjects(EODatabaseChannel.java:496)
at 
com.webobjects.eoaccess.EODatabaseContext._objectsWithFetchSpecificationEditingContext(EODatabaseContext.java:3090)
at 
com.webobjects.eoaccess.EODatabaseContext.objectsWithFetchSpecification(EODatabaseContext.java:3195)
at 
com.webobjects.eocontrol.EOObjectStoreCoordinator.objectsWithFetchSpecification(EOObjectStoreCoordinator.java:488)
at 
com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecification(EOEditingContext.java:4069)
at 
er.extensions.eof.ERXEC.objectsWithFetchSpecification(ERXEC.java:1307)
at 
com.webobjects.eocontrol.EOEditingContext.objectsWithFetchSpecification(EOEditingContext.java:)
at