Tải bản đầy đủ (.pdf) (50 trang)

Tài liệu Flash Builder 4 and Flex 4 Bible- P16 pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (636.6 KB, 50 trang )

Chapter 23: Working with HTTPService and XML
721
8. Save and run the application. As shown in Figure 23.9, you should see that the applica-
tion automatically retrieves and displays the data upon startup.
FIGURE 23.9
Data returned using code generated by Flash Builder
Listing 23.2 shows the completed application code. Notice that the use of the generated service
and value object classes makes the application code itself very simple.
LISTING 23.2
A completed application using generated HTTP data connection code
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”
xmlns:contactservice=”services.contactservice.*”>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.controls.Alert;
protected function dataGrid_creationCompleteHandler(
event:FlexEvent):void
{
getContactsResult.token = contactService.getContacts();
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
continued
30_488959-ch23.indd 72130_488959-ch23.indd 721 3/5/10 2:38 PM3/5/10 2:38 PM


Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
722
LISTING 23.2
(continued)
<fx:Declarations>
<s:CallResponder id=”getContactsResult”/>
<contactservice:ContactService id=”contactService”
fault=”Alert.show(event.fault.faultString)” showBusyCursor=”true”/>
</fx:Declarations>
<mx:DataGrid id=”dataGrid”
creationComplete=”dataGrid_creationCompleteHandler(event)”
dataProvider=”{getContactsResult.lastResult}” editable=”true”>
<mx:columns>
<mx:DataGridColumn headerText=”First Name” dataField=”firstname”/>
<mx:DataGridColumn headerText=”Last Name” dataField=”lastname”/>
<mx:DataGridColumn headerText=”Email” dataField=”email”/>
<mx:DataGridColumn headerText=”Phone” dataField=”phone”/>
</mx:columns>
</mx:DataGrid>
</s:Application>
Declaring and Configuring
HTTPService Objects
While the new code generation tools are fast and easy to use and generate code that’s adequate for
most simple Flex applications, it’s also important to understand how the generated code works. In
the next sections of this chapter I describe the
HTTPService and CallResponder components
and detail how to use them in a data-centric Flex application.
You can declare and configure an
HTTPService object in either MXML or ActionScript code. For

applications that communicate only with a single network resource, the MXML approach might be
simpler and easier to implement. In more complex applications that use multiple network
resources, ActionScript classes and methods that dynamically generate
HTTPService objects as
needed can be easier to manage.
Creating an HTTPService object
The MXML syntax to create an HTTPService object looks like this:
<fx:Declarations>
<s:HTTPService id=”myService” url=”data/contacts.xml”/>
</fx:Declarations>
As with all Flex components, the object’s id property is used to identify it uniquely in the context
of the current application or component. The
url property (discussed in detail in the next section)
can be set with either a literal
String, as in this example, or with a binding expression if you
want to be able to switch to a different network resource at
runtime.
30_488959-ch23.indd 72230_488959-ch23.indd 722 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
723
New Feature
As with all nonvisual components, an HTTPService object declared in MXML must be wrapped in an
<fx:Declarations> element in Flex 4.
n
Note
The HTTPService and other RPC classes are declared in the both the MX and the Spark MXML manifests, so
you can use either the
mx: or the s: prefix. Flash Builder auto-completes these declarations with the s: prefix
by default.

n
The equivalent ActionScript code looks like this:
import mx.rpc.http.HTTPService;
private var myService:HTTPService =
new HTTPService(“data/contacts.xml”);
Alternatively, you can declare the object first and then set its url in a separate statement:
private var myService:HTTPService = new HTTPService();
myService.url = “data/contacts.xml”;
The Flex framework’s class library has two HTTPService classes. The first, which is imported in
the preceding example, is a member of the
mx.rpc.http package and is used in ActionScript
code. The other version of the
HTTPService class is a subclass of the first and is a member of the
mx.rpc.http.mxml package. This is the version you use when you instantiate the object with
the
<s:HTTPService> tag.
The versions are nearly identical with only one difference. The MXML version implements an
initialized() method that’s designed to be called after the object’s instantiation. When you
declare the
HTTPService object in MXML, this method is called automatically; you only need to
call it yourself if you instantiate this version of the class in ActionScript code.
New Feature
In Flex 3, the showBusyCursor property, which causes an animated cursor to be displayed for the duration
of an
HTTPService request/response cycle, and the concurrency property, which determines how multi-
ple concurrent requests to the same network resource are handled, were declared in the MXML version of
HTTPService. In Flex 4, these have been moved to the superclass,
mx.rpc.http.HTTPService, and are
therefore available regardless of how you declare or instantiate the RPC object.
n

Tip
ActionScript-based declarations of HTTPService should be placed outside of any function declarations, so
that the object is accessible from all functions in the current application or component.
n
Essential HTTPService properties
Whether you use the MXML or ActionScript approach, the HTTPService component implements
these properties that determine where the request is made and what HTTP methods are used:
30_488959-ch23.indd 72330_488959-ch23.indd 723 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
724
l
concurrency:String. A rule that determines how to handle multiple concurrent calls
to the same network resource.
l
method:String. The HTTP method to be used.
l
resultFormat:String. The format in which the data should be returned.
l
showBusyCursor:Boolean. When true, causes an animated cursor to appear for the
duration of the request/response cycle.
l
url:String. The Web address to which the request is sent.
The details of these properties are described in the following sections.
Setting the url property
The url property is set to the network address to which the HTTP service should be sent. For a
Flex application designed for Web deployment, this can be either a relative or absolute address.
For example, if the Flex application is retrieving a static XML file that’s on the same server and
within the same directory structure, the
url could be set as follows:

myHTTPService.url = “data/contacts.xml”;
For Web-based applications, the expression data/contacts.xml means that the XML file is in
a
data subfolder on the same server from which the Flex application downloads at runtime.
For desktop applications deployed with Adobe AIR, or for Web applications that need to retrieve
data from a domain other than one from which the application is downloaded, you can set the
url
as an absolute address. This statement sets
url to an absolute location on the Web:
myHTTPService.url = “ />And this sets the location to a file in the application’s installed files directory in an Adobe AIR
application:
var f:File = File.applicationDirectory.resolvePath(
“data/contacts.xml”);
myHTTPService.url = f.nativePath;
Caution
If you need to retrieve content at runtime from a different domain on the Web, you may need to deal with
Flash Player’s cross-domain security constraint. See the information on using the cross-domain permissions file
later in this chapter and how to use the Proxy Service that’s included with LiveCycle Data Services and
BlazeDS in Chapter 26.
n
The network resource to which you send an HTTPService request can be either a static text file
or a dynamic application server page that generates a response upon demand. As long as the
response is in a form that the
HTTPService component is able to parse (usually a well-formed
XML file), the response will be read and understood when it’s received from the server.
30_488959-ch23.indd 72430_488959-ch23.indd 724 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
725
Setting the method property

The HTTPService component’s method property supports the following values:
l
GET (the default)
l
POST
l
PUT (only with AIR or a proxy service)
l
DELETE (only with AIR or a proxy service)
l
OPTIONS (only with a proxy service)
l
HEAD (only with a proxy service)
l
TRACE (only with a proxy service)
In RPC-style applications, the
HTTPService component is mostly used with the GET and POST
methods, while REST-style approaches sometimes use
PUT and DELETE requests.
Caution
Flash Player 10 only supports HTTP requests with methods of GET and POST. Desktop applications deployed
with AIR also can use the
PUT and DELETE request methods. To use PUT and DELETE requests in a Web
application, or any other request methods, you must send requests through a server-side proxy such as the
Proxy Service provided by LiveCycle Data Services and BlazeDS (described in Chapter 24).
n
For example, Flex developers who use Ruby on Rails as their application server sometimes follow a
RESTful pattern where the
HTTPService method determines what kind of data manipulation is
being requested by the client application. Each of the following methods is treated as a “verb” that

indicates what should be done with the data passed in the request:
l
DELETE request. Results in deleting existing data in the server tier.
l
GET request. Retrieves a representation of data without making any changes to the ver-
sion in the server’s persistent data store.
l
POST request. Results in creating a new data item in the server tier.
l
PUT request. Results in modifying existing data in the server tier.
Web Resource
For more information on using a RESTful approach with Ruby on Rails, visit the Ruby documentation at
An article by
Derek Wischusen on integrating HTTPService and Ruby on Rails is available at
www.adobe.com/devnet/
flex/articles/flex2_rails_print.html
.
n
Tip
The resthttpservice library, available at is a free
open-source Flex component that’s fully REST-aware and can serve as a replacement for the
HTTPService
class. A tutorial about it is available online at:
/> flex-and-rest-is-it-time-to-scrub-out-soap.html.
n
30_488959-ch23.indd 72530_488959-ch23.indd 725 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
726
Setting the resultFormat property

The resultFormat property determines how data is exposed in the Flex application when it’s
received from the server. The possible values are listed here:
l
array. The top-level object is returned as the first item in an ActionScript Array.
l
e4x. Well-formed XML is returned as an ActionScript XML object that can be parsed and
modified with EcmaScript for XML (E4X) syntax.
l
flashvars. Data formatted as name/value pairs is parsed into an ActionScript Object
with named properties. For example, the following
String value is a well-formed
flashvars value:
firstName=Joe&lastName=Smith
l
object (the default). Well-formed XML is returned as a tree of ActionScript objects.
When a single element exists in a particular level of the XML hierarchy with a particular
name, it’s returned as an instance of the
ObjectProxy class; when multiple elements of
the same name are returned, they’re wrapped in an
ArrayCollection.
l
text. The response is returned as a simple String value.
l
xml. Well-formed XML is returned as an ActionScript XMLNode object that can be parsed
with Document Object Model (DOM) code.
The resulting ActionScript
Object would have two properties named firstName and
lastName.
Cross-Reference
The use of E4X to parse well-formed XML is described in Chapter 24.

n
Setting the concurrency property
The concurrency property is implemented only with the MXML version of the HTTPService
component and determines how the responses from multiple concurrent requests will be handled.
The property’s possible values are listed here:
l
last. Issuing another request before the last one was completed results in canceling the
first request.
l
multiple (the default). Multiple responses are handled as they’re received from the
server, and it’s up to you (the developer) to create a code pattern that enables you to iden-
tify the responses for each request. The
AsyncToken class, an instance of which is
returned from the
send() method, can be helpful in this circumstance.
l
single. You can have only a single request active at any given time. Issuing another
request before the last one was completed results in a runtime error.
The following code results in canceling any pending
HTTPService requests when a new request
is sent:
<s:HTTPService id=”myService”
url=”data/contacts.xml”
concurrency=”last”/>
30_488959-ch23.indd 72630_488959-ch23.indd 726 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
727
Sending and Receiving Data
You send an HTTP request with the HTTPRequest object’s send() method. For example, if you

want to retrieve data upon application startup, you can call the
send() method in the applica-
tion’s
creationComplete event handler:
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”
creationComplete=»myService.send()»>
<fx:Declarations>
<s:HTTPService id=”myService” url=”data/contacts.xml”/>
</fx:Declarations>
</s:Application>
Alternatively, you can send the request upon a user event, such as the click event handler of a
Button component:
<s:Button label=”Make request” click=”service.send()”/>
Note
The send() method accepts an optional parameters argument typed as an Object that enables you to
send parameters to dynamic application server pages. I describe this technique later in this chapter.
n
Understanding asynchronous communications
All the Flex framework’s RPC components send and receive data asynchronously. This means that
when you send a request, Flash Player’s ActionScript Virtual Machine (AVM) doesn’t pause in its
code execution and wait for data to be returned. This architecture is similar to how a Web brows-
er’s
XMLHttpRequest object handles JavaScript requests for data: Requests are sent, and the
responses are handled through event listeners.
For ColdFusion developers, Flex’s
HTTPService and ColdFusion’s <cfhttp> tags behave dif-
ferently. ColdFusion handles responses to its
<cfhttp> command synchronously, meaning that it

waits for data to be returned before going to the next line of code. Two major differences between
the runtime environments account for this.
First, ColdFusion pages are transient and stay in server memory only until they’ve generated and
returned HTML to the requesting Web browser. Asynchronous operations require a runtime envi-
ronment that stays in memory and can listen for a response. Also, ColdFusion is multithreaded and
can afford to allocate a thread to wait for a response. Flash Player is single-threaded; if it had to
wait for a response, the application would have to suspend all other operations such as animations
and user interactions until the data came back.
Handling HTTPService responses
You can handle the response from a server with two approaches:
30_488959-ch23.indd 72730_488959-ch23.indd 727 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
728
l
With a binding expression that references returned data
l
With event listeners that execute ActionScript code when data is returned
Of these approaches, the binding expression is simpler and easier to code, but it gives much less
flexibility and power in terms of how you handle the returned data. In contrast, the event listener
architecture gives you the opportunity to debug, inspect, manipulate, and save returned data
persistently.
Using a binding expression
The HTTPService component’s lastResult property is a reference variable that gives you
access to the data that’s returned from the server. When the service object’s
resultFormat prop-
erty is set to the default value of
object and you retrieve well-formed XML, the expression
myService.lastResult refers to an instance of the ObjectProxy class that represents the
XML document.

The following code represents the contents of an XML file named
contacts.xml:
<?xml version=”1.0”?>
<contacts>
<row>
<contactid>1</contactid>
<firstname>Brad</firstname>
<lastname>Lang</lastname>
<streetaddress>3004 Buckhannan Avenue</streetaddress>
<city>Syracuse</city>
<state>NY</state>
<email></email>
<phone>315-449-9420</phone>
</row>
additional <row> elements
</contacts>
When an XML file is structured with multiple repeating elements of the same name, as is the case
with the
<row> element in this XML structure, the HTTPService components generates an
ArrayCollection that “wraps” the data. To display the data from a DataGrid or other data visu-
alization component, use a binding expression that starts with the
HTTPService object’s id and
lastResult property and then “walks” down the XML hierarchy to the repeating element name.
The following
DataGrid component uses the content of the repeating <row> elements as its data
provider:
<mx:DataGrid dataProvider=”{contactService.lastResult.data.row}”/>
Try these steps in the chapter23 project:
1. Open contacts.xml file from the project’s src/data folder. Notice that the XML
file has a root element named

<contacts> and repeating elements named <row>. Each
<row> element has a consistent internal structure consisting of named properties for con-
tactId
, firstname, lastname, and so on.
30_488959-ch23.indd 72830_488959-ch23.indd 728 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
729
2. Create a new MXML application named HTTPServiceWithBindings.mxml and
view it in Source mode.
3. Set its layout property to an instance of <s:VerticalLayout> with
horizontalAlign set to center.
<s:layout>
<s:VerticalLayout horizontalAlign=”center”/>
</s:layout>
4. Add an <fx:Declarations> element after the closing </s:layout> tag.
5. Add an <s:HTTPService> tag set between the <fx:Declarations> tags. Set its
id to contactService and its url property to data/contacts.xml:
<s:HTTPService id=”contactService”
url=”data/contacts.xml”/>
6. Add an <s:Button> component below the <s:HTTPService> tag. Set its label to Get
Data and its
click event listener to call the HTTPService object’s send() method:
<s:Button label=”Get Data” click=”contactService.send()”/>
7. Add a DataGrid component below the <mx:Button> tag. Set its dataProvider to
display the
HTTPService component’s returned data using a binding expression that
references the XML file’s repeating
<row> elements:
<mx:DataGrid

dataProvider=”{contactService.lastResult.contacts.row}”/>
8. Run the application, and click the Get Data button to send the request. You should
see the XML file’s data displayed in the
DataGrid, as shown in Figure 23.10.
The completed application is shown in Listing 23.3
LISTING 23.3
Using a binding expression to display retrieved data
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contacts.xml”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”contactService.send()”/>
<mx:DataGrid
dataProvider=”{contactService.lastResult.contacts.row}”/>
</s:Application>
30_488959-ch23.indd 72930_488959-ch23.indd 729 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
730
FIGURE 23.10
Data retrieved from the XML file and displayed in the DataGrid
On the Web
The code in Listing 23.3 is available in the Web site files as HTTPWithBindingsComplete.mxml in the src
folder of the

chapter23 project.
n
Tip
When you retrieve content from the local hard disk instead of a Web server, a file access runtime error might
occur. To fix this issue, you can place the application in a local security sandbox and block network access. You do
this in the project properties by adding the following compiler argument to the Flex project’s compiler arguments:
-use-network=false
n
Figure 23.11 shows the Flex Compiler section of the project properties screen with the additional
-use-network compiler argument.
Handling the result event
When data is returned from the remote server, the HTTPService object dispatches a result
event, whose event object is typed as
mx.rpc.events.ResultEvent. This ResultEvent
class has a
result property that refers to the returned data.
30_488959-ch23.indd 73030_488959-ch23.indd 730 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
731
FIGURE 23.11
Placing an application in the local sandbox to guarantee access to local files
Using local
sandbox
Note
The ResultEvent class also has a headers property that in theory should return the HTTP response headers
from the Web server. In practice, this object frequently returns
null.
n
To handle and save data using the result event, follow these steps:

1. Declare a bindable variable outside of any function that acts as a persistent refer-
ence to the returned data. If you’re expecting a set of repeating data elements, cast the
variable as an
ArrayCollection:
import mx.collections.ArrayCollection;
[Bindable]
private var myData:ArrayCollection
2. Create an event handler function that will be called when the event is dispatched. The
function should receive a single
event argument typed as ResultEvent and return void:
private function resultHandler(event:ResultEvent):void
{
}
30_488959-ch23.indd 73130_488959-ch23.indd 731 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
732
Tip
You can use Flash Builder 4’s new event handler generation capabilities to create the handler function auto-
matically. When you auto-complete the
result event in the HTTPService MXML declaration, Flash Builder
prompts you to generate the result handler. It then creates the event handler function with the method signa-
ture described in the preceding step.
n
3. Within the event handler function, use the event.result expression to refer to the
data that’s returned from the server. Walk down the XML hierarchy to get to the
repeating data elements, and return that expression to the bindable
ArrayCollection
variable:
myData = event.result.contacts.row;

You can listen for the result event with either an MXML attribute-based event listener or a
call to the ActionScript
addEventListener() method. The attribute-based event listener
looks like this:
<s:HTTPService id=”contactService”
url=”http://localhost/contacts.xml”
result=”resultHandler(event)”/>
When using addEventListener() to create an event listener, you can designate the event
name with the
String value result or with the ResultEvent class’s RESULT constant:
var myService:HTTPService = new HTTPService();
myService.url = “data/contacts.xml”;
myService.addEventListener(ResultEvent.RESULT, resultHandler);
The application in Listing 23.4 retrieves a data set at runtime using an HTTPService object’s
result event. Data is saved to a persistent ArrayCollection variable that’s been marked as
[Bindable] and then displayed in a DataGrid using a binding expression.
LISTING 23.4
An application using the HTTPService component and a result event
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.collections.ArrayCollection;
[Bindable]

private var myData:ArrayCollection
30_488959-ch23.indd 73230_488959-ch23.indd 732 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
733
protected function contactService_resultHandler(
event:ResultEvent):void
{
myData = event.result.contacts.row;
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contacts.xml”
result=”contactService_resultHandler(event)”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”contactService.send()”/>
<mx:DataGrid dataProvider=”{myData}”/>
</s:Application>
On the Web
The code in Listing 23.4 is available in the Web site files as HTTPResultEvent.mxml in the src folder of
the
chapter23 project.
n
Tip
It may seem at first glance that the use of the result event simply takes more code than a binding expression.
Many advantages to this approach, however, make the extra code worthwhile. By processing the returned data
in an event handler function, you have the opportunity to debug or modify data when it’s returned to the
server, and the persistent variable enables you to refer to the data at any later point.
It’s also possible for a single service to return different data structures depending on which parameters are sent

in the request. In this case, binding directly to the results isn’t possible, because you have to extract data from
the result with expressions that can differ depending on the circumstance.
n
Handling the fault event
When an HTTPService request results in an error, the HTTPRequest object dispatches a
fault event, whose event object is typed as mx.rpc.events.FaultEvent. This event object
has a
fault property typed as mx.rpc.Fault, which has these properties:
l
faultCode:String. A code that indicates the nature of the fault and whether it
occurred in the client or server environment.
l
faultDetail:String. An additional message that sometimes contains useful information.
l
faultString:String. The error message.
l
message:String. A string consisting of all the previous values concatenated together
with
| characters used as separators.
When you debug a
fault event, you can easily see the structure of the event object. Figure
23.12 shows the Variables view during a debugging session showing the structure of the
FaultEvent and Fault objects.
30_488959-ch23.indd 73330_488959-ch23.indd 733 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
734
FIGURE 23.12
The Variables view displaying fault information during a debugging session
To handle a fault event, create an event handler function that receives an event argument typed

as
FaultEvent. Within the body of the function, you can deal with the fault however you like.
This suppresses the ugly error message that appears in response to unhandled faults in the debug
player. The following code collects fault information from the event object and displays it to the
user with an
Alert pop-up window:
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.faultString, event.fault.faultCode);
}
Figure 23.13 shows the resulting application with the Alert dialog box showing the user the
faultString and faultCode values.
As with the
result event, you can listen for the fault event with either an MXML attribute-
based event listener or the
addEventListener() method. The MXML attribute version looks
like this:
<s:HTTPService id=”contactService”
url=”data/contactsMalformed.xml”
result=”resultHandler(event)”
fault=”faultHandler(event)”/>
When using addEventListener() to create an event listener, you can designate the event
name with the
String value fault or with the FaultEvent class’s FAULT constant:
30_488959-ch23.indd 73430_488959-ch23.indd 734 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
735
var myService:HTTPService = new HTTPService();
myService.url = “data/contacts.xml”;

