Hello,

I have a small, yet increasingly, complex application begun using Flex
DataServics / Tomcat / Spring / Hibernate, and am running into what
apparently are not uncommon limitations with regards to the complexity
of the data model when using DataServices.

The skinny: when deleting an item from a managed collection, instead of
the client issuing the correct 'update' operation on the collection,
some internal Adobe code detects something that results in the entire
collection being released, the consumer being unsubscribed, and the
destination being disconnected...

By and large things work well, but I recently added in some inheritance
to a particular table that may or may not be causing me trouble.

Before getting overly detailed as to my exact data model, let's try the
following summary:

1) table "Presentation" has a collection of "slides"

2) table "Slide" is extended by table "SlideMaster" and
"SlideReference", joined on a shared primary key

3) table "SlideMaster" has a collection of "slideElements", and
"slideReferences"

4) table "SlideReference" simply points back to a parent "slideMaster"

For my destination configuration, I actually define a destination for
each table: spring.presentation, spring.slide, spring.slideMaster,
spring.slideReference, etc.

Note: all DataServices are set to autoCommit = false, and autoSync =
true.

Note that this is not actually the top of my object tree, but let's just
deal with the notion of adding and removing Slides from a Presentation.

I can properly add slides by:
mySlide = new SlideMaster();
mySlide.presentation = myPresentation;
myPresentation.slides.addItem(mySlide);
// then do a commit
This works fine.

However, when I attempt to remove a slide:
index = myPresentation.slides.getElementIndex(mySlide);
myPresentation.removeItemAt(index);
What happens is very odd and very frustrating.

I have ALL of the debug logging enabled, so the first thing I see is a
message queued to destination spring.presentation, operation = update.
This is as expected.

Next, I see the propertyChangedEvent handlers called on my DataServices,
indicating that commitRequired has gone from false to true, again as
expected.

However - when not stepping through breakpoints, etc., the next thing
that happens is a subsequent call to the properyChangedEvent handlers,
indicating that commitRequired is now FALSE, and this is followed by the
client issuing the following log messages:
-------------------- logging start -------------------
4/1/2008 14:37:32.233 [INFO] mx.messaging.Consumer
'cds-consumer-spring.slide-null' consumer unsubscribe.
4/1/2008 14:37:32.235 [WARN] mx.messaging.Consumer
'cds-consumer-spring.slide-null' consumer channel disconnected.
4/1/2008 14:37:32.236 [INFO] mx.messaging.Producer
'ds-producer-spring.library' producer sending message
'296B7FA3-B4AB-2F9E-5FE8-0B479ACC829B'
4/1/2008 14:37:32.238 [DEBUG] mx.messaging.Channel 'my-amf' channel
sending message:

    [... operation = release; destination = spring.slide ...]

4/1/2008 14:37:32.240 [INFO] mx.messaging.Consumer
'cds-consumer-spring.presentation-null' consumer unsubscribe.
4/1/2008 14:37:32.240 [WARN] mx.messaging.Consumer
'cds-consumer-spring.presentation-null' consumer channel disconnected.
4/1/2008 14:37:32.240 [INFO] mx.messaging.Producer
'ds-producer-spring.library' producer sending message
'ADABC35E-C24F-283B-46DC-0B479AD08F51'
4/1/2008 14:37:32.242 [DEBUG] mx.messaging.Channel 'my-amf' channel
sending message:

    [... operation = release; destination = spring.presentation ...]
-------------------- logging end -------------------

Basically, when I remove mySlide from the myPresentation.slides
collection, after DataServices queues up the correct udpate message and
sets commitRequired to true, something else happens way beneath the
covers that results in this errant cancellation of the update, and
subsequent release of the collections.

I attempted to dig deeper by stopping execution at the point at which
the second call was made to the propertyChangedEvent handler, and found
the reason for this behavior has something to do with some internal
Adobe classes, and seems most specifically due to something called
releaseItemIfNoDataListReferences, which seems to get something
confused... either as though the entire myPresentation.slides collection
should be released, or... or what, I'm not sure, but it is at this
point, if I step through the code (without of course being able to see
the code, since I don't have the source) that things change and those
releases occur.

Here is the stack at the point at which my PropertyChange handler is
notified that commitRequired is now false:
com.nv.client.model::PresentationsProxy/handlePropertyChange
flash.events::EventDispatcher/dispatchEventFunction [no source]
flash.events::EventDispatcher/dispatchEvent [no source]
flash.events::EventDispatcher/dispatchEventFunction [no source]
flash.events::EventDispatcher/dispatchEvent [no source]
flash.events::EventDispatcher/dispatchEventFunction [no source]
flash.events::EventDispatcher/dispatchEvent [no source]
mx.data::DataMessageCache/checkCommitRequired
mx.data::DataMessageCache/removeMessage
mx.data::ConcreteDataService/internalReleaseItem
mx.data::ConcreteDataService/http://www.adobe.com/2006/flex/mx/internal:\
:releaseDataList
mx.data::ConcreteDataService/http://www.adobe.com/2006/flex/mx/internal:\
:releaseAssociations
mx.data::ConcreteDataService/http://www.adobe.com/2006/flex/mx/internal:\
:releaseItemIfNoDataListReferences
mx.data::DataList/removeItemAt
mx.collections::ListCollectionView/removeItemAt
com.nv.client.model::PresentationsProxy/removeSlide
com.nv.client.mediators.views::PresentationMapMediator/deleteSlideHandle\
r
flash.events::EventDispatcher/dispatchEventFunction [no source]
flash.events::EventDispatcher/dispatchEvent [no source]
mx.core::UIComponent/dispatchEvent
com.nv.client.view.presentations::PresentationTableSlideCell/deleteSlide
com.nv.client.view.presentations::PresentationTableSlideCell/menuHandler
flash.events::EventDispatcher/dispatchEventFunction [no source]
flash.events::EventDispatcher/dispatchEvent [no source]
mx.core::UIComponent/dispatchEvent
mx.controls::Menu/dispatchEvent
mx.controls::Menu/mouseUpHandler
I was able to work around this, somewhat, by doing the following:
index = myPresentation.slides.getElementIndex(mySlide);
mySlide.presentation = null;  // note this is not allowed in the DB
myPresentation.removeItemAt(index);
mySlide.presentation = myPresentation;
// do commit
This seems silly, of course, but if I remove the reference to the parent
Presentation from the Slide before removing it, then those nasty
unsubscribe/release collection operations are not triggered, and the
slide is deleted successfully.

However - IF I first delete a slide, and then attempt to add a slide, I
run into a new problem, in that the client for some reason injects the
primary key value of the DELETED slide into the upbound "create"
opeartion for the NEW slide.

So - if I delete slide with id=28, then create a new slide, the first
thing I see is a queued message for a new slide with id=0, as expected,
and I then see a message queued to update the presentation.slides
collection. However, when I commit, I see the actual message sent to the
server has changed from the queued message, and instead of id=0 for the
new slide, I now see id=28.

I am totally perplexed by this, and of course I suppose it's possible
that my inhertance scheme is confusing something somewhere, and I'd hate
to think that after investing the last month of my time getting past
various other idiosyncrasies of Flex LCDS, that I'd have to  rewrite
everything using RemoteObjects or some other solution.

Any information would be greatly appreciated, and I am happy to provide 
many more gory details as necessary.

Thanks in advance!

Greg

Reply via email to