Flash Remoting: Error-proofing the Connection class

October 19th, 2006 by Caleb

We all love Flash Remoting (and in particular AMFPHP). We ambitiously defend this new paradigm of RIA communication, emphasizing it’s numerous advantages and the significant, immediate benefits we can achieve by introducing remoting techniques into our code.

However, as Jeffery Bennett recently pointed out to me, the Connection class does not dispatch onStatus events if the gateway is inaccessable for whatever reason. This posting shows you have to add this capability with a few simple lines of ActionScript, giving you the ability to elegantly handle such errors.

This is how you would typically construct a simple method call using AMFPHP:


import mx.remoting.*;
import mx.rpc.*;
import mx.remoting.debug.NetDebug;
var gatewayUrl:String = "http://dev.caleb.org/amfphp/gateway.php"
var service:Service = new Service(gatewayUrl, null, 'HelloWorld');
var pc:PendingCall = service.say("Hello world!");
pc.responder = new RelayResponder(this, "handleResult", "handleError");
function handleResult(re:ResultEvent)
{
trace('The result is: ' + re.result);
}
function handleError(fe:FaultEvent)
{
trace('There has been an error');
}

The Connection class is typically employed by the Service class. If you inspect the signature of the Service class constructor, you’ll notice that the 5th [optional] parameter is the responder.

Service ( gatewayURI, logger, serviceName, conn, resp)

The first example doesn’t employ that handler, and even if one where to pass a responder, it wouldn’t receive error event dispatches. The Service class documentation states, “The resp parameter allows you to specify the responder object that contains the result and fault handling methods that receive control when the service returns a result or a fault condition.”

The problem is, the Service class doesn’t receive a fault condition if the Connection’s gateway creation fails. The Service class assumes that the Connection class has a gateway that is online. Of course, there is no guarantee that this can happen; it’s obviously a potentially erroneous assumption.

In order to error-proof the call, we need to make 2 simple changes to the Connection class, and 1 simple change to the Service class (in addition to passing a valid responder in as the 5th arugment to the Service class).

Changes to the Connection class:

Change to the Service class:

Following is the actual code we had to modify:

Connection class:

  1. Added 1 line to constructor
  2. AsBroadcaster.initialize(this);

  3. Added onStatus method which dispatches onStatus events using ASBroadcaster

  4. public function onStatus( status ):Void
    {
    trace('[Connection Class] onStatus invoked');
    this.broadcastMessage('onStatus');
    }

Service class:

  1. Added 2 lines @ Line 73

  2. __conn.addListener(this);
    __conn.addListener(__responder);

The “error-proof” example below shows you how to modify both the Service class and the Connection class (Note: I intentionally broke the following code in order to ensure that the onStatus method is invoked. If you want to see it work properly, change the “pdhp” to “php” in the gatewayUrl variable declaration):


import mx.remoting.*;
import mx.rpc.*;
import mx.remoting.debug.NetDebug;
var gatewayUrl:String = "http://dev.caleb.org/amfphp/gateway.pdhp"
var service:Service = new Service(gatewayUrl, null, 'HelloWorld', null, this);
var pc:PendingCall = service.say("Hello world!");
pc.responder = new RelayResponder(this, "handleResult", "handleError");
function handleResult(re:ResultEvent)
{
txtFeedback.text = 'The result is: ' + re.result;
}
function handleError(fe:FaultEvent)
{
trace('error');
txtFeedback.text = 'There has been an error';
}
function onStatus( status ):Void
{
trace('onStatus invoked')
}

The files are available for download here: http://dev.caleb.org/download/code/ErrorProofRemotingConnection.zip

I would love to hear any feedback anyone might have :-)

Digg It | Add to Del.icio.us

Filed under Caleb, Flash Remoting w/

