Gracefully Handle WSDL Faults in Flex Using Web Services

I recently came across this problem with an app I am writing at work using ASP.NET web services. There are certain scenarios where the application I am working needs to use a different URL to get to a web service (primarily a development URL vs a production URL).

Several times I inadvertently pointed my web services to the wrong URL and would get an HTTP Request Error when the Flex Web Service could not load the WSDL.

This got me to thinking about a an elegant way to handle instances where a web server might be down, or a particular web service may be unavailable, for whatever reason. I wanted to let users know that the Flex application is unable to communicate with the web server, and in most cases, basically disable the application, because let’s face it, an application is useless without data.

Most examples of Flex web services, particularly .NET web services being consumed by Flex demonstrate a web service declared using MXML and the URL to the WSDL hard coded into the WSDL property of that web service tag. Examples of declaring web services with ActionScript proved to be similar. The WSDL property is hard coded at the declaration of the web service object.

For example, most code snippets used to demonstrate using a web service would look somthing like the following

<mx:WebService id=”myWebService” wsdl=”http://fooserver/somedirector/foo.asxm?wsdl” showBusyCursor=”true”/>

What happens is that the Flex tries to load the WSDL for the web service when the application hits that WebService declaration, and if there is an HTTP Request error, Flex doesn’t handle it very gracefully, and for good reason.

It’s our job as developers to determine how we want to handle such exception. In this particular instance, I want my application to bascially lock itself, so I’ll display a modal PopUp with no close button or something like that, if an HTTP Request error is dispatched by Flex.

So to do this, I declared the web service, in ActionScript, but I could have just as easily used the <mx:WebService /> tag. And I did not supply the wsdl property in the declaration, instead in an init() method I called the the loadWSDL() method of that WebService object at run time. Adding an event listener for the FaultEvent event that will inevitably be dispatched if the Flex WebService encounters any issues in loading the WSDL.

In the FaultEvent event handler, I inspect the FaultEvent.fault.faultCode, FaultEvent.fault.faultDetail, and FaultEvent.faultString properties. If any one of these properties of the FaultEvent object for my WebService tell me that there was an error loading the WSDL, etc. I lock the application down and tell the user to politely contact the sys admin for further support. If this were an AIR application, I could use the filesystem to write this fault to an event log, etc.

The code is pretty simple:

import mx.rpc.soap.WebService;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
private var fooWS:WebService = new WebService();
private var fooWSDL:String = “http://localhost:2251/foo.asmx?wsdl”;

/*in the init method register an event listener for the FaultEvent, and attempt to load the WSDL for the web service with the loadWSDL() method*/

private function init():void
{
fooWS.addEventListener(FaultEvent.FAULT,onWSDLFault);
fooWS.loadWSDL(fooWSDL);
}

/*the event handler for the FaultEvent inspects the FaultEvent object’s fault.faultDetails fault.faultString and the fault.faultCode to see if it was an HTTP request error */

private function onWSDLFault(fault:FaultEvent):void
{
/*if the fault detail is that we were unable to load the wsdl, then we know that there is a problem communiating with the server*/
if(fault.fault.faultDetail.toLowerCase() == “unable to load wsdl
|| fault.fault.faultString.toLowerCase() == “http requrest error
|| fault.fault.faultCode.toLowerCase() == “server.error.request“)
{
var alert:Alert = Alert.show(”The application is unable to communicate with the web server, please try again. If you continue to experience this problem, ” +
please contact your system administrator“);
}
fooWS.removeEventListener(FaultEvent.FAULT,onWSDLFault);
}

This code works just as well if you wanted to use a <mx:WebService/> tag.


About this entry