myService.addEventListener(ResultEvent.RESULT, resultHandler);
myService.addEventListener(FaultEvent.FAULT, faultHandler);
FIGURE 23.13
Displaying fault information to the user
The application in Listing 23.5 shows the use of the fault event with an MXML-based event
listener.
LISTING 23.5
Using the fault event
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
[Bindable]
private var myData:ArrayCollection
private function resultHandler(event:ResultEvent):void
continued
30_488959-ch23.indd 73530_488959-ch23.indd 735 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
736
LISTING 23.5

(continued)
{
myData = event.result.contacts.xml;
}
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.faultString, event.fault.faultCode);
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contactsMalformed.xml”
result=”resultHandler(event)”
fault=”faultHandler(event)”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”contactService.send()”/>
<mx:DataGrid dataProvider=”{contactService.lastResult.contacts.row}”/>
</s:Application>
On the Web
The code in Listing 23.5 is available in the Web site files as HTTPFaultEvent.mxml in the src folder of the
chapter23 project.
n
Tip
All RPC components, including HTTPService, implement a requestTimeout property that sets a timeout
value in terms of seconds. For example, if you set
requestTimeout to a value of 10 and the server doesn’t
respond within ten seconds, a
fault event is dispatched.
n
Note

The result and fault events work exactly the same for all RPC components and use the same set of event
classes,
ResultEvent and FaultEvent. The only significant difference lies in the structure of the data
returned in a
result event. For example, HTTPService, when used to retrieve XML, returns data as a set of
objects or as an E4X-compatible
XML object, depending on the value of its resultFormat property. In con-
trast,
WebService and RemoteObject return data based on data types declared in metadata returned from
the server. In all cases, though, you access the returned data by referencing the
ResultEvent object’s
result property.
n
Working with CallResponder and AsyncToken
The CallResponder class is designed to enable you to assign multiple result and event handlers
for different application scenarios. Instead of binding a single set of event handlers to the RPC
component, you assign the handlers to a particular
CallResponder object:
30_488959-ch23.indd 73630_488959-ch23.indd 736 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
737
<s:HTTPService id=”contactService” url=”data/contacts.xml”/>
<s:CallResponder id=”getDataResponder”
result=”getData_resultHandler(event)”
fault=”faultHandler(event)”/>
New Feature
The CallResponder class is new to the Flex 4 SDK and is also included in the most recent version of the
Flex3 SDK.
n

