This content has been marked as final. Show 7 replies
Do you have an associated data service destination for the Loan entity type that is also marked as lazy? If this property isn't marked as lazy in the data service config a deep traversal is done because we don't maintain long running Hibernate sessions.
When you state that the session is getting blasted what exactly are you experiencing?
Thanks for the reply. I have tried a number of things, including setting the lazy="true" on all of the associated data service destinations. I have even gone as far as commenting out my sets for each definition - my current config. The problem I am having is I am getting one of the various Lazy Load failures which refer to a none existant session.
Aug 22, 2006 4:54:02 PM org.hibernate.LazyInitializationException <init>
SEVERE: could not initialize proxy - the owning Session was closed
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.jav a:84)
at flex.messaging.util.ToStringPrettyPrinter.prettifyComplexType(ToStringPrettyPrinter.java: 82)
at flex.messaging.util.ToStringPrettyPrinter.prettifyComplexType(ToStringPrettyPrinter.java: 163)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.j ava:252)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Htt p11BaseProtocol.java:664)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.ja va:80)
From what I can tell on the web I need to set up an OpenSessionInViewInterceptor, I am just not sure how to properly.
I think the issue is with our debug logging code (Message.*). We have some "pretty printer" logic which is trying to recursively dump out the state of any arguments and return values to the RemoteObject call. For your Hibernate entity object, this means it is trying to access the state of some properties which have not been initialized yet because they are lazily loaded. Since this is all happening after the remote object call has returned, the session is closed.
If you can modify the code of your hibernate entity class to add your own custom toString method, it will skip this recursive pretty printer logic. Just makes ure your toString does not fetch the state of properties that have not been loaded (I usually have mine print the ids of the referenced objects for single valued relationships and you probably want to just forgo printing anything for collections since hibernate will not have fetched any state for them).
Sorry for the problems... this pretty printer thing was added late in the game. I had kind of wanted an option to turn it on so it is off by default but we did not get that in.
Thanks for the info. I have been banging my head against the wall on this one. I will try and see what happens. I will post my result here. Thankfully I had added my own abstraction layer so this should be pretty easy.
That does not appear to be the problem or resolution to the problem. My toString method never even gets called.
My apologies, I think I was off by one-level in my understanding of the problem. From looking at the stack trace more carefully, I believe the issue is that you do a query on hibernate to return a Contact instance. It is not that this instance has properties which point to objects which are not initialized, but that it is not initialized itself. When the debug logging tries to fetch the Contact instance to call its toString method, it is failing to retrieve the "real" populated Contact instance.
This problem is more structural since even if you turn off debugging, the state of that object has not been fetched so this would just move the error elsewhere. I think that in this case, you just have to initialize the Contact instance in your RemoteObject before returning it. Otherwise, it is just a hollow shell which only has the "id" of the Contact - there is no data there yet. This might be a simple matter of trying to fetch some property of the Contact before it gets returned. There is also the "Hibernate.initialize(<your-obj>)" method which you could try as well to do this more generically.
The other problem I think you'll run into though is that the class name of the returned object is not what you'd expect. Instead of it being:
it is actually:
This is hibernate's generated class wrapper which fetches the state of the real contact the first time you try to access it. Unfortunately this wrapper class messes up the RemoteClass mapping if you are trying to map this to a concrete type in ActionScript. It may also mess up the serialization even if you are expecting that to come over as a weak typed "Object" in ActionScript (I believe it at least has an extra "implementation" property). If you do run into those problems, you could try using the solution we added for "Data Management Services". You'd have to simply add this line to some code which gets initialized before your remote object gets returned:
PropertyProxyRegistry.getRegistry().register(HibernateProxy.class, new HibernatePropertyProxy());
This basically means that whenever AMF encounters an object which implements the "HibernateProxy" interface, it uses this HibernatePropertyProxy class to help serialize that object. Instead of serializing the CGLIB wrapper class, it gets the implementation class from underneath that and serializes that object. This does assume that object has already had its public properties initialized so make sure to access some property of your Contact instance before closing the hibernate session.
Finally, I believe it is also possible to configure hibernate so it does not use CGLIB generated wrappers if this is getting too complicated. I hope this helps,
Thanks Jeff -
What I ended up doing was to set the lazy="true" on all my many-to-one and one-to-one definitions. I erroroniously thought that the problem was with my set definitions. If I get to spot, and I am sure I will, where I need to retrieve that deep relationship, I will try what you mentioned.