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