Adobe Flex 3 Help

Automatically generating web service proxies

You can use the Flex Builder Import Web Service feature to automatically generate connection code for invoking SOAP-based web service operations. The generated code includes client-side (ActionScript) web service proxy classes that return strongly typed objects. You can use the generated code to call web service operations directly and to pass strongly typed objects as operation parameters.

Generate client code for a WSDL document

  1. Select Data > Import Web Services (WSDL).
  2. Select the project source folder in which to save the generated code.
  3. Click Next.
  4. Specify the URI of the WSDL to use. If your project uses LiveCycle Data Services ES, you can optionally select a LiveCycle Data Services ES web service destination. For a LiveCycle Data Services ES destination to appear in the Import Web Service menu, it must be defined in the proxy-config.xml file and be configured in the following way:
    • The adapter="soap-proxy" attribute must be specified on the destination element. This implies that you have an adapter definition with the id="soap-proxy" attribute defined somewhere else in your configuration files.
    • The destination must also have an id attribute (the value of the id attribute is displayed in the pop-up menu).
    • The destination must have a wsdl child element. Its text value is prefilled in the WSDL URI text box in the wizard.
  5. Click Next.
  6. Deselect any of the listed web service operations for which you do not want to generate code.
  7. (Optional) Select a different service and or port from the Service and Port pop-up menus.
  8. (Optional) Change the default package name and the main class name.
  9. Click Finish to generate the ActionScript proxy classes.

Generated web service proxy files

The Import Web Service feature introspects a WSDL file and generates the following types of ActionScript class files:

Generated file

Description

BaseServiceName.as

A base implementation of the web service. This class contains the internal code that maps the operations from the WSDL file to Flex WSDLOperation instances and sets the corresponding parameters.

IServicename.as

The service interface that defines all of the methods that users can access.

Servicename.as

The concrete web service implementation.

BaseServicenameSchema.as

A file containing the XSD schema of the web service as an ActionScript custom type.

OperationnameResultEvent.as

For each web service operation, Flex Builder generates a strongly typed event type class. You can use these classes to benefit from strongly typed results.

Operationname_request.as

For each web service operation that passes parameters to the server operation, Flex Builder generates a request wrapper class with the parameters as members. The request object is intended for use with the MXML tag syntax.

Type.as

For each complex type defined in the WSDL file, Flex Builder generates a class with the same name as the complex type or with the same name as the enclosing element.

Managing generated web service code

The Manage Web Services feature lets you add, update, or delete generated web service proxy code.

Generate web service code

  1. Select Data > Manage Web Services.
  2. Select a project from the tree of projects.
  3. Click Add.
  4. Click Next.
  5. Enter a new WSDL URI or select an existing one from the pop-up menu. Optionally, if you have a LiveCycle Data Services ES installation, you can use a LiveCycle Data Services ES destination.
  6. Complete the Configure Code Generation text boxes and click Finish.

Update generated web service code

  1. Select Data > Manage Web Services.
  2. Within a project, select the WSDL URI for which you want to update generated code.
  3. Click Update.
  4. Click Refresh to find out if the WSDL document has changed since you imported it.
  5. If the WSDL document has changed, select the operations to update (if different from the default selections).
  6. Click Finish to regenerate code based on the current version of the WSDL document.

Delete generated web service code

  1. Select Data > Manage Web Services.
  2. Within a project, select the WSDL URI for the generated code to delete.
  3. Click Delete and then click Yes in the Confirm Imported WSDL Deletion dialog box.

Creating an application that uses the generated proxy code

You can use MXML tags or ActionScript to call a web service. Equivalent MXML-centric and ActionScript-centric applications use an address book web service that exposes the following operations:

  • AddEntry lets you store someone's address.
  • FindEntry lets you retrieve the address when you provide the person's name.

The AddEntry operation takes an Entry object as input and returns nothing. The FindEntry operation takes a string as input and returns an Entry object.

These sample applications demonstrate the following concepts for working with the code that Flex Builder generated from the WSDL document:

  • You can call a web service operation directly, as the following example shows:
    myWebService.callOperation(parameters)
    
    
  • The parameters passed to the web service operations are strongly typed and reflect the types that are described in the WSDL document.
  • The generated code includes event listeners that are specific to each operation; these listeners return strongly typed results.

