Flash Builder 4 and Flex 4 Bible- P16

Chia sẻ: Cong Thanh | Ngày: | Loại File: PDF | Số trang:50

lượt xem

Flash Builder 4 and Flex 4 Bible- P16

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Flash Builder 4 and Flex 4 Bible- P16: When Macromedia first released Flash MX in 2002, the product was branded as the new way to build Rich Internet Applications (known by the acronym RIA). The term was invented at Macromedia to describe a new class of applications that would offer the benefits of being connected to the Internet, including access to various types of Web-based services, but would solve many of the nagging issues that had been inherent in browser-based applications since the mid-1990s....

Chủ đề:

Nội dung Text: Flash Builder 4 and Flex 4 Bible- P16

  1. Chapter 23: Working with HTTPService and XML 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 continued 721
  2. Part III: Working with Data LISTING 23.2 (continued) 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: 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. 722
  3. Chapter 23: Working with HTTPService and XML New Feature As with all nonvisual components, an HTTPService object declared in MXML must be wrapped in an 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 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: 723
  4. Part III: Working with Data 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. 724
  5. Chapter 23: Working with HTTPService and XML 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 725
  6. Part III: Working with Data 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: 726
  7. Chapter 23: Working with HTTPService and XML 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: Alternatively, you can send the request upon a user event, such as the click event handler of a Button component: 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 tags behave dif- ferently. ColdFusion handles responses to its 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: 727
  8. Part III: Working with Data 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: 1 Brad Lang 3004 Buckhannan Avenue Syracuse NY Brad.C.Lang@trashymail.com 315-449-9420 ... additional elements ... When an XML file is structured with multiple repeating elements of the same name, as is the case with the 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 elements as its data provider: 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 and repeating elements named . Each element has a consistent internal structure consisting of named properties for con- tactId, firstname, lastname, and so on. 728
  9. Chapter 23: Working with HTTPService and XML 2. Create a new MXML application named HTTPServiceWithBindings.mxml and view it in Source mode. 3. Set its layout property to an instance of with horizontalAlign set to center. 4. Add an element after the closing tag. 5. Add an tag set between the tags. Set its id to contactService and its url property to data/contacts.xml: 6. Add an component below the tag. Set its label to Get Data and its click event listener to call the HTTPService object’s send() method: 7. Add a DataGrid component below the tag. Set its dataProvider to display the HTTPService component’s returned data using a binding expression that references the XML file’s repeating elements: 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 729
  10. Part III: Working with Data 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. 730
  11. Chapter 23: Working with HTTPService and XML 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 { } 731
  12. Part III: Working with Data 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: 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
  13. Chapter 23: Working with HTTPService and XML protected function contactService_resultHandler( event:ResultEvent):void { myData = event.result.contacts.row; } ]]> 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. 733
  14. Part III: Working with Data 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: 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: 734
  15. Chapter 23: Working with HTTPService and XML 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
  16. Part III: Working with Data LISTING 23.5 (continued) { myData = event.result.contacts.xml; } private function faultHandler(event:FaultEvent):void { Alert.show(event.fault.faultString, event.fault.faultCode); } ]]> 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: 736
  17. Chapter 23: Working with HTTPService and XML 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: n Using the AsyncToken Class 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. 737
  18. Part III: Working with Data 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 738
  19. Chapter 23: Working with HTTPService and XML 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. 739
  20. Part III: Working with Data 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
Đồng bộ tài khoản