• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag
 

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: [SOLVED] Baffling problem with foreign key
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [SOLVED] Baffling problem with foreign key


  • Subject: Re: [SOLVED] Baffling problem with foreign key
  • From: Gary Teter <email@hidden>
  • Date: Sun, 7 Dec 2008 12:44:23 -0800

I finally figured out what's going on, and I think it's a fundamental flaw in WebObjects. Fortunately Ralf's suggestion is a good-enough workaround:

A workaround may be to call "EOObserverCenter.notifyObserversObjectWillChange(null)" at strategic places like in Application.dispatchRequest().

What's supposed to happen: You change an attribute on an eo, which calls willChange(), which calls EOObserverCenter.notifyObserversObjectWillChange(this). The observer center notes that this was the most recently observed object for this thread, and calls editingContext.objectWillChange. The ec then grabs the current snapshot of the object, and then the attribute is finally changed in the eo. Any further calls to willChange >in the current thread< on the eo are ignored by the EOObserverCenter. When the ec saves changes, it calls notifyObserversObjectWillChange(null) so any future changes to the eo get noticed again.


How it fails: A request is handled by WorkerThread0. By the end of the request the eo has been modified but not saved, so the EOObserverCenter remembers that WorkerThread0's most recent object is that eo. Fifteen more requests are handled by WorkerThreads 1-15 in sequence. One of these requests completes the modification of the eo and calls saveChanges on the ec. At this point the ec tells the EOObserverCenter to forget about its most recent object, but it's being set to null in WorkerThread14 or whatever, not WorkerThread0.

The next request will wrap around to to be handled by WorkerThread0. This request modifies an attribute on the eo, but since the EOObserverCenter still thinks WorkerThread0 has already noticed the eo, it ignores the willChange and the ec doesn't grab a snapshot.

Later in the processing of this request, a different object gets changed, willChange gets called and the ec grabs a snapshot of the second object. Then, a change gets made to the original eo, willChange gets called, and since the EOObserverCenter was paying attention to the second object, it goes ahead and notifies the ec about the first object.

At this point the ec grabs a snapshot of the first object, but it's too late -- the object has already been modified, the ec didn't know about the previous change, so when saveChanges gets called the previous changes don't get saved to the database. And now your object graph no longer matches the database, and your app is borked.

I think I understand this bug well enough now to construct the simplest possible test case and file it in Radar. I also wouldn't be surprised to find it in 5.4 (still haven't upgraded so can't test).

On Dec 5, 2008, at 8:09 AM, Gary Teter wrote:

On Dec 5, 2008, at 3:22 AM, Ralf Schuchardt wrote:


Am 05.12.2008 um 01:41 schrieb Gary Teter:

Wow. I got misled by my logging. Turns out it's perfectly fine for __originalSnapshot to be null before objectWillChange is called, because the first time it's called it sets the __originalSnapshot >before< the new value is set. Further changes to the object don't set the __originalSnapshot.

So it turns out that the problem is that somehow objectWillChange is not getting called until >after< the change has been made. Here's what it should look like:

DebuggingEditingContext@2dc21d lock()
going to setServiceRate() - [2223, UPS Mail Innovations Bound Printed Matter, $5.36 for 64 oz, zone 5 (min BPM 50%)]
beginning willChange() - Order # 664975
objectWillChange: Order # 664975, created 08/25/06 03:03:44 PM 1 items for subtotal $59.95
snapshot() - returning: { ...omitted... } <-- here's where __originalSnapshot gets set
done willChange() - Order # 664975
beginning willChange() - Order # 664975
done willChange() - Order # 664975
done setServiceRate() - [2223, UPS Mail Innovations Bound Printed Matter, $5.36 for 64 oz, zone 5 (min BPM 50%)]


And here's what it looks like when it's borked:

DebuggingEditingContext@2dc21d lock()
going to setServiceRate() - [5, UPS Ground for 2400 oz, United States]
beginning willChange() - Order # 664975
done willChange() - Order # 664975
beginning willChange() - Order # 664975
done willChange() - Order # 664975
done setServiceRate() - [5, UPS Ground for 2400 oz, United States]


