Accessibility

Flex Article

 

Expediting Application Development with the Flex Application Starter Toolkit (FAST)


Table of Contents

Comments

FAST Data Communications Features

The following sections describe the data communications features in FAST. First, you’ll see a simple example of how remote data services are accessed. Next, you’ll read about the many useful features that the FAST provides “for free”, such as client-side data caching; support for RemoteObject, WebService, and HTTPService tags; and error handling. Finally, you’ll read about the classes that implement FAST data communications.

Simple Data Retrieval

We use a trivial example application to present the essential data communications features of FAST (_010_SimpleDataRetrieval.mxml). Figure 3 shows how the application appears to the user:

 The Simple Data Retrieval Example Application

Figure 3: The Simple Data Retrieval Example Application

You can run the code at: flexapps.macromedia.com/fast/fastTutorial/_010_SimpleDataRetrieval.mxml.

Flex source for the previous example application follows: (You can follow this code in the _011_SimpleDataRetrieval_minimal.mxml file, available in the Requirements section). Note the highlighted areas.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml">

  <s:_01_SimpleProxyFactory xmlns:s="services.*" 
                            debug="true"/>  
  
  <mx:DataGrid dataProvider="{customerSummaryArray}" 
               width="100%" height="100%"/>
  
  <mx:Button label="Get data"
             click="getPersonData()"/>
                                              
  <mx:Script>
      <![CDATA[
      
      import fast.services.ProxyFactory; 
      import fast.services.Proxy;
       private var customerSummaryArray:Array;
       private function getPersonData(){
      var proxy:Proxy = ProxyFactory.getProxy("simpleService");
      proxy.invoke("generateCustomerSummaryList", //remote method
             this,                        //local reply object
             "customerSummaryArray",      //local reply target
                                          //remote method inputs:
             50,                          //- # records requested
             1,                           //- index of first record
             0);                          //- server delay (ms)                                            
      }         
      ]]>   
  </mx:Script>    
</mx:Application>

The first highlighted line above refers to the proxy factory below (_01_SimpleProxyFactory.mxml):

<?xml version="1.0" encoding="utf-8"?>
<s:ProxyFactory xmlns:mx="http://www.macromedia.com/2003/mxml" 
                xmlns:s="fast.services.*">
        
    <mx:RemoteObject id="simpleService"   
                     named="FastReplyGenerator"
                     result="resultHandler(event)"
                     fault="faultHandler(event)"                     
                     showBusyCursor="true">                  
    </mx:RemoteObject>        
</s:ProxyFactory>

The preceding Flex code calls this remote Java method on the samples.fastTutorial.ReplyGenerator class:

public ArrayList generateCustomerSummaryList(int replySize,
                                        int firstIndex,
                                        int serverDelay)
                                        throws InterruptedException {
  . . .
}

Notice the following main points in this example:

  • A ProxyFactory subclass is defined declaratively. See the reference to _01_SimpleProxyFactory at the beginning of the Flex code above. Also, see the contents of _01_SimpleProxyFactory.mxml and note that _01_SimpleProxyFactory extends the fast.services.ProxyFactory base class.
  • The parameter passed to ProxyFactory.getProxy() matches the id of a service tag in the ProxyFactory subclass. In the example, this id is "simpleService".
  • A proxy instance is retrieved using ProxyFactory.getProxy().
  • The proxy instance manages data retrieval. It sends requests to the server, “catches” and routes server replies, and performs error handling. It sends diagnostic information to the Echo console if ProxyFactory.debug is true.
  • Remote services are accessed through the proxy.invoke() method. Parameters to this function include:

    • The remote method name (for RemoteObject) or operation (for WebService). In the example this value is "generateCustomerSummaryList".
    • The object and target to which the result should be sent, respectively this and "customerSummaryArray" in the example. Target can be a property, as in this example, or a function.
    • A variable number of input parameters. In this example the remote service expects 3 integers.

Client-side Data Caching

Figure 4 shows the FAST example program client-side data caching:

The Client-Side Data Caching Example Application

Figure 4: The Client-Side Data Caching Example Application

See it live at: flexapps.macromedia.com/fast/fastTutorial/_020_ClientSideDataCache.mxml.

