4 Replies Latest reply on Jul 27, 2006 2:54 PM by Bill White

    StackOverFlow with FDS

    Bill White
      I have an application using Flex Data Services running from Tomcat. I've created Java domain objects as well as corresponding ActionScript objects and everything seems to work fine when I pull the Java objects to the client using Data Management Services combined with the Java Adapter and my custom FlexFactory and a Spring backend. The objects being used have several associations: (ie. Student object references multiple Course objects which each reference a Teacher object, etc). With less than 500 rows in each table (Users, Teachers, Students, Courses, Subjects, etc) things work fine.

      However, when I put a significant number of rows of data into some of the tables all of a sudden I get an exception on the server. For example, if I have 100 Teacher rows in my database and those reference 500 Courses and those reference 1000 Students, things are fine. But if I put in another 5000 Students, which are also referenced by these Courses, I get this:

      Throwable in RtmpReader thread: java.lang.StackOverflowError
      java.lang.StackOverflowError
      at java.util.HashMap$KeySet.iterator(HashMap.java:867)
      at java.util.HashSet.iterator(HashSet.java:154)
      at java.util.AbstractCollection.toArray(AbstractCollection.java:173)
      at org.hibernate.collection.PersistentSet.toArray(PersistentSet.java:155)
      at java.util.ArrayList.<init>(ArrayList.java:136)
      at flex.messaging.io.ArrayCollection.<init>(ArrayCollection.java:44)
      at flex.messaging.io.amf.Amf3Output.writeArrayCollection(Amf3Output.java:407)
      at flex.messaging.io.amf.Amf3Output.writeObject(Amf3Output.java:147)
      at flex.messaging.io.amf.Amf3Output.writeObjectProperty(Amf3Output.java:215)
      at flex.messaging.io.amf.Amf3Output.writePropertyProxy(Amf3Output.java:495)
      at flex.messaging.io.amf.Amf3Output.writeCustomObject(Amf3Output.java:467)
      at flex.messaging.io.amf.Amf3Output.writeObject(Amf3Output.java:165)
      at flex.messaging.io.amf.Amf3Output.writeObjectArray(Amf3Output.java:730)
      at flex.messaging.io.amf.Amf3Output.writeAMFArray(Amf3Output.java:386)
      at flex.messaging.io.amf.Amf3Output.writeObject(Amf3Output.java:151)
      at flex.messaging.io.ArrayCollection.writeExternal(ArrayCollection.java:97)
      at flex.messaging.io.amf.Amf3Output.writePropertyProxy(Amf3Output.java:485)
      ...........(continues this loop for several more lines).............

      One the front end, the client appears to either hang or timeout with this:

      [RPC Fault faultString="Channel disconnected" faultCode="Client.Error.DeliveryInDoubt" faultDetail="Channel disconnected before an acknolwedgement was received"]
      at mx.data::ConcreteDataService/ http://www.adobe.com/2006/flex/mx/internal::dispatchFaultEvent()
      at ::DataListRequestResponder/fault()
      at mx.rpc::AsyncRequest/fault()
      at ::NetConnectionMessageResponder/NetConnectionChannel.as$37:NetConnectionMessageResponder: :channelDisconnectHandler()
      at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction()
      at flash.events::EventDispatcher/dispatchEvent()
      at mx.messaging::Channel/mx.messaging:Channel::disconnectSuccess()
      at mx.messaging.channels::RTMPChannel/mx.messaging.channels:RTMPChannel::statusHandler()

      I'm not sure what the cause is, but I think it may be related to one of these things:

      Possible Cause 1:
      The additional rows of data that I'm using to fill my database have some sort of flaw that is creating a circular reference among the objects being used by FDS.

      Possible Cause 2:
      I do not have the settings correct in FDS concerning lazy-initialization, caching, or some other property that would prevent the data management service from getting stuck in a loop, or trying to basically create one object in the object graph for each row in the database. Obviously if I have 20,000 rows in a table, I do not want the FDS to create 20,000 in-memory objects in the object graph that it uses to supply data to the clients, right?

      Possible Cause 3:
      I have not setup the fill or sync or whatever methods in my Assemblers correctly that are used by the clients to get data.

      Any ideas on where this error might be coming from?
        • 1. Re: StackOverFlow with FDS
          sanclementetech Level 1
          For your Assember definition in your applicationContext.xml do you specfy singleton="true" ?

          Something like:
          [code]
          <bean id="AddressAssembler" class="com.gcloans.dao.flex.AddressAssembler" singleton="true">
          <property name="bean">
          <ref bean="AddressDAO" />
          </property>
          <property name="id">
          <value>id</value>
          </property>
          </bean>
          [/code]
          • 2. Re: StackOverFlow with FDS
            Bill White Level 1
            Thanks for the response. Yes, I have singleton="true" for my applicationContext.xml that is used by my Spring Flex Factory.

            When I run the with the debug log level, it appears to me that a simple request for all of the User objects (there are about 70 rows in the users table) is resulting in FDS trying to load all sorts of related objects. This leads me to believe that I've misconfigured something somewhere. However, if I set all of my one-to-many and many-to-one associations to lazy='true', I still get the error and the debug log still shows FDS loading a lot more than the 70 objects I would expect.

            I wonder if I missed something that is needed to support lazy inits when I wrote my Java Assembler class? I have the standard getItem(Map) method implemented that the docs said I need for init support. Is there something else? (I'm assuming the lack of proper lazy inits is why I'm getting the stackoverflows when I load by DB with lots of data).

            Thanks
            • 3. Re: StackOverFlow with FDS
              Bill White Level 1
              Update: After looking further into the debug output on the server, it really does appear that FDS is trying to load every single object instance in all of the referenced properties of my objects. For example, on the Java side, I have a Teacher object which has a school property that references a School object. This School object has a property named Teachers that is a HashSet. This is a transient property that Hibernate populates for me at runtime, allowing me to get all the Teachers for a given School. It appears that this may be screwing up FDS because it is trying to load all the objects into memory at once. Any ideas? Jeff you seem to know this stuff best; have you come across this yet?
              • 4. Re: StackOverFlow with FDS
                Bill White Level 1
                Yet another update: I went into my Java code and commented out the HashSets that are populated by Hibernate that. Ex: Each Teacher object has a School property. In the School object, I define a HashSet named Teachers and Hibernate will populate that at runtime for me so I can get all the Teachers in a School. Once I disabled this, the StackOverFlows in FDS stopped. The problem is that this Hibernate feature is very nice to have on the backend.

                Does anyone know how to 'suppress' certain properties or attributes in my Java classes to FDS will not try to populated them when it sends them to the client? I was hoping that by simply not defining the corresponding property on the Managed Remote actionscript class that it would just ignore them but it doesn't. Any ideas?