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
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.
@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.
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?
Sorry, a typo with the RemoteClass tag. It should say [RemoteClass(alias="com.orion.query.impl.PagedArrayList")] which is my implementation.
Any thoughts?