At runtime, you select the responder you want to use by passing the AsyncToken that’s returned
from the service call to the
token property of the responder object:
getDataResponder.token = contactService.send();
When the RPC request’s data is returned, the responder object dispatches its result event and
calls your custom event handler function. Similarly, any exception causes the responder to dis-
patch its
fault event.
Note
As shown in the first section of this chapter on data-centric code generation, the CallResponder and
AsyncToken can also be used to set up a data binding relationship with a visual control. After associating the
CallResponder with the call by assigning its token to the value returned from the service call, you can then
refer to the
CallResponder object’s lastResult property in a binding expression:
<mx:DataGrid id=”dataGrid”
dataProvider=”{getDataResponder.lastResult}”/>
n
The AsyncToken class is a dynamic object that enables you to add arbitrary named properties to the
object at runtime and associate a remote server call with a responder object. Every request to a remote
operation through an RPC component returns an instance of
AsyncToken that stays in application
memory for the duration of the remote request. After making the request, you can add as many bits of
information as you need to track the purpose of the request or other important details:
var token:AsyncToken = contactService.send();
token.myProp1 = “Any property value”;
When data is returned in the result or fault event handlers, you can retrieve the arbitrary properties
from the event object’s
token property:
protected function resultHandler(event:ResultEvent):void
{

var savedProp = event.token.myProp1;
}
Using AsyncToken, you can “remember” information about the asynchronous call between the time
it’s made and the time its data is returned or a fault is thrown.
Using the AsyncToken Class
30_488959-ch23.indd 73730_488959-ch23.indd 737 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
738
The application in Listing 23.6 uses a CallResponder object to declare a pair of result and event
handlers. After the
HTTPService object’s send() method is called, the application then binds
the responder to the call by adding the responder to the returned
AsyncToken. The result event
handler is successfully called when the data is returned, and the data is captured and displayed.
LISTING 23.6
An application using a CallResponder
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;