The MXML and ActionScript address book applications both use the following generated ActionScript classes:

Generated file

Description

BaseAddressBookService.as

A base implementation of the web service. This class contains the internal code that maps the operations from the WSDL file to Flex WSDLOperation instances and sets the corresponding parameters.

IAddressBookService.as

The service interface that defines all of the methods that users can access.

AddressBookService.as

The concrete web service implementation.

BaseAddressBookServiceSchema.as

The XSD schema of the web service as an ActionScript custom type.

FindEntryResultEvent.as

A strongly typed event type object for the FindEntry operation. For each web service operation, Flex Builder generates a strongly typed event type class. You can use these classes to benefit from strongly typed results.

AddEntry_request.as

A request wrapper class for the AddEntry operation with the parameters as members. The request object is intended for use with the MXML tag syntax.

FindEntry_request.as

A request wrapper class for the FindEntry operation with the parameters as members. The request object is intended for use with the MXML tag syntax.

Entry.as

For each complex type defined in the WSDL file, Flex Builder generates a class with the same name as the complex type or with the same name as the enclosing element.

Calling a service with MXML

For an MXML-centric application, you create an instance of the web service in an MXML tag, as the following code snippet shows. Note that the application uses a custom namespace, ws; this namespace is declared as xmlns:ws="com.adobe.*" in the <mx:Application> tag.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ws="com.adobe.*">
...
    <!-- This is how we create an instance of the AddressBookService generated class.-->
    <ws:AddressBookService id="myWebService">
        <!-- We need to specify the request variables that are passed to the corresponding operations. -->
        <ws:addEntry_request_var>
            <!-- The addEntry operation has one input parameter. This parameter's type is Entry. -->
            <ws:AddEntry_request>                
                <ws:param0>
                    <ws:Entry>
                        <!-- We bind each of the members of an Entry object to the corresponding text input field.-->
                        <ws:name>{tiNameInput.text}</ws:name>
                        <ws:city>{tiCityInput.text}</ws:city>
                        <ws:street>{tiStreetInput.text}</ws:street>
                        <ws:state>{tiStateInput.text}</ws:state>
                        <ws:postalCode>{tiPostalCodeInput.text}</ws:postalCode>
                    </ws:Entry>
                </ws:param0>                
            </ws:AddEntry_request>
        </ws:addEntry_request_var>
        
        <!-- The findEntry operation has one input parameter of the String type. -->
        <ws:findEntry_request_var>
            <!-- We bind the corresponding text input field to the operation's input parameter.
              Since the operation's input parameter has a simple type, you can use the following syntax to do the data binding.
              Alternatively you could do: 
              <ws:FindEntry_request>
                <ws:param0>{tiSearch.text}</ws:param0>
              </ws:FindEntry_request>    
              -->              
            <ws:FindEntry_request param0="{tiSearch.text}">
            </ws:FindEntry_request>
        </ws:findEntry_request_var>
    </ws:AddressBookService>
...

On the click event for the Add entry button, call the addEntry_send() method to pass the request to the service, as the following code snippet shows:

...
<mx:Button label="Add entry" labelPlacement="top" click="myWebService.addEntry_send(); clearInputFields()"/>
...

On the click event for the Find entry button, call the findEntry_send() method to pass the request to the service, as the following code snippet shows:

...
<mx:Button label="Add entry" labelPlacement="top" click="myWebService.addEntry_send(); clearInputFields()"/>
...

In a Form control, bind the results of the findEntry operation to Form fields:

...
                <mx:HBox id="hbResults" x="10" y="70" width="100%" verticalAlign="middle" borderStyle="solid" visible="true">
                    <mx:Label text="Results:"/>
                    <!-- In the form that we use to display the data that is returned by the web service, we bind each 
                        member of the last result returned for the findEntry operation to its corresponding text control. -->
                    <mx:Form width="293" height="181" borderStyle="solid">
                        <mx:FormItem label="Name">
                            <mx:Text id="txNameOutput" text="{myWebService.findEntry_lastResult.name}"/>
...
                    </mx:Form>
                </mx:HBox>
...

