Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
636,6 KB
Nội dung
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=”http://ns.adobe.com/mxml/2009”
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 Flex4.
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. FlashBuilder 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 = “http://www.myserver.com/data/contacts.xml”;
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
http://api.rubyonrails.org/classes/ActionController/Resources.html. 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 http://code.google.com/p/resthttpservice, 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:
http://blogs.4point.com/taylor.bastien/2009/04/
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=”http://ns.adobe.com/mxml/2009”
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>Brad.C.Lang@trashymail.com</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=”http://ns.adobe.com/mxml/2009”
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.
[...]... standard and is implemented as a part of ActionScript 3 Any application running in Flash Player 9 or later has access to the E4X API and can use its simple syntax to parse, extract data from, and modify XML and XMLList objects stored in application memory In this chapter, I describe how to use E4X and ActionScript-based XML classes to parse and modify XML-formatted data in Flex applications 749 IN THIS... 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... code from “taking over” the user’s Flash Player and making repeated requests to arbitrary Web-based resources FIGURE 23. 14 Cross-domain permission is required in this circumstance Native domain Remote domain Flex /Flash document This HTTP request requires cross-domain permission Flex application running in the Flash Player 746 Chapter 23: Working with HTTPService and XML Tip Cross-domain permission... first create custom event handler 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... 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 { } 731 Part III: Working with Data Tip You can use FlashBuilder4 s new event handler generation capabilities to create the handler function automatically When... 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: 736 Chapter 23: Working with HTTPService and XML ... 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(),... declared in MXML l 748 FlashBuilder4 helps you build data-centric applications quickly and easily with new code generation features Cross-domain constraint issues can be solved by placing a cross-domain policy file in the Web root of the remote domain CHAPTER Managing XML with E4X X ML (EXtensible Markup Language) has become a lingua franca for data exchange on the Web When the XML standard was originally... 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... Chapter 24: Managing XML with E4X if (currentNode.attributes.price == ‘21 .41 ’) { arResult.push(currentNode) } } With E4X you would first assign the XML file’s root element to a new-style XML object You can then extract the element representing the “Widget” with the simple expression: var xResult:XMLList = xInvoices lineitem.(@price=21 .41 ); This example makes clear that E4X offers a much more concise and . online at:
http://blogs.4point.com/taylor.bastien/2009/ 04/
flex -and- rest-is-it-time-to-scrub-out-soap.html.
n
30 _48 8959-ch23.indd 72530 _48 8959-ch23.indd 725. file), the response will be read and understood when it’s received from the server.
30 _48 8959-ch23.indd 7 243 0 _48 8959-ch23.indd 7 24 3/5/10 2:38 PM3/5/10 2:38