Custom Serialization between ActionScript and Java

July 13, 2008 – 3:32 am

There are situation when the object serialization between ActionScript and Java causes some problems in it’s default form and i’ll detail that with one simple example. Let’s say we have a movie application where users watch some movies online. At the building block for this application would stay a Movie object, a Data Transfer Object (DTO). Why DTO ? Because instances of this object will be sent back and forth between client (ActionScript) and server (Java) across the network tier. Let’s suppose the Movie object is a simple one, with id and name. The two DTO classes would look like this:

ActionScript version:

package samples.dto
{

[RemoteClass( alias="samples.dto.Movie" )] 
public class Movie
{
    private var _id:int;
    private var _name:String;
   
    public function get id():int
    {
        return _id;
    }
   
    public function set id( value:int ):void
    {
        _id = value;
    }
   
    public function get name():String
    {
        return _name;
    }
   
    public function set name( value:String ):void
    {
        _name = value;
    }
}

}

and the Java version:

package samples.dto;

public class Movie
{
    private int id;
    private String name;
   
    public int getId()
    {
        return id;
    }
    public void setId( int id )
    {
        this.id = id;
    }
    public String getName()
    {
        return name;
    }
    public void setName( String name )
    {
        this.name = name;
    }
}

In this form, sending objects between ActionScript and Java won’t cause any troubles. Now on our little movie viewer application comes another functionality. You need to list the users currently viewing each movie. One could do this in multiple different ways but lets assume a bad practice was taken: keeping the online viewers for each movie in the Movie class. So a new property “viewedBy” for example would go into the ActionScript class. So far so good but what would happen if your app is a big hit and purchased by YouTube for example ? They have hundreds and hundreds of online users watching videos. What would happen is that redundant data is sent back and forth, and data that was designed for client-side display only is sent also to the server. Hundreds and hundreds of calls to the services with Movie object instances that have hundreds and hundreds items on their “viewedBy” property. Not very handy. As you probably guessed, custom serialization can help you.

Custom serialization is about managing what properties are passed between tiers for a specific object. This is done thru IExternalizable interface on ActionScript side and Externalizable interface on Java side. The methods that the AS object need to implement are writeExternal( output:IDataOutput ) and readExternal( input:IDataInput ). IDataOutput and IDataInput interfaces have methods for writing and reading binary data to and from serialized objects. On the Java side Externalizable interface provides same functionality writeExternal( ObjectOutput output ) and readExternal( ObjectInput input ).


So on our little example we want to keep the “viewedBy” property only on client-side object. Lets go ahead and see the modifications. First we need to implement IExternalizable interface and provide the two functions:

public function writeExternal( output:IDataOutput ):void
{
    output.writeInt( id );
    output.writeUTF( name );
}
   
public function readExternal( input:IDataInput ):void
{
    id = input.readInt();
    name = input.readUTF();
}

What this does is making sure only id and name property are being sent to the server. Make sure you read the data in the same way you write it, otherwise you will have problems. On the Java side implemented interface Externalizable would add the two methods:

public void writeExternal( ObjectOutput output ) throws IOException
{
    output.writeInt( id );
    output.writeUTF( name );
}
   
public void readExternal( ObjectInput input ) throws IOException
{
    id = input.readInt();
    name = input.readUTF();
}

If only the client side class is marked as IExternalizable (not Java class too) you will get a RPC fault error something like this:

[RPC Fault faultString="Class 'samples.dto.Movie' must implement java.io.Externalizable to receive client IExternalizable instances." faultCode="Client.Message.Encoding" faultDetail="null"]
    at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::faultHandler()
    at mx.rpc::Responder/fault()
    at mx.rpc::AsyncRequest/fault()
    at NetConnectionMessageResponder/statusHandler()
    at mx.messaging::MessageResponder/status()

And that would be pretty much it. Now “viewedBy” property is not sent to every call to Java services, packages are smaller and no networking problems (really think is that simple eh?).

  1. 3 Responses to “Custom Serialization between ActionScript and Java”

  2. Great article.

    I have done a lot of remoting work in the past (AMF0), but had never known how easily this could be implemented with the interfaces. I had done lame hacks like sending a TO from Java to Flash, modifying / adding to the TO on client side, and then transforming the TO to another client-side TO class before sending back in order to only send back what I wanted to the server.

    By Aran on Jul 13, 2008

  3. hi,

    Thanks for the enlighting post,it was a great help!!
    Can you explain how do we send an object array,something like this :
    public class XXX
    {

    private var id:int;
    private var organization:String;
    private var owner:UserRecord;
    private var params:Array;
    }
    public class UserRecord
    {
    private var display_name:String;
    private var id:int;
    private var xx:Array;
    }

    When I try to pass it as an object in the Axis webservice,It receives null.
    Object is constructed at the flex end though.

    What are the available options?Any help would be appreciated.

    Thanks,

    By Rohit on Jul 13, 2008

  4. Hi Rohit,

    First of all if you use nested classes you will need all of them mapped between actionscript and java using the [RemoteClass] metadata. This will assure that custom objects like “private var owner:UserRecord” will be properly deserialized on the Java end.

    As for the arrays you can use the default serialization to send them, and they will arrive at the server side as class implementation of java.util.List interface (ex: ArrayList).

    More on the mapping between ActionScript and Java objects here

    Note that when using default serialization (not using IExternalizable functionality) you will need to mark the properties that you don’t want to send with [Transient] metadata. This achieves same functionality as described in this post, the parameter won’t be sent to the server.

    For example:

    private var _viewedBy:Array;

    [Transient]
    public function get viewedBy():Array
    {
    return _viewedBy;
    }

    Hope this helps.

    By Adrian Aioanei on Jul 14, 2008

Post a Comment