Monday, September 17, 2007

Coping with Flex Asynchronous Remote Calls - Part I

This post is showing you, how to easily use a modal dialog popup with a ProgressBar, when calling a Web Service in Flex. This can help make the impression to the user, that the call is synchronous.

UPDATE: This is Part I in a multipart post. You can view part II here, about using callbacks to cope with the asynchronous calls.

Previously, i blogged about how to call a web service from flex code. In that post, I showed the basics of calling web services from actionscript code, but I only briefly mentioned, that remote calls are asynchronous in flex. Actually, the asynchronity of remote calls has a major impact, on how you design the client.

In this post, I show one way to cope with the asynchronity.

When a remote call is issued, and the result of the call is to be known on the client, before it can let the user continue, we need to "wait" for the operation to finish. This can be done by opening a modal dialog. In this example, the modal dialog also contains an indication of progress, showing the user, that some operation is running.

Here is the code for the client:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="loadWebService()">
<mx:Script>
<![CDATA[
import mx.rpc.soap.WebService;
import mx.rpc.events.ResultEvent;
import mx.managers.PopUpManager;

private var longRunningService : WebService = new WebService();

private function loadWebService() : void {
longRunningService = new WebService();
longRunningService.wsdl = "/services/LongRunningService?wsdl";
longRunningService.loadWSDL();
}

private function callWebService() : void {
var popup : ShowProgress = ShowProgress(PopUpManager.createPopUp(this, ShowProgress, true));
PopUpManager.centerPopUp(popup);
longRunningService.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
PopUpManager.removePopUp(popup);
});
longRunningService.slowOperation();
}
]]>
</mx:Script>

<mx:Button label="Call a long running remote method" click="callWebService()"/>
</mx:Application>

In the above code, loadWebService() is called at application creation time. It loads and parses the wsdl and adds web service operations to the longRunningService variable.

When the button is clicked, it calls callWebService() which:
  1. Creates a popup window from the ShowProgress type (my progress dialog), marking it modal. After this line of code, the modal popup is showing, and no user input can be made.
  2. It then adds an event listener for the ResultEvent.EVENT event, which is dispatched when the web service call completes. This handler will remove the popup when called.
  3. The web service call is made.
And here is the code for the ShowProgress.mxml dialog:

<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" title="Talking to server" creationComplete="init()">
<mx:Script>
<![CDATA[
private function init() : void {
progress.setProgress(1, 0); // to start progress indicator when indeterminate
}
]]>
</mx:Script>
<mx:ProgressBar id="progress" mode="manual" indeterminate="true"/>
</mx:TitleWindow>

It contains only a ProgressBar component, which is set into manual mode and set to be indeterminate. In manual mode, we must use setProgress to update progress. When being indeterminate, it does not show progress against an absolute stop value, but simply indicates "some" progress. In the init() method, I call setProgress(1, 0), which starts the indeterminate progress indicator.

It is important to note here, that the call is not actually synchronous now, just because of the modal dialog. It only appears to be, by the user. The application will continue, after the call to the web service.

Downloading the source
I have zipped up the sources for you. It can be downloaded from here. Ready to be build with maven.

This is a multi-module maven build. There are two directories:
  • client : Contains the flex source and a pom to build it
  • server : Contains the web service and a pom to build it
The war artifact output from the server module have in it the flash output from the client module and a index.html which loads it.

To start the server after a build, you simply jump into the server directory and do a "mvn jetty:run-exploded".

Other Small Flex Tutorials
This was lesson 7 in my series of posts on what I learn about developing filthy rich flash apps using flex2. If you want to read more, the previous lessons can be found here:

2 comments:

Vickram said...

Very nice tip! Thanks.

Yannick said...

Great post thanks !!!