0 Replies Latest reply on Mar 12, 2013 1:21 PM by joe_valenzuela

    Error #1034 Type Coercion fail with registerClassAlias and nested Vectors

    joe_valenzuela

      I'm attempting to use flash.net.registerClassAlias and ByteArray.writeObject in order to serialize/deserialize data with static type information.  It works as you'd expect in the general case but I've run into problems with some nested Vectors that I don't understand.  Hopefully someone can point out if I'm just missing something.

       

      For what I understand, we must register both the scalar types and a one-deep specification of a Vector for that scalar type in order to use nested Vectors.  For example:

       

                  flash.net.registerClassAlias("TestStructureInner", TestStructureInner);

                  flash.net.registerClassAlias("VectorTestInner", Vector.<TestStructureInner> as Class);

       

      This should allow us to read/write objects of type TestStructureInner, Vector.<TestStructureInner>, and Vector.<Vector.<TestStructureInner>> into ByteArrays.  And in general it seems to work.

       

      Attached though is a simplified test case that fails, however.  The first time we deserialize the data it works.  The subsequent time, however, we encounter the following runtime error #1034.

       

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fcb9 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fbc9 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fdd1 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fce1 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fbf1 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fec1 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fad9 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304fa61 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304f9e9 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

          TypeError: Error #1034: Type Coercion failed: cannot convert __AS3__.vec::Vector.<Object>@304f971 to __AS3__.vec.Vector.<__AS3__.vec::Vector.<Test0.as$30::TestStructureInner>>.

       

      Re-registering the class aliases again via flash.net.registerClassAlias works in this test case but isn't 100% for our actual application (I'm reticent to even mention it but it seems relevant).  Is there a step I'm missing here?  Any light shed would be appreciated.

       

      // mxmlc -debug Test0.as

      package

      {

          import Base64; // http://code.google.com/p/jpauclair-blog/source/browse/trunk/Experiment/Base64/src/Base64.a s

         

          import flash.net.registerClassAlias;

          import flash.events.Event;

          import flash.utils.ByteArray;

       

       

          import flash.display.Sprite;

          import flash.display.Stage;

       

       

          import flash.system.System;

       

       

          public class Test0 extends Sprite

          {

              static private const OPERATION_SERIALIZE:uint = 0;

              static private const OPERATION_DESERIALIZE_AND_FAIL:uint = 1;

              static private const OPERATION_DESERIALIZE_AND_SUCCEED:uint = 2;

             

              static private var staticStage:Stage;

              private var bar:Vector.<TestStructure>;

       

       

      /*************************************************************

      * common functions

      **************************************************************/

              static private function registerClassAliases():void

              {

                  flash.net.registerClassAlias("TestStructureInner", TestStructureInner);

                  flash.net.registerClassAlias("VectorTestInner", Vector.<TestStructureInner> as Class);

                  flash.net.registerClassAlias("TestStructure", TestStructure);

              }

             

              static public function staticDeserialize():Object

              {

                  var byteArray:ByteArray = Base64.decode("EBUAG1Rlc3RTdHJ1Y3R1cmUKEwAHZm9vEAEAH1ZlY3RvclRlc3RJbm5lcgoBEAEABAoBEAEABA oBEAEABAoBEAEABAoBEAEABAoBEAEABAoBEAEABAoBEAEABAoBEAEABA==");

                  byteArray.position = 0;

                  return byteArray.readObject();

              }      

       

       

              public function Test0():void

              {

                  registerClassAliases();

                 

                  // Switching operation between the constants demonstrates failure/success in a couple of different ways.

                  // SERIALIZE is just used to prepare the base64 string for subsequent tests.

                 

                  var operation:int = OPERATION_SERIALIZE_AND_FAIL;

                  if (operation == OPERATION_SERIALIZE)

                  {

                      trace("Serializing");

                     

                      // outputs base64 string for subsequent tests

                      serialize();

                  }

                  else if (operation == OPERATION_DESERIALIZE_AND_FAIL)

                  {

                      trace("Fail case");

                     

                      // perform successful one deserialization, then one failing one.

                      deserializeOnceThenFail();

                  }

                  else if (operation == OPERATION_DESERIALIZE_AND_SUCCEED)

                  {

                      trace("Success via re-registration");

                     

                      // perform successful one deserialization, then another successful one.

                      deserializeOnceThenSucceed();

                  }

              }

       

       

      /*************************************************************

      * serialize

      **************************************************************/

              // outputs base64 string we use for subsequent tests.

              private function serialize():void

              {

                  var baz:Vector.<TestStructure> = new Vector.<TestStructure>;

                  for (var i:int=0; i<10; ++i)

                      baz.push(new TestStructure);

                 

                  var byteArray:ByteArray = new ByteArray;

                  byteArray.writeObject(baz);

                  trace(Base64.encode(byteArray));

              }

       

       

      /*************************************************************

      * deserializeOnceThenFail

      **************************************************************/

       

       

              // perform successful one deserialization, then one failing one.

              public function deserializeOnceThenFail():void

              {

                  // save stage

                  staticStage = stage;

                 

                  // the first deserialize will proceed without error.

                  staticDeserialize();

                  trace("Successful deserialize");

                 

                  // add an event listener in order to invoke error on subsequent frame

                  stage.addEventListener(Event.ENTER_FRAME, doEnterFrameOnceThenFail);

              }

             

              // remove event listener and invoke again.

              static private function doEnterFrameOnceThenFail(e:Event):void

              {

                  staticStage.removeEventListener(Event.ENTER_FRAME, doEnterFrameOnceThenFail);

                  staticDeserialize();

                  trace("unsuccessful deserialize2");

              }

       

       

      /*************************************************************

      * deserializeOnceThenSucceed

      *

      * Here, we re-call flash.net.registerClassAlias on all our class types when running.

      **************************************************************/

              // perform successful one deserialization, then one failing one.

              public function deserializeOnceThenSucceed():void

              {

                  // save stage

                  staticStage = stage;

                 

                  // the first deserialize will proceed without error.

                  staticDeserialize();

                  trace("Successful deserialize");

                 

                  // add an event listener in order to invoke error on subsequent frame

                  stage.addEventListener(Event.ENTER_FRAME, doEnterFrameOnceThenSucceed);

              }

       

       

              // remove event listener and invoke again.

              static private function doEnterFrameOnceThenSucceed(e:Event):void

              {

                  staticStage.removeEventListener(Event.ENTER_FRAME, doEnterFrameOnceThenSucceed);

                 

                  registerClassAliases();

                  staticDeserialize();

                  trace("successful deserialize2");

              }

          }

      }

       

       

      internal class TestStructureInner

      {

                public var value:int;

      }

       

       

      internal class TestStructure

      {

                public var foo:Vector.<Vector.<TestStructureInner>> = new Vector.<Vector.<TestStructureInner>>;

      }