jump to navigation

Handling RPC service events June 6, 2010

Posted by Tournas Dimitrios in Flex.
trackback

Calls to a remote service are asynchronous. After you invoke an asynchronous call, your application does not wait for the result, but continues to execute. Therefore, you typically use events to signal that the service call has completed.When a service call completes, the WebService and HTTPService components dispatch one of the following events:

  • A result event indicates that the result is available. A result event generates an mx.rpc.events.ResultEvent object. You can use the result property of the ResultEvent object to access the data returned by the service call.
  • A fault event indicates that an error occurred. A fault event generates an mx.rpc.events.FaultEvent object. You can use the fault property of the FaultEvent object to access information about the failure.

You can also handle the invoke event, which is broadcast when an RPC component makes the service call. This event is useful if operations are queued and invoked at a later time.

You can handle these events at three different levels in your application:

  • Handle them at the component level. Specify event handlers for the fault and result events for the component. By default, these event handlers are invoked for all service calls.
  • For the WebService component only, handle them at the operation level. These event handlers override any event handler specified at the component level. The HTTPService component does not support multiple operations, so you use this technique only with the WebService component.
  • Handle them at the call level. The send() method returns an AsyncToken object. You can assign event handlers to the AsyncToken object to define event handlers for a specific service call.

Handling events at the component level

Handle events at the component level by using the fault and result properties of the component to specify the event handlers, as the following example shows:

<?xml version="1.0"?>
<!-- ds\rpc\RPCIntroExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        
            import mx.rpc.events.ResultEvent;
            import mx.rpc.events.FaultEvent;
            import mx.controls.Alert;

            public function handleResult(event:ResultEvent):void {
                // Handle result by populating the DataGrid control.
                // The operation returns an Array containing product ID, name, and price.
                myDG.dataProvider=event.result;
            }

            public function handleFault(event:FaultEvent):void {
                // Handle fault.
                Alert.show(event.fault.faultString, "Fault");
            }
      
    </mx:Script>

    <!-- Define a WebService component  and connect to a service destination. -->
   <mx:WebService
        id="adbe_news"
        useProxy="true"
        destination="ws-catalog"
        result="handleResult(event);"
        fault="handleFault(event);"/>

    <!-- Call the getProducts() operation of the web service.
      The operation takes no parameters. -->
    <mx:Button click="adbe_news.getProducts();"/>

    <!-- Define a DataGrid  control to  diplay  the results of the web service. -->
   <mx:DataGrid id="myDG" width="100%" height="100%">
        <mx:columns>
            <mx:DataGridColumn dataField="productId" headerText="Product Id"/>
            <mx:DataGridColumn dataField="name" headerText="Name"/>
            <mx:DataGridColumn dataField="price" headerText="Price"/>
        </mx:columns>
    </mx:DataGrid>

</mx:Application>

In this example, all operations that you invoke through the WebService component use the same event handlers.

Handling events at the operation level for the WebService component

For the WebService component, you can handle events at the operation level. These event handlers override any event handler specified at the component level. When you do not specify event listeners for an operation, the events are passed to the component level.In the following MXML example, the WebService component defines default event handlers, and the operation specifies its own handlers:

<?xml version="1.0"?>
<!-- ds\rpc\RPCResultFaultMXML.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

 <mx:Script>

 import mx.rpc.soap.SOAPFault;
 import mx.rpc.events.ResultEvent;
 import mx.rpc.events.FaultEvent;
 import mx.controls.Alert;

 public function getProductsResult(event:ResultEvent):void {
 // Handle result.
 }

 public function getProductsFault(event:FaultEvent):void {
 // Handle operation fault.
 Alert.show(event.fault.faultString, "Error");
 }

 public function defaultResult(event:ResultEvent):void {
 // Handle result.
 }

 public function defaultFault(event:FaultEvent):void {
 // Handle service fault.
 if (event.fault is SOAPFault) {
 var fault:SOAPFault=event.fault as SOAPFault;
 var faultElement:XML=fault.element;
 // You could use E4X to traverse the raw fault element
 // returned in the SOAP envelope.
 }
 Alert.show(event.fault.faultString, "Error");
 }

 </mx:Script>

<mx:WebService id="WeatherService"
 destination="ws-catalog"
 result="defaultResult(event);"
 fault="defaultFault(event);">
 <mx:operation name="getProducts"
 fault="getProductsFault(event);"
 result="getProductsResult(event);">
 </mx:operation>
 </mx:WebService>

 <mx:Button click="WeatherService.getProducts.send();"/>
</mx:Application>

Handling events at the call level

Sometimes, an application requires different event handlers for calls to the same service. For example, a service call uses one event handler at application startup, and a different handler for calls during application execution.To define event handlers for a specific service call, you can use the AsyncToken object returned by the send() method. You then register event handlers on the AsyncToken object, rather than on the component, as the following ActionScript code shows:

<?xml version="1.0"?>
<!-- ds\rpc\RPCAsynchEventHandler.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

 <mx:Script>
 
 import mx.rpc.soap.SOAPFault;
 import mx.rpc.events.ResultEvent;
 import mx.rpc.events.FaultEvent;
 import mx.controls.Alert;
 import mx.rpc.AsyncToken;
 import mx.rpc.AsyncResponder;

 // Define an instance of the AsyncToken class.
 public var serviceToken:AsyncToken;

 // Call the service, and then
 // assign the event handlers to the AsyncToken object.
 public function setCustomHandlers():void {
 // send() returns an instance of AsyncToken.
 serviceToken = WeatherService.getProducts.send();
 var asynchRes:AsyncResponder =
 new AsyncResponder(getProductsResult, getProductsFault);
 serviceToken.addResponder(asynchRes);
 }

 // Use the token argument to pass additional information to the handler.
 public function getProductsResult(event:ResultEvent, token:Object = null):void {
 // Handle result.
 }

 // Use the token argument to pass additional information to the handler.
 public function getProductsFault(event:FaultEvent, token:Object = null):void {
 // Handle operation fault.
 Alert.show(event.fault.faultString, "Error");
 }

 public function defaultResult(event:ResultEvent):void {
 // Handle result.
 }

 public function defaultFault(event:FaultEvent):void {
 // Handle service fault.
 if (event.fault is SOAPFault) {
 var fault:SOAPFault=event.fault as SOAPFault;
 var faultElement:XML=fault.element;
 // You could use E4X to traverse the raw fault element
 // returned in the SOAP envelope.
 }
 Alert.show(event.fault.faultString, "Error");
 }
 
 </mx:Script>

 <mx:WebService id="WeatherService"
 destination="ws-catalog"
 result="defaultResult(event);"
 fault="defaultFault(event);">
 <mx:operation name="getProducts"/>
 </mx:WebService>

 <!-- Call the service using the default event handlers. -->
 <mx:Button label="Use Default Handlers" click="WeatherService.getProducts.send();"/>

 <!-- Call the service using the custom event handlers. -->
 <mx:Button label="Use Custom Handlers" click="setCustomHandlers();"/>

</mx:Application>

Notice that some properties are assigned to the token after the call to the remote service is made. In a multi-threaded language, there would be a race condition where the result comes back before the token is assigned. This situation is not a problem in ActionScript because the remote call cannot be initiated until the currently executing code finishes.

Advertisements

Comments»

No comments yet — be the first.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s