Porting Flashcom Applications to ActionScript 3

Regardless if you Flex or Flash, I ran into a porting issue with a Flashcom app I wrote in Flex 1.5 & ActionScript 2. A lot of the server-side code, which is written in case sensitive JavaScript 1, utilizes the Flashcom Component Framework. This framework utilizes a namespace scheme to allow clients to identify server components, and server components to identify client components. This allows them to send messages to each other, and works really well…

…except in Flash Player 9. For some reason, the namespace mechanism doesn’t work for ActionScript 3 classes. This isn’t a big deal for playing existing content. All of my existing Flashcom apps I wrote in Flash MX 2004 & Flex 1.5 (Flash Player 7) still run just fine in Flash Player 9 in both Firefox & IE.

It’s when you have a server-side script do a NetConnection.call on an Flash Player 9 created SWF that things don’t work. You CAN call a method that your class has defined as public assuming you point the NetConnection’s client property to your class; protected and private don’t work. However, the namespace mechanism commonly used in ActionScript 2 doesn’t work with the server; it constantly reports method not found. You’d typically decorate the client side NetConnection object reference that you’re component got passed in via it’s loose interface “connect” method. This decoration with the namespaces pointing to your component allowed the server-side to find it. The server-side Flashcom Component Framework already has a built-in namespace mechanism that still works just fine.

You can emulate this by extending NetConnection, and making the class dynamic. Still, you’ll get the method not found error.

My only guess at the problem is I think it has to do with the lack of support of “slash syntax”. I’m not sure the new ActionScript Virtual Machine supports it. I know AVM does; it’s how Flash Player 4 SWF’s will work the same as they always have. However, it seems the FCS Component Framework utilizes this behind the scenes somehow. When you do this on the server-side:

nc.call ( this.callPrefix + "method" );

You’re basically going:

nc.call ( "YourComponent/InstanceName/method" );

…I guess. I gave up after 3 nights of trying to get it to work. I didn’t mind porting client code, but I didn’t want to port server-side code. Anyway, fix for me is to pass in the callPrefix as the first parameter to the method, and have the client side Observer class just parse out “who this message goes to”.

If you get it to work on your end, drop a note in the comments. I’m using Flex 2 & FCS 1.5 on Windows via Flash Player 9 in Firefox 1.5.

4 Replies to “Porting Flashcom Applications to ActionScript 3”

  1. Hello Jesse,

    Thanks for posting this message. I’ve been at it porting an FMS application to Actionscript 3.0 and Flex for a week and couldn’t get the method calls with NetConnection to work. It’s consoling that I’m not the only one having problems.

    I’m using Influxis as a hosting, so there’s no easy way to circumvent the object decoration that is used as a namespace mechanism: The standard components use the /-substitution and cannot be overriden, unless I rewrite the whole component framework.

    When I use a dynamic class as client for the NetConnection object on the client-side, the debugger never complains when it cannot find a method, so this isn’t very helpful. Next, I tried to use a static class and yes, the debugger signals an exception when a method cannot be found, but only if the server-side call was not decorated with class and instance.

    Then, I tried to extend the Proxy class and use it as a client object for NetConnection to see what exactly is happening on the client side. Unfortunately to no avail. It seems like the method calls with slashes in them are just plainly ignored by Flash Player 9.

    The experiment with Proxy did reveil something interesting, though. It turns out that Flash Player 9 doesn’t actually ‘call’ the function on the client object. Instead, it ‘get’s the function as a property and then calls it as a method on some different object.

    It’s a mistery to me how Flash Player decides what object to call the method on, but it looks like it has to do with the last created instance of the class that the method belongs to.

    Well, I hope this gives some avenues of inquiry for other readers and that some of you may shed some light on this.

  2. Not sure if I blogged it, but can’t find the link now. Bottom line, you just change the this.callPrefix on the server-side for client.call’s. Then, you have the client parse this string and dispatch the calls to the components manually.

    So, this:

    client.call(this.callPrefix + ‘method’, null);

    becomes:

    client.call(‘method’, null, this.callPrefix);

    You then have your client property, typically a class, handle the routing. See the comments in the previous post.

  3. I could get the server calls to the client working fine using the method that JesterXL described like this.

    application.onConnect(myclient)
    {
    this.acceptConnection(myclient);

    myclient(“methodToCall”, null, args);

    }

    on the client side I did have to define the method being called as a method in an external public class and pass it to the client property of the NetConnection object like this:

    //external class

    package{
    public ExternalClass{

    public ExternalClass(){
    //empty constructor
    }

    public methodToCall(args)
    {
    trace(args);
    }
    }
    }

    in the main timeline of the client swf

    var newPublicObject:ExternalClass = new ExternalClass();

    var my_nc:NetConnection = new NetConnection();
    my_nc.client = newPublicObject;

    my_nc.connect(rtmp://www.domain.com/applicaitonName/AppInstance);

    This all works fine, but I cannot get any call to work where the client calls a server method. According to the documentation, you have to define the server side method on the Client Object that is passed to the onConnect Event in the application main.asc. That right there sounds like a name space problem to me, since that is also where you call client side methods right?

    It is supposed to go something like this on the server side:

    application.onConnect(myclient)
    {

    this.acceptConnection(myclient);

    myclient.methodToCall = function()
    {
    return “someString”;
    }
    }

    The client swf calls the method using the NetConnection call method:

    my_nc.call(“methodToCall”,null, args);

    the second parameter is a Responder Class object that you can define. It is used to set up functions to handle return values if the call succeeds or fails like this:

    var myResponder:Responder = new Responder(successFunction, failFunction);

    so you could change the NetConnection call to

    my_nc.call(“methodToCall”,myResponder,args);

    If the call fails it sends a return object to the failFunction that has three properties…
    level
    code
    description – This one tells you why it failed

    so you can set up the failFunction like this:

    function failFunction(e:Object)
    {
    //Note that the return object is just a generic object not an error object
    trace(e.descriptoin);
    }

    This always traces as Method not found no matter how I try to define the method on the server side

    I have tried every method that they show in the server documentation and I can’t get the client to call a server side function. One guess was the AMF encoding so I set that to 0 for the earlier encoding method that is suppported by FMS 2 and that eliminated IO Errors being returned from the NetConnection object, but it did not solve the issue of callling server side functions. This is a big problem. I am going to try creating server side classes that might also solve the scoping issue on the server side the way it did on the client side and see if that works. Let me know if anyone solves this one. Thanks.

Comments are closed.