import mx.rpc.events.ResultEvent;
[Bindable]
private var myData:ArrayCollection
protected function button1_clickHandler(event:MouseEvent):void
{
getDataResponder.token = contactService.send();
}
protected function getData_resultHandler(event:ResultEvent):void
{
myData = event.result.contacts.row;
}
protected function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.faultString, event.fault.faultCode);
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contacts.xml”/>
<s:CallResponder id=”getDataResponder”
result=”getData_resultHandler(event)”
fault=”faultHandler(event)”/>
</fx:Declarations>
<s:Button label=”Get Data” click=”button1_clickHandler(event)”/>
<mx:DataGrid dataProvider=”{myData}”/>
</s:Application>
30_488959-ch23.indd 73830_488959-ch23.indd 738 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
739

On the Web
The code in Listing 23.6 is available in the Web site files as CallResponderDemo.mxml in the src folder of
the
chapter23 project.
n
Working with ItemResponder and AsyncToken
Developers who prefer to work entirely with ActionScript to manage their service calls sometimes
use a pattern that includes the Flex framework’s
ItemResponder and AsyncToken classes.
Note
The ItemResponder and AsyncToken classes work nearly exactly the same with all RPC components.
n
The ItemResponder class can be used instead of the CallResponder, attribute-based event
listeners, or the
addEventListener() method to handle and dispatch event objects to
ActionScript event handler functions. To use
ItemResponder, you first create custom event han-
dler functions to handle an RPC request’s
result and fault events. Each event handler function
receives an
AsyncToken argument in addition to the expected event object. For example, the
result handler function signature looks like this:
private function resultHandler(event:ResultEvent,
token:AsyncToken):void
{
handle returned data
}
The fault event handler function looks like this:
private function faultHandler(event:FaultEvent,
token:AsyncToken):void

