Flash Remoting: Error-proofing the Connection class
Oct 19th
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:
- Initialize w/ ASBroadcaster
- Dispatch onStatus event
Change to the Service class:
- Subscribe to the Connection class’ events
Following is the actual code we had to modify:
Connection class:
- Added 1 line to constructor
- Added onStatus method which dispatches onStatus events using ASBroadcaster
AsBroadcaster.initialize(this);
public function onStatus( status ):Void
{
trace('[Connection Class] onStatus invoked');
this.broadcastMessage('onStatus');
}
Service class:
- Added 2 lines @ Line 73
__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
AMFPHP in AS3
Sep 11th
Remoting in ActionScript 3 is easy to implement, but there are some important things to keep in mind. Most notably, the mx.remoting package is no longer required. There are no additional packages to install, everything you need is built right in to flash.net
This RemotingConnection class extends NetConnection and sets the objectEncoding to AMF:
package
{
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
public class RemotingConnection extends NetConnection
{
public function RemotingConnection( sURL:String )
{
objectEncoding = ObjectEncoding.AMF0;
if (sURL) connect( sURL );
}
}
}
This class employs the above class, and makes a remote service call:
package
{
import flash.net.Responder;
public class AS3RemotingTest
{
public var dataProvider:Array;
public var gateway : RemotingConnection;
public function AS3RemotingTest()
{
this.init();
}
public function init()
{
var gatewayUrl:String = "http://localhost:88/amfphp/gateway.php";
gateway = new RemotingConnection(gatewayUrl);
var responder:Responder = new Responder(onResult, onFault);
var arg:String = 'foo';
gateway.call( "HelloWorld.say", responder, arg);
}
public function onResult( result ) : void
{
trace('onResult invoked');
trace(result);
}
public function onFault( fault : String ) : void
{
trace('onFault invoked');
trace( fault );
}
}
}
(Note: The above code assumes that you have AMFPHP installed and running out of a folder named amfphp on your localhost)