Archive for February, 2008

Flex: ObjectUtil.copy() throws errors for classes with custom namespace properties.

Tuesday, February 26th, 2008

The easiest way to clone an instance of a class in Flex is to use the inbuilt ObjectUtil.copy() . This function serialises the entire object into an array of bytes and then deserialises it back into a completely new instance of that class. All that needs to be added to a class to ensure that it is correctly deserialised is to include the [RemoteClass] metadata tag above the class definition.

Rather than explaining it all here, I suggest you have a read of Darron Schall’s explanation of it here.

I’ve used this method for cloning custom objects in several projects without issue, but when I implemented this functionality in a current project, everytime I called ObjectUtil.copy() I received the following error:

ArgumentError: Error #2004: One of the parameters is invalid.
    at flash.utils::ByteArray/writeObject()

There is only one parameter for ObjectUtil.copy() – the object to be copied, so obviously there was something in one of my classes that didn’t like being deserialised. Unfortunately by this time there was already a reasonable inheritance chain going in my classes, and eventually I had to start stripping bits out of my classes (and superclasses) until the error went away.

It turns out that the culprit was a custom namespace property in my superclass. Whenever the namespace was defined, ByteArray.writeObject() fails to deserialise the byte array, and the copy fails.

package
{
    [RemoteClass]
    public class Example
    {
        public var ns:Namespace = new Namespace("http://www.misprintt.net");

        public function Example()
        {

        }
    }
}

Cloning an instance of this class will always throw an error:

var example:Example();= new Example();
var o:Object = ObjectUtil.copy(example);

Luckily the solution is also describe in Darron’s post. While he doesn’t indentify what problems he was having, he explains how he used the [Transient] metadata tag to avoid issues with ObjectUtil.copy().

So now that the culprit has been identified, it is just a matter of adding the [Transient] metadata tag to avoid the namespace being serialised in the first place.

package
{
    [RemoteClass]
    public class Example
    {
	[Transient]
        public var ns:Namespace = new Namespace("http://www.misprintt.net");

        public function Example()
        {

        }
    }
}

Anyway, hopefully this saves some time for those trying to decipher yet another one of those vague flash player errors :)