Note that the serviceRate has been completely set by this point, and objectWillChange has not yet been called. (It gets called later. Now I get to figure out why EOObserverCenter.notifyObserversObjectWillChange() apparently isn't doing its job...


It might well be another EOF bug (or a consequence of the bug Chuck talked about).

EOObserverCenter stores the last changed object per thread, so it will not repeatedly send notifications for the same object.
This information is normally reset at certain points, but sometimes it's missed.


As a result you may see sporadic failures to recognize changes in an EO when the same worker thread is changing the same object.

A workaround may be to call "EOObserverCenter.notifyObserversObjectWillChange(null)" at strategic places like in Application.dispatchRequest().

(But I believe the real culprit is the EC loosing its information about changed objects, otherwise it shouldn't be necessary to tell the EC about changes in an EO again ...)

Ralf

That's what I suspected, so I added a call to notifyObserversObjectWillChange(null) to a method that responds to the EditingContextDidSaveChanges notification, figuring that's the best place to put it. But the borking is still there. I also added logging to see if the observerNotificationSuppressCount was non- zero during OrderObject's willChange (it's zero), and to display the observersForObject for the OrderObject in case somehow its ec was not on the list (it is).


As I understand EOObserverCenter the only thing left is that the observer center's last changed object is being set somehow behind my back in between my setting it to null and my attempt to set the serviceRate relationship. But how and why is eluding me right now:

DebuggingEditingContext@6231ed _clearOriginalSnapshotAndInitializeRec() - OrderLineItem 1302722
_editingContextDidSaveChanges - notifyObserversObjectWillChange(null)
DebuggingEditingContext@6231ed saveChanges()
_editingContextDidSaveChanges - notifyObserversObjectWillChange(null)
DebuggingEditingContext@6231ed unlock()
DebuggingEditingContext@6231ed tryLock()
DebuggingEditingContext@6231ed lock()
DebuggingEditingContext@6231ed processRecentChanges()
DebuggingEditingContext@6231ed unlock()
<end of previous request>


[2008-12-04 18:42:46 PST] <WorkerThread8> <127.0.0.1> "POST /cgi- bin/WebObjects/Store.woa/1/wo/TdoyaGbiVbMqgXYbawJFpw/ 93.2.3.1.0.2.1.35.3.1.1.1.1.2.1.5.3.0.3.1 HTTP/1.1" Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_4_11; en) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1

DebuggingEditingContext@6231ed lock()
going to setServiceRate() - [5, UPS Ground for 2400 oz, United States]
beginning willChange() - Order # 664975, observerNotificationSuppressCount: 0
beginning willChange() - Order # 664975, observersForObject: (DebuggingEditingContext@6231ed)
done willChange() - Order # 664975, observerNotificationSuppressCount: 0
done willChange() - Order # 664975, observersForObject: (DebuggingEditingContext@6231ed)
beginning willChange() - Order # 664975, observerNotificationSuppressCount: 0
beginning willChange() - Order # 664975, observersForObject: (DebuggingEditingContext@6231ed)
done willChange() - Order # 664975, observerNotificationSuppressCount: 0
done willChange() - Order # 664975, observersForObject: (DebuggingEditingContext@6231ed)
done setServiceRate() - [5, UPS Ground for 2400 oz, United States]


Anybody know the best way to install my own replacement EOObserverCenter so I can see what's going on? Or a way to set breakpoints in code that's not mine?


--
The Ent visualization project:
http://wirehose.com/research/entvisualization



_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >Baffling problem with foreign key (From: Gary Teter <email@hidden>)
 >Re: Baffling problem with foreign key (From: Chuck Hill <email@hidden>)
 >Re: Baffling problem with foreign key (From: Gary Teter <email@hidden>)
 >Re: Baffling problem with foreign key (From: Gary Teter <email@hidden>)
 >Re: Baffling problem with foreign key (From: Chuck Hill <email@hidden>)
 >Re: Baffling problem with foreign key (From: Gary Teter <email@hidden>)
 >Re: Baffling problem with foreign key (From: Chuck Hill <email@hidden>)
 >Re: Baffling problem with foreign key (From: Gary Teter <email@hidden>)
 >Re: Baffling problem with foreign key (From: Ralf Schuchardt <email@hidden>)
 >Re: Baffling problem with foreign key (From: Gary Teter <email@hidden>)

  • Prev by Date: Re: [BUG] ERXGoogleSpell API
  • Next by Date: Re: Criticism of Java Persistence Frameworks Blog Post
  • Previous by thread: Re: Baffling problem with foreign key
  • Next by thread: Where is the deadlock culprit?
  • Index(es):
    • Date
    • Thread