Re: Snapshot problems
Re: Snapshot problems
- Subject: Re: Snapshot problems
- From: Chuck Hill <email@hidden>
- Date: Thu, 19 Apr 2007 21:24:28 -0700
Mark,
On Apr 19, 2007, at 8:54 PM, Steven Mark McCraw wrote:
Ok, I spent the evening scouring every framework and the
application to make 100% certain that I am not violating any EOF
commandments, and although it is always possible that I missed
something somewhere, I am pretty darn sure I am clean.
Furthermore, DebugGroupMultithreading isn't spitting out any
warnings, so I assume I'm safe there. I'm not using a shared
editing context anywhere. As far as I know, my editing contexts
never get garbage collected until the session expires (I have two
that I use, the default editing context, and an editing context
that is nested in the default which is referenced in session and
locks and unlocks in awake and sleep).
Session's awake and sleep you mean? OK, that seems pretty safe from
an unlocked access point of view.
I've managed to come up with a workflow that reliably causes the
exception,
Are any other EOs faulting in prior to or while running this
workflow? Are there other sessions actively processing requests at
the same time?
and over the course of running it dozens of times with different
debugging statements, I've learned a few things. I'm loathe to
call this a bug in EOF, because there are so many unknowns and
complexities, but it sure seems like a good candidate for that
label. Here is the scenario:
I have an edit page for a catalog item. The catalog item has one
or more KitQuantity's, and each KitQuantity has an InventoryItem:
CatalogItem <-->>KitQuantity<<-->InventoryItem
A KitQuantity is a glorified join table which relates the catalog
item to many inventory items, plus keeps a little bit of other
information such as how many of each inventory item belong in the
catalog item definition. The relevant part here is the piece where
I add KitQuantities. If I have an existing catalog item, I load
the edit page and pass it the catalog item to be edited. Within
the edit page's setCatalogItem method, I get local instances of all
the relevant pieces within my nested editing context (_nestedEC)
using EOUtilities.localInstanceOfObject/localInstancesOfObjects. I
list the KitQuantities on the edit page, and have a delete button
beside each one. When the delete button is clicked, the following
code is executed:
public WOComponent removeItem() {
Just for giggles, have you tried adding these lines here:
_nestedEC.revert();
ec.revert();
No, you should not have to, I am just wondering if adding them
changes the outcome at all.
_nestedEC.deleteObject( _kitQuantity );
What are the delete rules on the relationships out of KitQuantity?
_nestedEC.saveChanges();
ec.saveChanges();
setValueForBinding( "Changes Saved", "message" );
return context().page();
}
It works great when I load an existing Catalog Item and delete it's
KitQuantity relationships one by one. In the same page I can do a
search on inventory items and select inventory items (and a
quantity) to add to the catalog item via KitQuantity
relationships. I create my KitQuantity using
EOUtilities.createAndInsertObject with _nestedEC, set the quantity
attribute, addObjectToBothSidesOfRelationshipWithKey for both the
CatalogItem and the InventoryItem, saveChanges() on _nestedEC, and
then saveChanges on session.defaultEditingContext():
public WOComponent addItemToKit() {
Also, try here:
_nestedEC.revert();
ec.revert();
_kitQuantity = (KitQuantity)
EOUtilities.createAndInsertInstance( _nestedEC, "KitQuantity" );
Is awakeFromInsertion implemented in KitQuantity? Did you remember
to call super?
_kitQuantity.setQuantity( proposedQuantity );
_kitQuantity.addObjectToBothSidesOfRelationshipWithKey
( catalogItem, "catalogItem" );
_kitQuantity.addObjectToBothSidesOfRelationshipWithKey
( inventoryItem,
"inventoryItem" );
localSession.addToMessage( proposedQuantity + " " +
inventoryItem.sku()
+ " added to kit." );
}
_nestedEC.saveChanges();
ec.saveChanges();
return context().page();
}
This works great also. The KitQuantities are visibly represented
on the page, they are definitely in the database, and I can even
print out the snapshot for the items for both editing contexts as
they are created, and everything is perfect.
What if you print the snapshots out in the removeItem method?
If I were to quit the application, restart, and come back to this
page and edit this item, I could delete the KitQuantities without a
care in the world. But if I immediately start deleting the NEWLY
CREATED KitQuantity items, I run into problems.
That sounds very, very familiar. I am sure I have had this happen to
me, but I am also pretty sure it turned out to not be an EOF bug. I
am wracking my brain trying to recall when / why this happened...
Usually (but not always) the first one deletes ok, but at some
point in deleting the remaining ones, I get the following exception:
java.lang.IllegalStateException: recordDeleteForObject:
com.webobjects.eoaccess.EODatabaseContext
com.webobjects.eoaccess.EODatabaseContext@c5627c failed to find a
snapshot for EO with Global ID:_EOIntegralKeyGlobalID[KitQuantity
(java.lang.Integer)1216] that has been deleted from
er.extensions.ERXECer.extensions.ERXEC@b88745. Cannot delete an
object that has not been fetched from the database
It almost looks like EOF is trying to process the same delete twice
in a row. Is there any chance that the action method is somehow
getting called twice? I have also seen stuff like that happen when
the editing contexts are not locked properly, but you seem to be
locking correctly.
[2007-04-19 23:06:49 EDT] <WorkerThread9>
java.lang.IllegalStateException: recordDeleteForObject:
com.webobjects.eoaccess.EODatabaseContext
com.webobjects.eoaccess.EODatabaseContext@c5627c failed to find a
snapshot for EO with Global ID:_EOIntegralKeyGlobalID[KitQuantity
(java.lang.Integer)1216] that has been deleted from
er.extensions.ERXECer.extensions.ERXEC@b88745. Cannot delete an
object that has not been fetched from the database
at com.webobjects.eoaccess.EODatabaseContext.recordDeleteForObject
(EODatabaseContext.java:4926)
at
com.webobjects.eoaccess.EODatabaseContext.recordChangesInEditingContex
t(EODatabaseContext.java:6059)
at
com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesInEditing
Context(EOObjectStoreCoordinator.java:412)
at com.webobjects.eocontrol.EOEditingContext.saveChanges
(EOEditingContext.java:3226)
at er.extensions.ERXEC._saveChanges(ERXEC.java:947)
at er.extensions.ERXEC.saveChanges(ERXEC.java:870)
at EditKitHelper.removeItem(EditKitHelper.java:77)
...
Here the editing context identified by "b88745" represents the
session's editing context, and the exception is thrown when I call
saveChanges on the default editing context within the removeItem
method. Furthermore, if I print out ec.deletedObjects() right
before calling ec.saveChanges (and after _nestedEC.saveChanges),
the item to be deleted is there!:
ec.deletedObjects(): (<KitQuantity pk:"1216">)
Can you print out its snapshot right then too.
So it appears that the nested EC is flushing its information to the
default ec correctly, and I can tell that the editingContext's
snapshots are fine until very shortly before the operation. Just
in case there was something funny going on in the EO's, I commented
out every line of code from CatalogItem, InventoryItem, and
KitQuantity (the three classes being dealt with here), so that
effectively they were all blank implementations, and I still get
the same result. This would seem to rule out any possibility of
EOF commandment violation.
So there is nothing in them now? Are there any super classes that
may be affecting things.
At this point I am over trying to understand what is going on or
walk on eggshells to make sure I don't offend EOF's delicate
sensibilities. I'm under a deadline and I'm seriously considering
just cutting EOF out of the loop and doing the whole thing using
straight JDBC, but I hear (and somewhat know from experience) that
that approach is a slippery slope to misery, so I thought I would
put out a detailed description of what I'm doing just in case
anyone sees something glaringly obvious or stupid in my methodology
(always a distinct possibility). Any help or thoughts are greatly
appreciated.
That was, I must say, a very, very good error report. See if any of
the above things provide any more insight and I will keep trying to
recall when this last happened to me.
Chuck
On Apr 19, 2007, at 4:34 PM, Chuck Hill wrote:
On Apr 19, 2007, at 12:54 PM, Steven Mark McCraw wrote:
Hey Chuck,
/Library/Receipts tells me I'm on the 5.3.3 update.
I have been running with DebugGroupMultithreading for a few days
now, and nothing seems to have changed, so I assumed everything
was ok there, but it could just be that I set things up wrong. I
just added the following lines to my Application constructor:
NSLog.debug.setAllowedDebugLevel
(NSLog.DebugLevelInformational);
NSLog.allowDebugLoggingForGroups
(NSLog.DebugGroupEnterpriseObjects |
NSLog.DebugGroupMultithreading);
Should that do it, or is there something else I need to do?
I think that should do it.
Otherwise, I will go through and clean out anything anywhere that
overrides a setter or getter and changes the data being set/get,
and I'll see if that makes a difference.
Thanks for the suggestions.
The only other things that I can think of that might _possibly_
causing something like this are
- misuse of the shared EC
- somehow keeping a reference to an EO after its editing context
has been disposed
- holding a lock on an EC for too lock and it getting out of synch
with the snapshots
Chuck
--
Practical WebObjects - for developers who want to increase their
overall knowledge of WebObjects or who are trying to solve specific
problems.
http://www.global-village.net/products/practical_webobjects
_______________________________________________
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