{
handle fault
}
Before you make the RPC request, you create an instance of the ItemResponder class and pass
references to the
result and fault event handler functions as constructor method arguments:
var responder:ItemResponder =
new ItemResponder(resultHandler,faultHandler);
Note
As with addEventListener(), you’re passing the functions as objects, and not calling them directly, so you
only pass the function names and not their complete calling syntax.
n
The next steps are as follows:
1. Make the RPC request and return an instance of AsyncToken.
30_488959-ch23.indd 73930_488959-ch23.indd 739 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
740
2. Add the ItemResponder object to the AsyncToken object’s array of responders
with its
addResponder() method.
var token:AsyncToken = contactService.send();
token.addResponder(responder);
When the asynchronous request is completed, the AsyncToken object calls the appropriate event
handler function, depending on whether a
result or fault event is dispatched by the RPC
component. The event handler function receives both its event object and a reference to the
AsyncToken object that called it.
The application in Listing 23.7 uses
ItemResponder and AsyncToken objects to manage an

asynchronous request and its result and fault events.
LISTING 23.7
Using ItemResponder and AsyncToken
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.ItemResponder;
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Bindable]
private var myData:ArrayCollection
private var contactService:HTTPService = new HTTPService();
private function getData():void
{
contactService.url=”data/contacts.xml”;
var responder:ItemResponder =
new ItemResponder(resultHandler,faultHandler);
var token:AsyncToken = contactService.send();
token.addResponder(responder);
}

