From an AS3 Flash app, I'm trying to set a SharedObject to an instance of a custom class I've created. From what I can tell, as soon as I call sharedObject.setProperty("propertyName", myCustomClass)
Red5 throws "Error loading class" and then disconnects the client because decoding failed.
It seems that plenty of other people have had similar problems, but everything I've found is about creating SharedObjects on the server-side. I'm having trouble finding much about creating the SharedObject on the client-side (in the Flash app). I'm just using the included "live" Red5 app out of the box.
Here's the actual error I see in the Red5 logs...
[ERROR] [NioProcessor-7] org.red5.io.amf.Input - Error loading class: com.striparcade.API.Player
[ERROR] [NioProcessor-7] org.red5.server.net.rtmp.codec.RTMPProtocolDecoder - Error decoding buffer
com.striparcade.API.Player
is the custom class in question. This class implements IExternalizable, includes writeExternal() and readExternal() methods, and a call to registerClassAlias(). It seems to serialize just fine.
Surely I don't have to recreate this class in the Red5 app as well? Shouldn't Red5 just take the data and pass it along to the other clients when needed? Any idea what I'm missing?
Using Red5 1.0.1, btw. I see that a lot of bugs regarding AMF3 encoding were fixed around version .7. Also, just testing locally on a Windows 7 machine right now.
I've solved the problem, but I'm no Red5 expert so take the following explanation with a grain of salt and correct me if I'm wrong... It seems that either Red5, or the "live" application included with Red5, attempts to instantiate whatever objects it receives via a SharedObject on the server-side. So, I believe you would actually need to replicate in Java whatever CustomClasses you're sharing from the client-side in AS3. Seems really odd to me, but that's all I can gather, and that would explain the Red5 error logs.
This was unacceptable for my needs, as I plan to have other programmers take my client-side code as an API and abstract away the server-side details... so recreating whatever classes they come up with on the server isn't really feasible.
An easy workaround is to "wrap" whatever you're sharing in a ByteArray and then unwrap it when you retrieve it. Red5 doesn't seem to complain about ByteArrays, and happily broadcasts them out to the client with no knowledge of what's inside. Here are a couple functions I whipped up to handle this...
private function setRed5Property(propertyName:String, data:Object):void
{
var dataBytes:ByteArray = new ByteArray();
dataBytes.writeObject(data);
_red5SharedObject.setProperty(propertyName, dataBytes);
_red5SharedObject.setDirty(propertyName);
}
private function getRed5Property(propertyName:String):Object
{
var dataBytes:ByteArray = new ByteArray();
dataBytes.writeBytes(_red5SharedObject.data[propertyName]);
dataBytes.position = 0;
return dataBytes.readObject() as Object;
}