I've been working with Hibernate for some time now, and I'm pretty familiar with working with it. My main focus with using Hibernate is to use it as a serverside ORM solution for a Flash Player frontend developed in AS3. This has posed a very large amount of problems due to the inner workings of Hibernate and mostly how Hibernate manages collections. In order to get to the questions I want to ask, I'll have to explain how getting AMF (AS3's serialized data) to Java and how one can implement sharing entities across the wire between a JEE server and a Flash Player/AIR client.
AMF, which stands for Action Message Format, is a lightweight, compressed binary format which allows for native AS3 types (eg: String, int, uint, Number, Date, Array) to be "mobilized" and sent outside of the confines of Flash Player. There are numerous projects that implement the AMF protocol for working with Flash Player data-types as well as handling Flash Player remote method invocations.
One of these platforms, which I use every day, is Red5. Red5 is an open-source, Java implementation of a realtime data/media server for Flash. Red5 implements the RTMP protocol to allow Flash to connect on a persistent connection to eliminate HTTP-like pings back and forth from server to client and vice-versa. I can invoke a method from Red5 on a client and the server will not have to reconnect to the client, since the connection is persistent and not polling.
A great feature of Flash Player 9+ is that it allows for externalizable objects. This is kind of hard to explain, but basically you define a serverside Java object implementing the "
org.red5.io.amf3.IExternalizable" interface as well as a client AS3 object implementing the "
flash.utils.IExternalizable" interface. Both the serverside and clientside interfaces define two methods, "readExternal(IDataInput)" and "writeExternal(IDataOutput)". The purpose of these methods are so that you can create a serialization "schema" for your objects. The client can register a "class alias" for an object so that the server, in this case Red5, reads all objects of type X into a serverside object of type Y. This is what that method looks like:
"registerClassAlias(my.clientSide.EntityClass, "my.serverSide.EntityClass");" What this method does is it tells the server: "When you receive an object of type X, feed it into a new instance of type Y."
This makes up the AMF serialization that Flash Player provides. Red5 handles all of the (de)serialization behind the scenes luckily, so that externalized classes can be mapped quickly from client to server.
There are a few discrepancies, however. One of the big ones is working with collections. Flash Player 9, at the time of this writing, doesn't support typed collections (There is a new Vector<?> type, and it's ok but it's only available in Flash Player 10, and I'm stuck in 9 for the time being), it only supports an Array type. An AMF Array is simply an untyped collection of values. This makes serialization kind of tricky. It can still be done, but you have to be very careful to not violate Java's typed collections rules. Basically, the workaround is this:
@SuppressWarnings("unchecked")
public void readExternal(IDataInput input) {
this.myCollection = (ArrayList<MyType>)input.readObject();
}
So, all in all, you can get AMF data to Java with little to no problems via Red5's AMF support.
Now, let's talk about Hibernate.
I have worked A LOT with AMF and Hibernate, and the one remarkably difficult thing to master is working with collections. Talk about DetachedEntityExceptions galore. The problem with working with collections is that Hibernate uses its own List, Set, and Map implementations which depend on being attached to a session object. Red5, by default, deserializes AMF arrays into ArrayList objects. So if I send a User object across the wire to Red5 and ask Hibernate to update it (session.update(user)) and it has a collection as one of its properties, it will throw errors, guaranteed. I have had to implement a ton of ridiculous stuff in order to counter this. It was only recently that the real problem was revealed to me late one night at home. It struck me like a brick in the back of the head.
HIBERNATE RELIES ON ITS OWN COLLECTION IMPLEMENTATIONS!!! At last it made sense! Anyway, this basically eliminates lazy-fetching on the serverside for me. If I don't make every association fetch eagerly, I get a lot of errors. First, I can't write collections to the output stream correctly. They throw exceptions telling me that "there is no session!" And for good reason! In order to make sure I'm doing the right thing, I explicitly force sessions to close, so as to not leave them floating in space. The entities are usually always serialized last, so I am forced to close my session before returning the results to Flash, but that of course leaves my collections all screwed up.
So finally, I can get to my question. Is there a way to workaround this? Is there a way for me to force all collections to be eagerly fetched without having to declare it on every one of my entities? I'm using Hibernate Annotations. Is there any other better way of doing this?
Also, if anyone has any ideas on this, they would be greatly appreciated. I'm looking to build a strong framework to handle entities across Red5, Hibernate, and Flash.