The following example shows the complete MXML-centric address book application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ws="com.adobe.*">
    <mx:Script>
        <![CDATA[
            /**
                @private
                
                This method clears the input fields from the Add Entry view. 
            */
            private function clearInputFields():void {
                tiNameInput.text = "";
                tiCityInput.text = "";
                tiStreetInput.text = "";
                tiStateInput.text = "";
                tiPostalCodeInput.text = "";
            }
            
        ]]>
    </mx:Script>

    <!-- This is how we create an instance of the AddressBookService generated class.-->
    <ws:AddressBookService id="myWebService">
        <!-- We need to specify the request variables that are passed to the corresponding operations. -->
        <ws:addEntry_request_var>
            <!-- The addEntry operation has one input parameter. This parameter's type is Entry. -->
            <ws:AddEntry_request>                
                <ws:param0>
                    <ws:Entry>
                        <!-- We bind each of the members of an Entry object to the corresponding text input field. -->
                        <ws:name>{tiNameInput.text}</ws:name>
                        <ws:city>{tiCityInput.text}</ws:city>
                        <ws:street>{tiStreetInput.text}</ws:street>
                        <ws:state>{tiStateInput.text}</ws:state>
                        <ws:postalCode>{tiPostalCodeInput.text}</ws:postalCode>
                    </ws:Entry>
                </ws:param0>                
            </ws:AddEntry_request>
        </ws:addEntry_request_var>
        
        <!-- The findEntry operation has one input parameter of the String type. -->
        <ws:findEntry_request_var>
            <!-- We bind the corresponding text input field to the operation's input parameter.
              Since the operation's input parameter has a simple type, you can use the following syntax to do the data binding.
              Alternatively you could do: 
              <ws:FindEntry_request>
                <ws:param0>{tiSearch.text}</ws:param0>
              </ws:FindEntry_request>    
              -->              
            <ws:FindEntry_request param0="{tiSearch.text}">
            </ws:FindEntry_request>

        </ws:findEntry_request_var>
    </ws:AddressBookService>
        
    <mx:Panel width="640" height="480" layout="absolute" verticalCenter="0" horizontalCenter="0" title="AddressBook Client App">
        <mx:TabNavigator x="10" y="10" width="100%" height="100%">
            <mx:Canvas label="Add" width="100%" height="100%" id="tabAdd">
                <mx:HBox x="10" y="10" width="100%" verticalAlign="middle" borderStyle="solid">
                    <mx:Label text="New entry details:"/>
                    <mx:Form width="293" height="181" borderStyle="solid">
                        <mx:FormItem label="Name">
                            <mx:TextInput id="tiNameInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="City">
                            <mx:TextInput id="tiCityInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="Street">
                            <mx:TextInput id="tiStreetInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="State">
                            <mx:TextInput id="tiStateInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="Postal Code">
                            <mx:TextInput id="tiPostalCodeInput"/>
                        </mx:FormItem>
                    </mx:Form>
                    <!-- On the click event for the Add entry button, we call the addEntry_send() method of the web service that we defined earlier. -->
                    <mx:Button label="Add entry" labelPlacement="top" click="myWebService.addEntry_send(); clearInputFields()"/>
                </mx:HBox>
            </mx:Canvas>
            <mx:Canvas label="Search" width="100%" height="100%" id="tabSearch">
                <mx:HBox x="10" y="10" width="100%">
                    <mx:Label text="Name"/>
                    <mx:TextInput id="tiSearch"/>
                    <!-- On the click event for the 'Find entry' button we call the 'findEntry_send()' method of the web service we defined earlier. -->
                    <mx:Button label="Find entry" click="myWebService.findEntry_send()"/>
                </mx:HBox>
                <mx:HBox id="hbNoResults" x="10" y="40" height="22" visible="false">
                    <mx:Text text="'No entry was found!"/>
                </mx:HBox>
                <mx:HBox id="hbResults" x="10" y="70" width="100%" verticalAlign="middle" borderStyle="solid" visible="true">
                    <mx:Label text="Results:"/>
                    <!-- In the form that we use to display the data that is returned by the web service, we bind each 
                        member of the last result returned for the findEntry operation to its corresponding text control. -->
                    <mx:Form width="293" height="181" borderStyle="solid">
                        <mx:FormItem label="Name">
                            <mx:Text id="txNameOutput" text="{myWebService.findEntry_lastResult.name}"/>
                        </mx:FormItem>
                        <mx:FormItem label="City">
                            <mx:Text id="txCityOutput" text="{myWebService.findEntry_lastResult.city}"/>
                        </mx:FormItem>
                        <mx:FormItem label="Street">
                            <mx:Text id="txStreetOutput" text="{myWebService.findEntry_lastResult.street}"/>
                        </mx:FormItem>
                        <mx:FormItem label="State">
                            <mx:Text id="txStateOutput" text="{myWebService.findEntry_lastResult.state}"/>
                        </mx:FormItem>
                        <mx:FormItem label="Postal Code">
                            <mx:Text id="txPostalCodeOutput" text="{myWebService.findEntry_lastResult.postalCode}"/>
                        </mx:FormItem>
                    </mx:Form>
                </mx:HBox>
            </mx:Canvas>
        </mx:TabNavigator>
    </mx:Panel>