private function resultHandler(event:ResultEvent,
token:AsyncToken):void
{
30_488959-ch23.indd 74030_488959-ch23.indd 740 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
741
myData = event.result.contacts.row;
}
private function faultHandler(event:FaultEvent, token:AsyncToken):void
{
Alert.show(event.fault.faultString, event.fault.faultCode);
}
]]>
</fx:Script>
<s:Button label=”Get Data” click=”getData()”/>
<mx:DataGrid dataProvider=”{myData}”/>
</s:Application>
On the Web
The code in Listing 23.7 is available in the Web site files as ItemResponderDemo.mxml in the src folder of
the
chapter23 project.
n
Tip
It’s a common practice to create individual custom classes to manage each unique RPC request. Each custom
class uses a common naming convention for both the function that creates and executes an RPC request, such
as
execute(), and its event handler methods, such as resultHandler() and faultHandler(). Known
as the Command design pattern, this approach enables you to manage complex applications with dozens or
thousands of unique server requests and is at the heart of the Cairngorm microarchitecture that’s used by

developers of large Flex applications.
n
Web Resource
Steven Webster provides an excellent description of the Command design pattern (in the context of the
Cairngorm microarchitecture) in his six-part series on Cairngorm at
www.adobe.com/devnet/flex/
articles/cairngorm_pt1.html
.
n
Working with Value Objects
XML-formatted data retrieved with the HTTPService component is always exposed as an
ArrayCollection of ObjectProxy instances. If you prefer to work with strongly typed value
object classes, you can create a simple set of code that transforms the
Object instances into your
value objects. This process has two steps:
1. Create a value object class with the appropriate properties and set the value object
class’s constructor method to accept an optional argument typed as the ActionScript
Object class. Within the constructor method, if the Object argument was passed in,
transfer its property values to the equivalent properties in the current instance of the
value object class:
30_488959-ch23.indd 74130_488959-ch23.indd 741 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
742
public function Contact(data:Object = null)
{
if (data != null)
{
this.contactid = Number(data.contactid);
this.firstname = data.firstname;

this.lastname = data.lastname;
set additional properties
}
}
2. At runtime, in the result event handler, loop through the ArrayCollection and
create one new instance of the value object for each data item, and then replace
the original object with the
ArrayCollection class’s setItemAt() method:
private function resultHandler(event:ResultEvent):void
{
var obj:Contact;
myData = event.result.contacts.row;
for (var i:int=0; i<myData.length; i++)
{
obj = new Contact(myData.getItemAt(i));
myData.setItemAt(obj, i);
}
}
Note
Notice that the value object class’s constructor method explicitly typecasts properties as necessary. This is a
major benefit of creating the extra code to transfer data from generic instances of the Object class to strongly
typed value objects: Data is correctly cast and easier to use in other code throughout the application.
n
The application in Listing 23.8 retrieves data from the server and then loops through the
ArrayCollection to replace each generic Object with an equivalent value object. When the
user selects a row from the
DataGrid, a bindable instance of the value object named current-
Contact
is filled in with the selected data and its details are displayed in the Panel.
LISTING 23.8