The example program retrieves data from a Java server using a remote method called getCustomerDetail. The getCustomerDetail method waits three seconds before returning, which makes the effect of client-side caching more noticeable. Client-side caching is enabled for calls to the getCustomerDetail method, which causes the proxy.invoke() method to go through the following extra steps on every call:

  • Create a cache key by serializing input parameters to getCustomerDetail method.
  • Check the cache for replies from getCustomerDetail with a matching key.
  • If a match is found, return the reply from cache.
  • If no match is found, send the server request and put the reply into the cache when it is received.

Caching is enabled in the ProxyFactory class. In the example application, (_020_ClientSideDataCache.mxml) the ProxyFactory is defined in line 10:

<s:_02_ClientDataCacheProxyFactory xmlns:s="services.*" debug="true"/>

The ProxyFactory source (_02_ClientDataCacheProxyFactory.mxml) shows the syntax for enabling the cache:

<?xml version="1.0" encoding="utf-8"?>
<s:ProxyFactory xmlns:mx="http://www.macromedia.com/2003/mxml" 
                xmlns:s="fast.services.*">
                                                      
    <mx:RemoteObject id="cachedService"   
                     named="FastReplyGenerator"
                     result="resultHandler(event)"
                     fault="faultHandler(event)"                     
                     showBusyCursor="true">                  
    </mx:RemoteObject>
    
    <s:cachedMethods>
        <mx:Array>
            <s:CachedMethod serviceName="cachedService" 
                            methodName="getCustomerDetail"/>
        </mx:Array>
    </s:cachedMethods>

</s:ProxyFactory> 

This is the only change needed to enable caching. All other application logic is the same with or without caching enabled . As the example program shows, you can dump the cache with the following syntax:

proxy.dumpCache("getCustomerDetail");

To understand FAST caching more deeply, examine the Echo console output produced by the caching example applications.

RemoteObject, WebService, and HTTPService Support

FAST supports the three main data communication protocols that Flex 1.5 supports natively: RemoteObject, WebService, and HTTPService. The previous examples demonstrate support of the RemoteObject protocol.

The FAST syntax for the WebService protocol is identical to that used for the RemoteObject protocol. The only difference is in the ProxyFactory, where you use the WebService tag instead of RemoteObject. The web services example program (_030_WebService.mxml) is identical to the previous example, except that it communicates through SOAP/WebService rather than AMF/RemoteObject. Here is the web service example application’s ProxyFactory class (_03_ClientDataCacheProxyFactory_WS.mxml):

<?xml version="1.0" encoding="utf-8"?>
<s:ProxyFactory xmlns:mx="http://www.macromedia.com/2003/mxml" 
                  xmlns:s="fast.services.*">
    
    <mx:WebService id="cachedService_ws" 
                   serviceName="FastReplyGenerator"
                   result="resultHandler(event)"
                   fault="faultHandler(event)" 
                   showBusyCursor="true">
    </mx:WebService>    

    <s:cachedMethods>
        <mx:Array>
            <s:CachedMethod serviceName="cachedService_ws" 
                            methodName="getCustomerDetail"/>
        </mx:Array>
    </s:cachedMethods>   
</s:ProxyFactory>

Run the sample code at: flexapps.macromedia.com/fast/fastTutorial/_030_WebService.mxml.

Conceptually, FAST support for the HTTPService protocol is very similar to that of the RemoteObject and WebService protocols, but the syntax differs in some ways. The following snippets come from the HTTPService example program, _040_HTTPService.mxml. For the HTTPService application, you import a different proxy class:

import fast.services.HttpProxy;  

Get an HttpProxy instance through a different ProxyFactory method:

 var httpProxy:HttpProxy = ProxyFactory.getHttpProxy("httpService");

The call to invoke a remote HTTP service includes a parameter that specifies which part of the reply XML object should be returned to the caller. See pathInResult in the code snippet below:

httpProxy.requestXmlData(targetUrl,     //target url
                     pathInResult,  //path in result to needed data
                     this,                  //local reply object
                     "customerSummaryArray",//local reply target
                                            //service inputs:
                     {replySize:20,         //- # records 
                     firstIndex:2,         //- first record index
                     serverDelay:0});      //- server delay (ms)

Run the sample code at: flexapps.macromedia.com/fast/fastTutorial/_040_HTTPService.mxml.

In the example program, pathInResult is set to “custSummList.custSumm”. The server reply looks like the following:

