Sometimes you need to build a custom remoting protocol layer in Flash. I had an XML-based one but it was slow. Aside from verbosity, it was slow to process on both sides because XML must be parsed as a whole (stopping is possible through streaming API but not skipping selectively). That costs time and space which one can't afford in use cases like mine. Also, it's rather awkward to add encryption and compression layers transparently on top of XML, awkwardness stemming from having to use HTTP headers to get the job done.
In my use case, most of the payload was intended to opaque to the server because the server acts only as a distributor. Server just reads what's on outside of the box, saves a time limited copy for latecomers then forwards the box to destination clients without knowing what's in the box. This means I can compress the content if it's big enough. I can also encrypt it using a symmetric key then encrypt the key for each intended audience with their respective public key. Each step adds only a sticker ("Inflammable!") on the box. Archiving is done by a server-side subscriber that saves anything with a specific sticker.
I suppose I could have used Flash's built-in support for remoting but it was tedious to figure it out enough for me to use. Breaking things down to headers and bodies is easy but figuring out headers I need to support and handling body and result the way Flash expects is non-trivial and unnecessary in my case.
So I built my own and it's looking fast and flexible enough for my app. Here are some notes from my workbench:
- Java Preferred – Adobe's server teams use Java so a lot of Java leaked into serialization API and encoding format. You'll find it somewhat easier to build the server-end in Java.
- writeObject saves space – most of IDataInput and IDataOutput methods writes out data as-is. writeInt will write out 4 bytes. To write out in compact AMF3 format, use only writeObject. Rest of the methods will be necessary if you are using non-Flash object serialization like that of Java's built-in object serialization.*
- Use registerClassAlias – [RemoteClass(alias=…)] trick seems to work only when Flex classes are used.
- ActionScript is single-threaded – a fact that both simplifies and complicates. Very forgettable too.
- ActionScript is not Flash – ActionScript runs inside Flash but the two are not the same. For example, Flash may have other threads than the one ActionScript is on.
-
Flex is not Flash – Flex adds a boatfull of ActionScript classes, source of much but not all of which is included in Flex SDK. Each Flex class you use will add byte codes to the output Flash movie and class dependency will often result in surprising size increases.
- Watch your weight – A minimal Flex app weights around 100K. A few more lines and, wham, your app is 200K. If you don't use any Flex classes, you only have to worry about embeded resources. My custom remoting fancy app with encryption and compression is about 40K and loads seemingly instantly.
- One problem with using IExternalizable is that AMF3 doesn't offer no hint as to where externalized object data ends because a matching Java class is expected 'know' internally. You'll have to write ObjectInputStream equivalent for AMF3 or, if your AS3 class hierarchy is simple, add the hint yourself. I do this by adding an intermediate serialization step using an interface like this:
public interface Shareable {function readAMF(input:Array);
function writeAMF(output:Array);
}
readAMF() implementations just shift() values out in turn and writeAMF() does the opposite by pushing values into the array in the same order. In writeExternal(), writeAMF is called to build an array of data across class hierarchy then it's written out together. Equivalent is done in readExternal(). This way, server-end logic gets not only simpler but need zero knowledge about client-side classes.
That's it for now. There are other Flash related funkiness I can enumerate but where is the fun in that? ;-p