Using value objects with data from an HTTPService request
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”
creationComplete=”contactService.send()”>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<fx:Script>
<![CDATA[
30_488959-ch23.indd 74230_488959-ch23.indd 742 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
743
import mx.collections.ArrayCollection;
import mx.events.ListEvent;
import mx.rpc.events.ResultEvent;

import vo.Contact;
[Bindable]
private var myData:ArrayCollection
[Bindable]
private var currentContact:Contact;
private function contactService_resultHandler(event:ResultEvent):void
{
var obj:Contact;
myData = event.result.contacts.row;
for (var i:int=0; i<myData.length; i++)
{

obj = new Contact(myData.getItemAt(i));
myData.setItemAt(obj, i);
}
}
protected function datagrid1_changeHandler(event:ListEvent):void
{
currentContact = event.target.selectedItem as Contact;
}
]]>
</fx:Script>
<fx:Declarations>
<s:HTTPService id=”contactService” url=”data/contacts.xml”
result=”contactService_resultHandler(event)”/>
</fx:Declarations>
<mx:DataGrid dataProvider=”{myData}”
change=”datagrid1_changeHandler(event)”>
<mx:columns>
<mx:DataGridColumn dataField=”firstname” headerText=”First Name”/>
<mx:DataGridColumn dataField=”lastname” headerText=”Last Name”/>
</mx:columns>
</mx:DataGrid>
<s:Panel title=”Current Contact” width=”300”>
<mx:Form>
<mx:FormItem label=”First Name:”>
<s:Label text=”{currentContact.firstname}”/>
</mx:FormItem>
<mx:FormItem label=”Last Name:”>
<s:Label text=”{currentContact.lastname}”/>
</mx:FormItem>
<mx:FormItem label=”City:”>

<s:Label text=”{currentContact.city}”/>
</mx:FormItem>
</mx:Form>
</s:Panel>
</s:Application>
30_488959-ch23.indd 74330_488959-ch23.indd 743 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Part III: Working with Data
744
On the Web
The code in Listing 23.8 is available in the Web site files as HTTPValueObjects.mxml in the src folder of the
chapter23 project. The Contact value object class is defined in Contact.as in the src/vo subfolder.
n
Passing Parameters to Server Pages
When you use the HTTPService component to make calls to dynamic pages that are managed
by an application server, you frequently need to pass parameters. The syntax for passing param-
eters is the same regardless of whether you use the
HTTPService component with GET or
POST requests.
You can pass parameters in an
HTTPService request two ways:
l
Named parameters that are packaged in an ActionScript Object
l
Bound parameters that are set up in the HTTPService object declaration
Using named parameters
To pass parameters by name, first create an instance of an ActionScript Object. The Object
class is dynamic, meaning that you can add arbitrary named properties at runtime. Set each param-
eter as a named property of the properties object, and then pass the properties object as the only
argument in the object’s

send() method.
The ActionScript code to accomplish these tasks might look like this:
private function sendData():void
{
var params:Object = new Object();
params.firstname=”Joe”;
params.lastname=”Smith”;
contactService.send(params);
}
You also can use shorthand ActionScript code to create an object and pass it in a single statement:
private function sendData():void
{
contactService.send({firstname:”Joe”, lastname:”Smith”});
}
If the HTTPService object’s method property is set to GET, the parameters are appended to the
request URL. The first part of the resulting HTTP request would look like this:
GET /?firstname=Joe&lastname=Smith HTTP/1.1
30_488959-ch23.indd 74430_488959-ch23.indd 744 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Chapter 23: Working with HTTPService and XML
745
In contrast, if the HTTPService object’s method property is set to POST, the parameters are
appended to the end of the HTTP request. The following is a literal
POST request header sent from
a Flex application hosted by Microsoft Internet Explorer 6:
POST / HTTP/1.1
Accept: */*
Accept-Language: en-US
Referer: file://C:\flex4bible\workspace\chapter23\
bin-debug\HTTPSendParams.swf

x-flash-version: 9,0,115,0
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;
.NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .
NET CLR 3.5.21022)
Host: localhost
Connection: Keep-Alive
Cache-Control: no-cache
firstname=Joe&lastname=Smith
Using bound parameters
You can set up bound parameters in an HTTPService declaration so that named properties are
sent with a consistent source. For example, assume that you’ve declared a bindable instance of a
value object that stores current values:
[Bindable]
private var myContact:Contact;
If you know that the parameters you send with HTTPService always get their values from this
object, you can declare the relationship using binding expressions:
<s:HTTPService id=”contactService” url=”myAppPage.php”
result=”resultHandler(event)”>
<s:request>
<firstname>{myContact.firstname}</firstname>
<lastname>{myContact.lastname}</lastname>
</s:request>
</s:HTTPService>
When you call the HTTPService object’s send() method with no arguments, the named
parameters in the
<s:request> tag set are sent with exactly the same HTTP request syntax as
with the named parameters syntax described previously.

Cross-Reference
To fully demonstrate the use of HTTPRequest parameters, you need an application server that can receive
and respond to parameterized requests.
n
30_488959-ch23.indd 74530_488959-ch23.indd 745 3/5/10 2:38 PM3/5/10 2:38 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

×