Serialization of Custom Collections for Flex Data Services

In my current project, we have a custom collection on the Java side that is supposed to be sent via LCDS to the Flex client. When we began testing, however, we found that the collection was not being passed, only the properties of “standard” Java types were (e.g. String, int). It seems that if LCDS does not know how to handle an object, it simply ignores it and does not include it in the serialization process. This was the case here, LCDS did not understand how to serialize our custom collection and simply did not include it in the transfer.

For example, in the model code below, when an instance of MyListKeeper is serialized and sent to the Flex client, only the name property is included, not myList.

     public class CustomList
         extends ArrayList<Foo>
         implements List<Foo>, Serializable
     {
         // constructors
         // extension methods, e.g.
         public Bar getFirstBar() { ... }
     }

     public class MyListKeeper
         implements Serializable
     {
         private CustomList myList;
         private String name;

         // getters & setters
     }

We were able to solve this by writing custom serialization methods (via the java.io.Externalizable interface) for both the collection and the class that contains a reference to it. In the code below, notice that our classes now implement Externalizable (a subclass of Serializable).

     public class CustomList
         extends ArrayList<Foo>
         implements List<Foo>, Externalizable
     {
         // as in the previous example ...

         public void writeExternal(ObjectOutput out)
             throws IOException
         {
             // externalizes the list - LCDS knows how to handle an ArrayList
             out.writeObject(new ArrayList(this));
         }

         public void readExternal(ObjectInput in)
             throws IOException, ClassNotFoundException
         {
             // start by clearing the current collection
             this.clear();
             // now read in the new list and store it
             this.addAll((List)in.readObject());
         }
     }

     public class MyListKeeper
         implements Externalizable
     {
         // as in the previous example ...

         public void writeExternal(ObjectOutput out)
             throws IOException
         {
             out.writeUTF(this.name);
             out.writeObject(this.myList);
         }

         public void readExternal(ObjectInput in)
             throws IOException, ClassNotFoundException
         {
             this.name  = in.readUTF();
             // the following may not be 100% correct, feel free to correct me
             this.myList = (CustomList)this.readObject();
         }
     }

Finally, we need to mirror our custom serialization on the Flex side. In ActionScript, classes with custom serialization implement the flash.utils.IExternalizable interface.

    [Managed]
    [RemoteClass(alias="CustomList")]
    public class CustomList
        implements IExternalizable
    {
        public var list : IList;

        // other methods, etc

        public function readExternal(input : IDataInput) : void
        {
            this.list = ArrayCollection(input.readObject());
        }

        public function writeExternal(output : IDataOutput) : void
        {
            output.writeObject(this.list);
        }
    }

    [Managed]
    [RemoteClass(alias="MyListKeeper")]
    public class MyListKeeper
        implements IExternalizable
    {
        public var myList : CustomList;
        public var name : String;

        // other methods, etc

        public function readExternal(input : IDataInput) : void
        {
            this.name = input.readUTF();
            // the list itself is received as an ArrayCollection, so we just assign it directly
            this.myList.list = input.readObject();
        }

        public function writeExternal(output : IDataOutput) : void
        {
            output.writeUTF(this.name);
            output.writeObject(this.myList);
        }
    }

Adobe has a nice overview of custom serialization as well, but focuses primarily on utilizing it to control which parameters are serialized.

References

About these ads

4 Comments on “Serialization of Custom Collections for Flex Data Services”

  1. ru55e77 says:

    I’m sure this is the answer to my BlazeDS ArrayList nightmare!! If only I could understand a little more to be able to implement the example into my own app.

    Externalizing an object no problem!

    Externalizing an ArrayList of custom objects problem!

    Is there anyway you could expand the example so I can understand better?
    Thanks in advance.

  2. josh says:

    @ru55e77 – can you be any more specific about your problem? My example above is fairly complete and should get you almost all the way there.

  3. Joao says:

    Hello Josh,

    I realize this is an old post, but I ran into this problem and I can’t my custom collection serialization. I have a collection that has 1 extra property.

    Here is a short implementation.

    [RemoteClass(alias="com.orion.query.IPagedList")]
    public class PagedArrayList implements IExternalizable{

    public var first:Number;

    I’ve done exactly how you specified on my java back end but I still keep getting a ArrayCollection back on flex. The items inside of the collection (Country objects) are being parsed correctly, except for the root custom collection.

    I’m using BlazeDS.

    The only thing that I’ve done differently from your sample is not using the [Managed]

    For some reason, it gives me the following error:

    Severity and Description Path Resource Location Creation Time Id
    1172: Definition mx.data:IManaged could not be found. amf/src PagedArrayList.as line 1 1226547573515 9952
    1172: Definition mx.data:IManaged could not be found. amf/src PagedArrayList.as line 1 1226547573515 9954
    1172: Definition mx.data.utils:Managed could not be found. amf/src PagedArrayList.as line 1 1226547573515 9953
    1172: Definition mx.data.utils:Managed could not be found. amf/src PagedArrayList.as line 1 1226547573515 9955

    Could you point me to the right direction?

  4. Joao says:

    Sorry, a typo with the RemoteClass tag. It should say [RemoteClass(alias="com.orion.query.impl.PagedArrayList")] which is my implementation.

    Any thoughts?

Follow

Get every new post delivered to your Inbox.

Join 25 other followers