Passing typed ActionScript objects to Flex using PHP and a message queue

Last week I wrote up a few blog posts (here, here and here) about creating a Flex based dashboard that utilized message queues to pass data.  It was a really fun example to write but there was one thing I did not get to implement.  What I wanted to do was use the sales notification mechanism to pass PHP objects to Flex using the message queue.  But I could not get the unserialization mechanism to work and so I had to settle for passing a simple message that a sale had been made.

However, because you can pass typed objects back and forth between PHP and ActionScript over HTTP using Zend_Amf_Server I figured that there MUST be a way of doing it automatically.  The first thing I did was create a valueObject class called Boogers (I descend into adolescence while trying new things) and called it in ActionScript so I could see the bytes that were created.  The class Boogers had a property called “nutso” (again, adolescence) to which I assigned the value of “what?”.  The code looked something like this

1
2
3
4
5
6
7
8
9
10
var bgrs : Boogers = new Boogers;
bgrs.nutso = "what?";
var baobj : ByteArray = new ByteArray;
baobj.writeObject(bgrs);
var ints2 : String = new String();
baobj.position = 0;
for (var i : uint = 0; i < baobj.length; i++) {
  var b : uint = baobj.readByte();
  ints2 +=  b + " " ;
}

This resulted in the bytes

1
10 19 41 118 97 108 117 101 79 98 106 101 99 116 115 46 66 111 111 103 101 114 115 11 110 117 116 115 111 6 11 119 104 97 116 63

Then I wrote some PHP code that created a PHP object called valueObjects\Boogers, serialize it and then output the bytes so I could compare it with the ActionScript output.  Note  that the class name follows the same namespace definition as the ActionScript class.  I wanted to have direct 1:1 relationships between PHP and ActionScript.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace valueObjects;
$b = new Boogers();
$b->nutso = "what?";
 
$stream = new \Zend_Amf_Parse_OutputStream();
$ser = new \Zend_Amf_Parse_Amf3_Serializer($stream);
$ser->writeObject($b);
$output = (string)$stream->getStream();
 
$a = '';
for ($i = 0; $i < strlen($output); $i++) {
  $a .= ord($output[$i]) . ' ';
}
echo $a;

 

The end result were the bytes

1
19 41 118 97 108 117 101 79 98 106 101 99 116 115 92 66 111 111 103 101 114 115 11 110 117 116 115 111 6 11 119 104 97 116 63

It was missing char 10.  But I found out that you needed to do a newline character for AMF to work properly, so I just prepended it to my output

1
$output = "\n" . (string)$stream->getStream();

So the next thing I wanted to do was send it to a message queue where ActionScript could read it using Stomp.

1
2
3
$stomp = new \Zend_Queue_Adapter_Activemq(array());
$stomp->setQueue(new \Zend_Queue(array('name' => '/queue/data')));
$stomp->send($output);

I ran the code and it sent the message to the message queue.  On the ActionScript side I set up a Stomp handler like I did in my webinar demo and was able to receive the message.  Reading the message is done by creating a method that responds to a message event generated by the Stomp library.

1
2
3
public function processMessage(msg : MessageEvent) : void {
  var obj : * = msg.message.body.readObject();
}

But the problem I ran into was that the typing of obj was always a generic Object.  So I proceeded to try and figure out how to get a properly typed object passed into ActionScript.  I tried several different methods but the craziest was that I tried was trying to implement a sort of null RPC call that would call com.adobe.serializers.utility.TypeUtility.convertResultHandler to do the unserializing.  But no matter what, none of the methods I tried would yield a properly type ActionScript object.  So I looked at the text output of the PHP output.

1
)valueObjects\Boogersnutsowhat?

Oh.

Notice anything?

Yep.  PHP namespace separator.  What did ActionScript use?  Yep, a period.

To solve it I added one line to the ActionScript processMessage() method.

1
2
3
4
public function processMessage(msg : MessageEvent) : void {
  flash.net.registerClassAlias("valueObjects\\Boogers", valueObjects.Boogers);
  var obj : * = msg.message.body.readObject();
}

Now when it is run I get a properly typed ActionScript object that I can work on in my Flex application.

About the author

Kevin Schroeder

View all posts

4 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *