Expand my Community achievements bar.

StackOverFlow with FDS

Avatar

Level 2
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?
4 Replies

Avatar

Level 3
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]

Avatar

Level 2
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

Avatar

Level 2
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?

Avatar

Level 2
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?