Java 5.0 introduced typesafe enums which are a special type of class. enums in other languages are typically just an ordered set of properties, however, Java enums allow custom behaviors and logic to be added through constructors, fields and methods.
FDS is based on JDK 1.4.2 and does not natively support enums. ActionScript 3 does not have the concept of enums either. To FDS, an enum class definition looks like a normal class. As such, only public fields and public bean methods with get/set accessors are seen as properties.
An enum can be written to capture the selected value by making the class look like a normal value Object.
public enum FruitEnum
this.value = value;
public String value;
While this doesn’t provide round trip support for enums, it does allow Java to ActionScript conversions of enums.
I started a blog to document solutions to questions that I found myself frequently answering on the Flex forums. So the first topic up for discussion is using custom serialization with value objects in RemoteObject. This solution takes advantage of the ActionScript 3 API flash.utils.IExternalizable which is compatible with Java’s java.io.IExternalizable API. By implementing these interfaces on the client and server your value objects can take control of their serialization and customize what data is sent over the wire.
A common use case for using externalizable classes is to include read-only properties in serialization. While there are other approaches to achieve this for server code, there aren’t many approaches available for client code. The server uses the Java Beans API when serializing classes so one could change their value objects to implement java.beans.BeanInfo to customize introspection, however there isn’t an equivalent for this in ActionScript. This may be fine if data is not editable on the client – but many applications involve data manipulation so read-only information needs to be transmitted to maintain the idenity and/or state of an instance. A simpler, brute-force approach might be to track when a setter has been called and throw an error if it is called again – but the fact that your value object had read-only properties wouldn’t be obvious from your API.
So, for an elegant solution that works for both the client and server we are left with the option of making our classes externalizable for two-way custom serialization. Thankfully this is relatively straight-forward. The client ActionScript class simply implements flash.utils.IExternalizable. This API requires two methods readExternal() and writeExternal() which take flash.utils.IDataInput and flash.utils.IDataOutput streams respectively. The implementations of these methods mirror the server Java class, which implements java.io.Externalizable – also with two methods readExternal() and writeExternal() taking java.io.ObjectInput and java.io.ObjectOutput streams respectively.
While the IDataInput and IDataOutput classes let you design your own protocol and write fundamental data types such as byte, int, and UTF-8 encoded Strings, most implementations will take advantage of the readObject() and writeObject() methods respectively as these use AMF 3 to efficiently deserialize and serialize ActionScript objects. (Remember that AMF 3 allows: (a) objects to be sent by reference to avoid redundant instances from being serialized, to retain object relationships and to handle cyclical references, (b) object traits to be sent so that the description of a type is only sent once rather than them repeated for each instance, and (c) reoccuring strings can be sent by reference to again avoid redundant information from being sent). One may even decide to omit property names altogether in their externalizable classes’ custom serialization code and rely on a fixed order to send just the property values.
To see a code example, check out externalizable.zip. While this example focuses on serializing read-only properties there may be many other usages for custom serialization such as omitting properties, avoiding redundant serialization of information or including properties from custom namespaces.