15 Comments »

  1. […] Read […]

    Pingback by The Flash Index » Blog Archive » Flash Remoting: Error-proofing the Connection class — October 20, 2006 @ 8:34 pm

  2. Very nice !! Thanks for sharing.
    However i am encountering trouble while testing your example. It all works fine in your example. BUT if i change the gatewayURL to mine (amfphp 1.2) and replace your service.whatever call so it works with my setup/function, then i will get an “onStatus” call no matter if the connection succeeded or failed. It just comes up all the time. Suggestions?

    Comment by Klark Kent — November 7, 2006 @ 4:14 am

  3. One thing is that on your server the common trace message “Error opening URL “http:// xyz” is not even showing up when pointing to a nonexisting gatewayURL. On my server i am allways getting this error.

    Comment by Klark Kent — November 7, 2006 @ 4:29 am

  4. Klark, thanks for the comments. I haven’t yet encountered that situation. I’m travelling on business today, but I will try to reproduce and resolve the problem ASAP. Thanks for the feedback :-)

    Comment by Caleb — November 7, 2006 @ 10:23 pm

  5. Hi!
    I saw your code, and i’m having a problem with Connection class that only occurs in Flash Player 8 and above.
    When I publish to Player 8, my Connection.onStatus fires
    to function correctly. The problem is that the status
    information is undefined!

    myConnection.onStatus=function(status)
    {
    trace(”onStatus”);
    trace(status.details);
    trace(status.description);
    }

    Any idea?

    Thanks in advance,
    Rui Pereira

    Comment by Rui Pereira — November 9, 2006 @ 4:06 am

  6. Rui,

    You are accurate in your observation that no status information is being dispatched with the onStatus method invocation. I’ll add that to my list of fixes to address when time permits … thanks for the comment :-)

    Comment by Caleb — November 9, 2006 @ 5:14 am

  7. I tried your example and could not get it to fire any error. I even downloaded your files. And used those and still nothing. I modified both class files. I’m using flash 8 and publishing to 8 as well.

    Comment by Kay — November 15, 2006 @ 10:54 am

  8. Hello Caleb,

    Thanks a lot for sharing this code! I wouldn’t have known about this issue otherwise.

    Unfortunately, I just can’t get it to work properly. Adding ‘this’ as the last parameter for the service call will return a ‘type mismatch’ compiler error, and simply removing it (or adding a valid responder param) doesn’t do anything at all (as in no RPC code gets executed). Changing to a valid gateway path does get things rolling again, although onStatus() never gets called either way.

    I am using version 9.0r28 of the flash player. My code differs slightly from yours in that I’m adding a logger as a second parameter to my service call (in case this makes any difference).

    Thanks for your time, and good luck on your business trip!

    Comment by Bernardo Kuri — December 2, 2006 @ 12:04 am

  9. If you want avoid patching, you can make use of the connection argument passed to the Service class. For example:

    var gatewayUrl:String = “http://dev.caleb.org/amfphp/gateway.php”
    var conn:Connection = new Connection();
    conn.onStatus = function( info ):Void
    {
    if (info == undefined) {
    trace(”The host can’t be reached”);
    } else {
    trace(”onStatus: ” + info.code);
    }
    }
    conn.connect(gatewayUrl);
    var service:Service = new Service(null, null, ‘HelloWorld’, conn);
    var pc:PendingCall = service.say(”Hello world!”);
    pc.responder = new RelayResponder(this, “handleResult”, “handleError”);
    function handleResult(re:ResultEvent)
    {
    trace(’The result is: ‘ + re.result);
    }
    function handleError(fe:FaultEvent)
    {
    trace(’There has been an error’);
    }

    Hope that helps.

    Comment by Ezequiel — December 23, 2006 @ 9:37 am

  10. Awesome code Ezequiel! I like your solution rather than patching core classes. Thanks a lot!

    Damn it, it’s so easy actually.. and I was looking for such a long time for a solution!

    Thanks guys.

    Comment by Brad — February 2, 2007 @ 12:59 pm

  11. If any one change the gatewayURL to mine (amfphp 1.2) and replace your service.whatever call so it works with my setup/function.

    Comment by enrique vamp — March 18, 2007 @ 11:16 pm

  12. @Bernardo_Kuri

    try to publish for Flash 7 to see if it fix the type mismatch error. If so when publishing for Flash 8 define service like this :
    [code]
    var service:Service = new mx.remoting.Service(gatewayUrl, null, ‘HelloWorld’);
    [/code]
    Seems AS2 in Flash8 doesn’t understand well ‘new Service’ it needs ‘new mx.remoting.Service’ for not issuing a type error… I eventually ran amok before seeing this page : http://yawoong.com/board/view.php?id=tutorial_kidari70&no=127

    Comment by mecanography — March 19, 2007 @ 8:38 am

  13. For anyone who was attempting to use Ezequiel’s method and wasn’t successful, modify the following line:

    var service:Service = new Service(null, null, ‘HelloWorld’, conn);

    to become:

    var service:Service = new Service(null, null, ‘HelloWorld’, conn, this);

    That seemed to do the trick for me.

    Comment by Digi — August 15, 2007 @ 8:00 am

  14. Is there a similar solution in AS3 ?
    Thanks

    Comment by mammut — February 21, 2008 @ 3:29 am

  15. ya rite but some times its not work yaar. Give me some more info

    Comment by hairy — March 24, 2008 @ 2:11 am

RSS feed for comments on this post. TrackBack URI

Leave a comment


Anti-Spam Image


To prove you are a human being, please type the word shown in the picture above:.

Anti-spam word: (Required)*