<custSummList>
        <custSumm>
                <lastName>Sosay2</lastName>
                <firstName>Kaiser2</firstName>
                <customerId>ID1002</customerId>
                <address>2 Hill St., Mytown MA</address>
                <phoneNumber>(321) 456-10002</phoneNumber>
        </custSumm>
        <custSumm>
                <lastName>Sosay3</lastName>
                <firstName>Kaiser3</firstName>
                <customerId>ID1003</customerId>
                <address>3 Hill St., Mytown MA</address>
                <phoneNumber>(321) 456-10003</phoneNumber>
        </custSumm>

        . . .

<custSummList>

After the reply XML is converted to Object form, custSumList.custSumm evaluates to an array of objects that display as follows in the Echo Console:

Echo Inspector Display of HTTPService Result Array

Figure 5: Echo Inspector Display of HTTPService Result Array

The other important thing to note about HttpProxy.requestXmlData() is that all input parameters are passed to the server through the last (the fifth) parameter. For form/url-encoded data, all inputs are passed in an object, as shown in the previous example. For application/xml encoding, an XML object would be passed instead.

Error handling

FAST data access eliminates silent failures and provides all available error-related information to the developer in an easily-accessible manner. FAST handles the following error types:

Server-side errors

  • Uncaught exceptions, such as null pointer
  • Exceptions thrown explicitly by server-side application logic
  • Timeout due to a reply not returned within a pre-defined duration
  • Invalid XML returned to client

Infrastructure errors

  • Exception due to wrong method/operation name or signature
  • Timeouts for various reasons, such as an invalid server URL

Client-side errors

  • Invalid use of FAST APIs

The example application shown in Figure 6 forces many types of data access failure.

The Error Handling Example Application

Figure 6. The Error Handling Example Application

(+) View larger

You can try this functionality at: flexapps.macromedia.com/fast/fastTutorial/_050_ErrorHandling.mxml.

The code behind each of the “Go” buttons intentionally causes a system error. For example, the following code sample uses the RemoteObject proxy to call the remote method, getCustomerDetail, with the wrong number of input parameters:

roProxy.invoke("getCustomerDetail",
               this,                
               "customerDetail",     
               "ID001");                                   
               //2);                //  Missing input parameter

This causes a dialog box to appear with detailed error information (Figure 7).

 Example FAST Fault Pop-Up

Figure 7. Example FAST Fault Pop-Up

The intention of the FAST error handling mechanism is to expedite development. It is meant for use in a development environment, not for your application’s ultimate end user, though it can be adapted for this purpose.

FAST makes possible client-side handling of server-side exceptions. FAST also permits attachment of “extra” data to the request that will be available during response or error handling. See the FAST documentation on Proxy.invoke() and on the ProxyBase class. Also see the last entry in the error handling program (exceptionHandledAtClient) for a working example of these functionalities.

FAST Classes

Figure 8 shows a class diagram to give you a circumspect view of the classes that implement FCC data communications.

FAST Data Communications Class Diagram

Figure 8. FAST Data Communications Class Diagram

(+) View larger

The MyProxyFactory class is the only class that is application-specific. All other classes are part of the FAST library and should not be modified. The application developer puts the required service tags (such as RemoteObject) into MyProxyFactory, as shown in the previous example programs. You do not have to name this class MyProxyFactory.

ProxyFactory is responsible for managing proxy instances. It ensures that only one proxy instance is created for each service. This supports client-side data caching and optimized data access in large-scale applications. Setting ProxyFactory.debug to true causes the debug subclasses (such as DebugProxy) to be instantiated at runtime, which results in the application generating additional Echo information. You should enable debug for development, but disable it in production. See additional comments below.

ProxyBase implements common reply and fault handling methods. Inputs and fault data can be accessed by the application during reply and fault handling respectively through methods on this class. This class also provides common functionality related to caching.

Proxy exposes the core invoke() method and handles details related to RemoteObject and WebService calls.

The HttpProxy class exposes the core requestXmlData() method and handles details related to HTTPService calls.

Cache manages client-side storage and retrieval of data returned by the server.

DebugProxy, DebugHttpProxy, and DebugCache generate Echo data that is useful for diagnostic and performance optimization purposes. These classes also add error handling unnecessary in a production setting, such as invalid remote method. These classes are instantiated at runtime only if ProxyFactory.debug is true. Otherwise, the application uses their higher performance, less verbose base classes.

FaultHandler presents pop-up dialog boxes with error information. The developer can change the default class used for the pop-up message. See the error handling example program for usage tips.