0 Replies Latest reply on Apr 1, 2008 2:09 PM by gordogre

    unexpected "unsubscribe" and "release collection" operations on removeItemAt

    gordogre Level 1
      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/deleteSlideHandler
      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