</mx:Application>

Calling a service with ActionScript

For an ActionScript-centric application, you create an instance of the web service in ActionScript, as the following code snippet shows:

...
<mx:Script>
    <![CDATA[
        import com.adobe.*;
        import mx.rpc.events.FaultEvent;
        import mx.controls.Alert;
        
        // Declare an instance of the generated web service class.
        public var agenda:AddressBookService;
        public function initApp():void
        {
            // Instantiate the new object.
            agenda = new AddressBookService();
            
...
        }
...

If you are using a LiveCycle Data Services ES destination, you pass the destination name to the service as a parameter of the constructor.

Add a result event listener (a function that you have previously defined) for the operation to call, as the following code snippet shows:

agenda.addEntryEventListener(myResultHandlingFunction);

In the addEntry() method, call the addEntry operation of the service and pass the correct values as arguments, as the following example shows:

agenda.addEntry(myparam0);

In the searchEntry() method, call the findEntry operation of the service and bind the results of the findEntry operation to Form fields:

...
        /**
        * The handleSearchResult() method is the result event handler for the 
        * findEntry operation.
        * It displays the address of a given person by populating the corresponding
        * Form fields with the members of the strongly typed Entry result that 
        * you get when the call to the operation succeeds. Or, if we have no record of the person's address, a message is displayed that 
        * no entry was found. 
        */
        public function handleSearchResult(event:FindEntryResultEvent):void
        {
            if(event.result != null) {
                // Instantiate a new Entry object with the result that we got from the call. 
                var res:Entry = event.result;
                
                // Populate the result Form fields with the corresponding data.
                txNameOutput.text = res.name;
                txCityOutput.text = res.city;
                txStreetOutput.text = res.street;
                txStateOutput.text = res.state;
                txPostalCodeOutput.text = res.postalCode;
                
                // Make sure that the no entry found message is not displayed.
                hbNoResults.visible = false;
                
                // Show the results.
                hbResults.visible = true;
                
                // Clear the search name field
                tiSearch.text = "";
            }
            else {
                // Display the no entry found message.
                hbNoResults.visible = true;
                
                // Hide any previous results.
                hbResults.visible = false;
            }
        }
...

The following example shows the complete ActionScript-centric address book application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
<mx:Script>
    <![CDATA[
        import com.adobe.*;
        import mx.rpc.events.FaultEvent;
        import mx.controls.Alert;
        
        // Declare an instance of the generated web service class.
        public var agenda:AddressBookService;
        
        /**
        * In the initApp() method we will create a new web service object and
        * add the fault event listener for that web service.
        * Unlike the event listeners, we get only one fault event listener per 
        * web service class, as opposed to the event listeners that we get for each
        * operation that returns something.
        */
        public function initApp():void
        {
            // Instantiate the new object.
            agenda = new AddressBookService();
            
            // Register the fault event listener method. 
            agenda.addAddressBookServiceFaultEventListener(handleFaults);
        }
        
        /**
        * The addEntry() method is used to call the addEntry web service operation.
        * The method gets called when the user clicks the Add Entry button. 
        * It builds an Entry object by using the data that the user has provided, calls the 
        * web service operation and passes along the strong typed parameter, and then
        * clears the user input fields to provide the visual hint that an action has been taken.
        */
        public function addEntry():void
        {
            // Instantiate a new Entry object.
            var newEntry:Entry = new Entry();

            // Use the data that the user has provided to populate the Entry object.
            newEntry.name = tiNameInput.text;
            newEntry.city = tiCityInput.text;            
            newEntry.street = tiStreetInput.text;
            newEntry.state = tiStateInput.text;
            newEntry.postalCode = tiPostalCodeInput.text; 
            
            // Call the addEntry operation directly from the web service class instance and
            // pass along the required parameter.
            agenda.addEntry(newEntry);
            
            // Clear the user input fields.
            clearInputFields();
        }
        
        private function clearInputFields():void {
            tiNameInput.text = "";
            tiCityInput.text = "";
            tiStreetInput.text = "";
            tiStateInput.text = "";
            tiPostalCodeInput.text = "";
        }
        
        /**
        * The handleFaults() method is a very basic fault event handler method that
        * displays an Alert with the error message.
        */
        public function handleFaults(event:FaultEvent):void
        {
            Alert.show("A fault occured contacting the server. Fault message is: " + event.fault.faultString);
        }
        
        /**
        * The searchEntry() method is used to call the findEntry web service operation.
        * It gets called when the user clicks the Find Entry button.
        * It adds the specific findEntry event listener, and if the user has provided a name
        * it makes a call to the web service operation with the provided name.
        */
        public function searchEntry(name:String):void
        {
            // Register the event listener for the findEntry operation.
            agenda.addfindEntryEventListener(handleSearchResult);
            
            // Call the operation if we have a valid name.
            if(name!= null && name.length > 0)
                agenda.findEntry(name);    
        }
        
        /**
        * The handleSearchResult() method is the result event handler for the 
        * findEntry operation.
        * It displays the address of a given person by populating the corresponding
        * form fields with the members of the strongly typed Entry result that 
        * you get when the call to the operation succeeds. Or, if we have no record of a person's address, a message is displayed that 
        * no entry was found.the 
        */
        public function handleSearchResult(event:FindEntryResultEvent):void
        {
            if(event.result != null) {
                // Instantiate a new Entry object with result that we got from the call. 
                var res:Entry = event.result;
                
                // Populate the result form fields with the corresponding data.
                txNameOutput.text = res.name;
                txCityOutput.text = res.city;
                txStreetOutput.text = res.street;
                txStateOutput.text = res.state;
                txPostalCodeOutput.text = res.postalCode;
                
                // Make sure that the no entry found message is not displayed.
                hbNoResults.visible = false;
                
                // Show the results.
                hbResults.visible = true;
                
                // Clear the search name field.
                tiSearch.text = "";
            }
            else {
                // Display the no entry found message.
                hbNoResults.visible = true;
                
                // Hide any previous results. 
                hbResults.visible = false;
            }
        }
    ]]>
</mx:Script>    
    <mx:Panel width="640" height="480" layout="absolute" verticalCenter="0" horizontalCenter="0" title="AddressBook Client App">
        <mx:TabNavigator x="10" y="10" width="100%" height="100%">
            <mx:Canvas label="Add" width="100%" height="100%" id="tabAdd">
                <mx:HBox x="10" y="10" width="100%" verticalAlign="middle" borderStyle="solid">
                    <mx:Label text="New entry details:"/>
                    <mx:Form width="293" height="181" borderStyle="solid">
                        <mx:FormItem label="Name">
                            <mx:TextInput id="tiNameInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="City">
                            <mx:TextInput id="tiCityInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="Street">
                            <mx:TextInput id="tiStreetInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="State">
                            <mx:TextInput id="tiStateInput"/>
                        </mx:FormItem>
                        <mx:FormItem label="Postal Code">
                            <mx:TextInput id="tiPostalCodeInput"/>
                        </mx:FormItem>
                    </mx:Form>
                    <mx:Button label="Add entry" labelPlacement="top" click="addEntry()"/>
                </mx:HBox>
            </mx:Canvas>
            <mx:Canvas label="Search" width="100%" height="100%" id="tabSearch">
                <mx:HBox x="10" y="10" width="100%">
                    <mx:Label text="Name"/>
                    <mx:TextInput id="tiSearch"/>
                    <mx:Button label="Find entry" click="searchEntry(tiSearch.text);"/>
                </mx:HBox>
                <mx:HBox id="hbNoResults" x="10" y="40" height="22" visible="false">
                    <mx:Text text="'No entry was found!"/>
                </mx:HBox>
                <mx:HBox id="hbResults" x="10" y="70" width="100%" verticalAlign="middle" borderStyle="solid" visible="false">
                    <mx:Label text="Results:"/>
                    <mx:Form width="293" height="181" borderStyle="solid">
                        <mx:FormItem label="Name">
                            <mx:Text id="txNameOutput"/>
                        </mx:FormItem>
                        <mx:FormItem label="City">
                            <mx:Text id="txCityOutput"/>
                        </mx:FormItem>
                        <mx:FormItem label="Street">
                            <mx:Text id="txStreetOutput"/>
                        </mx:FormItem>
                        <mx:FormItem label="State">
                            <mx:Text id="txStateOutput"/>
                        </mx:FormItem>
                        <mx:FormItem label="Postal Code">
                            <mx:Text id="txPostalCodeOutput"/>
                        </mx:FormItem>
                    </mx:Form>
                </mx:HBox>
            </mx:Canvas>
        </mx:TabNavigator>
    </mx:Panel>
</mx:Application>

Working with special types

In addition to the simple classes that the code generator creates for WSDL-defined complex types and request and result event wrappers, special classes are generated for the following types:

  • Simple types that enumerate accepted values
  • Array types

Generated code for simple types, enumerations, and restrictions

When the code generator introspects a WSDL document and encounters the definition of a simple type that is a restriction of a certain type, and the WSDL provides a list of accepted values, the generated ActionScript model exposes the acceptable values. To do so, the actual value has [Inspectable] metadata attached to it. When using MXML syntax, the values read from the WSDL document are proposed as hints, and any other values are rejected by the compiler.

As an example, consider the definition of a simple type that is a string with possible length unit values. Its definition inside the WSDL document is:

<s:simpleType name="Lengths">
    <s:restriction base="s:string">
        <s:enumeration value="Angstroms"/> 
        <s:enumeration value="Nanometers"/> 
        <s:enumeration value="Microinch"/>
        <s:enumeration value="Microns"/> 
        <s:enumeration value="Mils"/> 
</s:restriction>
</s:simpleType>

The code generator translates this into an ActionScript class called Lengths.as with a single member (_Lengths), of type String. Inside the generated class, it also adds the[Inspectable] metadata with the values it read from the WSDL document, as the following example shows:

public class Lengths
{
    /**
    * Constructor, initializes the type class.
    */
    public function Lengths() {}
        [Inspectable(category="Generated values",
        enumeration="Angstroms,Nanometers,Microinch,Microns,Mils", type="String")]
        public var _Lengths:String;
        public function toString():String {
        return _Lengths.toString();
    }
)

Generated code for array types

When an operation must return an array of a specific type and it is defined as a complex type inside the WSDL document, a class is generated for it. This class extends mx.collections.ArrayCollection and implements all of the utility methods that are defined in the base class. To make it easier to see what the underlying type of the array is, all of the methods are slightly modified from their original. For example, getItemAt(index:int) becomes getBaseTypeAt(index:int), getItemIndex(item:Object) becomes getBaseTypeIndex(item:BaseType), and so on.

Consider the following structure:

<s:complexType name="ArrayOfAlert">
    <s:sequence>
        <s:element minOccurs="0" maxOccurs="unbounded" name="Alert" type="tns:Alert" />
    </s:sequence> 
</s:complexType>

This structure results in the following generated class:

public class ArrayOfAlert extends ArrayCollection {
/**
    * Constructor - initializes the array collection based on a source array
    */
    public function ArrayOfAlert(source:Array = null) {
        super(source);
    }
    public function addAlertAt(item:Alert,index:int):void {
        addItemAt(item,index);
    }
    public function addAlert(item:Alert):void {
        addItem(item);
    }
    public function getAlertAt(index:int):Alert {
        return getItemAt(index) as Alert;
    }
    public function getAlertIndex(item:Alert):int {
        return getItemIndex(item);
    }
    public function setAlertAt(item:Alert,index:int):void {
        setItemAt(item,index);
    }
    public function asIList():IList {
        return this as IList;
    }
    public function asICollectionView():ICollectionView {
        return this as ICollectionView;
    }
}

One exception to this naming rule happens when the base type is another complex type named Item. This causes the generation of methods that override the ones implemented in the base class, but without actually specifying it. In this case, the base type is renamed to MyItem, inside method names. When used as actual argument type, the base type name is left unchanged.

Adding a header to an operation call and getting the header from an operation result

Operations defined in a WSDL document can optionally have headers attached to them, either when calling an operation or when returning the result. The code that Flex Builder generates lets the user handle both the request headers and the result headers.

Request headers

If the WSDL document defines request headers for an operation, the generated code has the following extra methods for each operation:

setOperationName_header() Sets the operation's request header. You must pass it the exact header object that the operation expects.

getOperationName_header() Gets the object that was previously passed as the operation header.

addOperationName_header(header_arguments:headerType) Adds a new header item for the operation. This is the preferred way of adding headers becaue it automatically takes care of encoding the header and you need to provide only a strong typed object, the method argument.

You can add a request header to an operation call, as the following example shows:

...
public function doCall():void {
    var myHeader:LicenseInfo = new LicenseInfo()
    //Or use the keywordSearchRequest_header property to set the value.
    myService.addkeywordSearchRequest_header(myHeader);
    myService.addkeywordSearchRequestEventListener(handleResults);
    myService.keywordSearchRequest(inputParams);
}
...

Result headers

Some operations also return information in headers along with the actual result. You can retrieve the array of headers by accessing the headers property on the typed result event, inside the operation's result event handler, as the following example shows:

...
public function doCall():void {
    myService.addkeywordSearchRequestEventListener(handleResults);
    myService.keywordSearchRequest(inputParams);
}
public function handleResult(event:KeywordSearchRequestResultEvent):void {
    trace(event.result.TotalResults); //do something with the result
    trace(event.headers); //do something with the result headers
} 

Handling the result of an operation call

After calling a web service operation, you must retrieve the result and manipulate it. The result of a web service call can be either a SOAP-encoded response or a SOAP fault that contains an error.

To facilitate access to the response of a web service operation call, the code generator also creates some typed event classes. Because Flex operates asynchronously, you must use events to be notified of the result or fault. You can do this in any of the following ways:

  • By using the token returned when the operation call is placed
  • By using the utility methods defined on the typed service
  • By binding elements via MXML to the service's lastResult property

Using a return token

When the call to the operation is made, the user gets an AsyncToken object returned immediately. This can be used to attach event listeners (methods that are executed when a specific event occurs), by using syntax like the following example:

...
private function doCall():void {
    var ret:AsyncToken;
    ret = myService.keywordSearchRequest(input);
    ret.addEventListener
        (KeywordSearchRequestResultEvent.KeywordSearchRequest_RESULT,handleResult);
    ret.addEventListener(FaultEvent.FAULT,handleFaults);
}
...

In this example, the handleResult() and handleFaults() methods are user-defined methods. When using this approach, the result handling method has an argument of type ResultEvent, instead of a strongly typed, operation-specific event, as in the following example:

public function handleResults(event:ResultEvent):void {
    trace(event.result); //do something with the result
}

Using utility methods

Through metadata, the service provides a list of events to which the user can listen. There is a single unified fault event, and one result event for each operation. This is because each operation returns a different type of result, but the fault is the same for all. The service provides the following utility methods for attaching event listeners to an operation call:

  • The method to add the fault event listener for the service, as the following example shows:
    public function addSearchServiceFaultEventListener(listener:Function):void
    
    
  • The method on each operation to add the listener to process the result, as the following example shows:
    public function addkeywordSearchRequestEventListener(listener:Function):void
    
    

The types of events that the service exposes are available via code hints and as metadata on the service. Each event metadata is commented and exposes the method that dispatches it, as the following example shows:

/**
 * Dispatched when a call to the operation KeywordSearchRequest completes successfully 
 * and returns some data.
 * @eventType KeywordSearchRequestResultEvent
 */
[Event(name="KeywordSearchRequest_result", type="KeywordSearchRequestResultEvent")]

When using this approach, the result handling method takes the strongly typed, operation-specific event, as the following example shows:

public function handleResults(event:KeywordSearchRequestResultEvent):void 
{
      trace(event.result);    //do something with the result
}

Using MXML binding

The generated service class exposes for each operation a specific property, operationName_lastResult, which is populated each time the result of the operation call is returned. You can bind this property through MXML, and when the operation returns a value, it automatically populates all bound items. The following example shows a binding to operationName_lastResult in an MXML tag:

<mx:Text text={myService.keywordSearchRequest_lastResult} />