Flash Builder 4 and Flex 4 Bible- P18

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

0
62
lượt xem
15
download

Flash Builder 4 and Flex 4 Bible- P18

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- P18: 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ủ đề:
Lưu

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

  1. Chapter 26: Integrating Flex Applications with BlazeDS and Java Note Desktop Flex applications deployed with Adobe AIR don’t need to use the Proxy Service. These applications aren’t downloaded from the Web at runtime, so they aren’t subject to the rules of the Web security sandbox and can make runtime requests directly to any domain. n The application in Listing 26.2 uses a proxied request for data in an XML file stored on the server. LISTING 26.2 A Flex application using the Proxy Service 821
  2. Part IV: Integrating Flex Applications with Application Servers On the Web The code in Listing 26.2 is available in the Web site files as DefaultProxyDestination.mxml in the src folder of the chapter26 project. n When you run the application in its current state, it correctly downloads and displays the requested data. If you remove the HTTPService component’s useProxy property or set it to false, the request fails because the domain of the XML file and the domain from which the appli- cation is downloaded don’t match. The result is a security fault, as shown in Figure 26.5. FIGURE 26.5 A Flex application displaying a security fault Note In the example shown in Listing 26.2, the HTTPService request triggers a cross-domain security violation, because the application is downloaded from http://localhost, while the HTTPService component’s url property refers to http://127.0.0.1. While these two ways of representing the localhost domain are technically the same, Flash Player doesn’t have any way of knowing it. Flash Player cannot match Internet Protocol (IP) addresses to their Domain Name Service (DNS) equivalents and doesn’t even try. n Using named destinations A named Proxy Service destination uses an id other than DefaultHTTP. You can use a named destination in two ways: l When the named destination contains a nested element, it represents an alias for a single Web resource. The destination id can then be referred to in the Flex application instead of the actual url. l When the named destination contains one or more nested elements, it can proxy multiple Web resources. 822
  3. Chapter 26: Integrating Flex Applications with BlazeDS and Java To create a named destination for HTTPService that serves as an alias for a single Web resource, add a single element nested within the destination’s element. Set the element’s text value to the explicit address of the Web resource. The following declaration creates a destination with an id of contactsXML that points to the location of the data in the remote domain: http://127.0.0.1:8400/blazeds/flex4bible/data/contacts.xml In the Flex application, set the HTTPService object’s destination property to the id you configured in BlazeDS: Tip When you set the destination property of a WebService or HTTPService object, its useProxy prop- erty is set to true automatically. Setting a destination and then setting useProxy to false wouldn’t make any sense, because the destination refers to a Proxy Service resource on the server. n Try these steps to use a destination that’s already been created in proxy-config.xml: 1. Open DefaultProxyDestination.mxml. 2. Choose File ➪ Save As from the Flash Builder menu, and name the new file NamedProxyDestination.mxml. 3. Locate the tag. 4. Remove the url and useProxy properties. 5. Add a destination property set to contactsXML. The HTTPService declaration should look like this: 6. Run the new version of the application, and test retrieving data from the server. The proxied request should be completed successfully. On the Web The completed code for this exercise is available in the Web site files as NamedProxyDestinationComplete.mxml in the src folder of the chapter26 project. n 823
  4. Part IV: Integrating Flex Applications with Application Servers You also can include elements in a named destination, either along with or instead of the element. This declaration uses the same destination and a dynamic url: http://localhost:8400/blazeds/* To use a dynamic url in a named destination, set the HTTPService or WebService object’s destination and url properties. The url should match the pattern in the dynamic url in the destination that’s defined on the server: To use the Proxy Service with the Flex framework’s WebService component, declare a named destination that uses an adapter named soap-proxy. Declare a nested property that points to the endpoint Uniform Resource Identifier (URI) where service requests should be sent and, optionally, a element that indicates the location of the service’s Web Services Description Language (WSDL) service description: /myapp/services/contactService?wsdl /myapp/services/contactService The WebService object in the Flex application then declares just the destination and sends requests to execute service operations to BlazeDS: Using the Remoting Service The Remoting Service enables you to execute public methods of server-side Java classes hosted by LCDS or BlazeDS. The Flex application uses the RemoteObject component to execute the calls and handle results returned from the remote server. 824
  5. Chapter 26: Integrating Flex Applications with BlazeDS and Java AMF Documentation In the past, a number of individuals and organizations reverse-engineered AMF to create open-source or commercial server implementations that are compatible with Flex applications. OpenAMF (http:// sourceforge.net/projects/openamf/), Red5 (http://osflash.org/red5), AMFPHP (www. amfphp.org), and WebORB (www.themidnightcoders.com/weborb/java/) all represent poten- tial alternatives to Adobe’s own products for providing AMF-based messaging with Java-based applica- tion servers. In February 2008, Adobe Systems publicly documented both AMF0 and AMF3 so that organizations that had previously implemented AMF-capable servers could verify that their work matched the proto- col exactly and to allow new participants in the world of Flex development to get it right the first time. The AMF documentation is currently available from these links: AMF0: http://opensource.adobe.com/wiki/download/attachments/1114283/amf0_ spec_121207.pdf?version=1 AMF3: http://opensource.adobe.com/wiki/download/attachments/1114283/amf3_ spec_121207.pdf?version=1 The RemoteObject component is one of the Flex framework’s three Remote Procedure Call (RPC) components. The other two, the WebService and HTTPService components, have been described previously. Like these two, the RemoteObject component makes calls asynchronously and handles returned results with either binding expressions or event handlers. The Remoting Service on the server and the RemoteObject component on the client use a binary format to transfer data back and forth. This format, AMF (Action Message Format), was originally created for ColdFusion’s Flash Remoting technology and was then adapted for use with Java classes in Flex Data Services, LiveCycle Data Services, and now BlazeDS. Because this format is binary, the result is smaller data bundles, and there is no need for resource-intensive XML parsing. In most cases, the result is better speed and performance. Note There are two versions of AMF. The first version, now known as AMF0, was originally supported in earlier ver- sions of ColdFusion and Flex 1.x. The newer version, known as AMF3, is supported by the current versions of ColdFusion, LiveCycle Data Services, and BlazeDS. Flex 3 and Flex 4 applications make requests in AMF3 by default, but they can be configured to communicate in AMF0 when required. n Creating and exposing Java classes The RemoteObject component can call public methods of any basic Java class that’s been hosted and configured in LCDS or BlazeDS. (For convenience, I’ll refer exclusively to BlazeDS for the rest of this chapter, but the functionality and techniques are exactly the same for LiveCycle Data Services.) 825
  6. Part IV: Integrating Flex Applications with Application Servers You need to follow two steps when making the Java methods available: 1. Create and compile a Java class, and place in the BlazeDS classpath. 2. Create a destination that points to the Java class on the server. Any plain old Java Object (sometimes known as a POJO) can be used through the Remoting Service. Classes written in other common Java design patterns, such as servlets and Enterprise Java Beans (EJBs), can’t be called directly through the Remoting Service. If you have existing functional- ity already built in these formats, though, it’s a fairly easy task to create a POJO to call from Flex that in turn makes calls on the server to existing functions. Follow these rules for creating Java classes for use with the Remoting Service: l All classes must be in the BlazeDS classpath. l For individual classes, you can accomplish this by placing them in BlazeDS’s WEB- INF/classes folder. As with all Java Enterprise Edition applications, classes placed in this folder are automatically available to the application. l For classes stored in JAR (Java Archive) files, the JAR file can be placed in BlazeDS’s WEB-INF/lib folder. As with all Java Enterprise Edition applications, archive files placed in this folder are automatically added to the classpath when the application qis started. l The Java class must have a no-arguments constructor method or no explicit con- structor methods at all. At runtime, the Remoting Service gateway creates an instance of the Java class (static methods aren’t supported). It assumes the presence of a constructor method that can be called with no arguments: public ROService() { System.out.println(“constructor method called”); } If you create a class with no explicit constructor method, the Java compiler adds the no-arguments constructor for you. If there’s at least one constructor method with arguments, though, you’re responsible for creating the alternative constructor method with no arguments. l All methods must be explicitly marked as public. Java enables you to drop the access modifier from a method declaration, but these methods aren’t available to the Remoting Service. This simple Java-based method is suitable for use by the Remoting Service: public String helloWorld() { return “Hello from the world of Java!”; } l You can’t use a small set of reserved method names. These methods are used by the gateway library at runtime; if your class implements any of these method names, conflicts can result: l addHeader() l addProperty() 826
  7. Chapter 26: Integrating Flex Applications with BlazeDS and Java l clearUsernamePassword() l deleteHeader() l hasOwnProperty() l isPropertyEnumerable() l isPrototypeOf() l registerClass() l setUsernamePassword() l toLocaleString() l toString() l unwatch() l valueOf() l watch() l Method names should not start with an underscore (_) character. Listing 26.3 shows the source code for a Java class named ROService in the flex4bible package. It has an explicit no-arguments constructor method and a single method that returns a String value. LISTING 26.3 A Java class suitable for use with the Remoting Service package flex4Bible; public class ROService { public ROService() { } public String helloWorld() { return “Hello from the world of Java”; } public List getArray() { Map stateObj; List ar = new ArrayList(); stateObj = new HashMap(); stateObj.put(“capital”, “Sacramento”); stateObj.put(“name”, “California”); ar.add(stateObj); stateObj = new HashMap(); stateObj.put(“capital”, “Olympia”); stateObj.put(“name”, “Washington”); ar.add(stateObj); stateObj = new HashMap(); continued 827
  8. Part IV: Integrating Flex Applications with Application Servers LISTING 26.3 (continued) stateObj.put(“capital”, “Salem”); stateObj.put(“name”, “Oregon”); ar.add(stateObj); return ar; } public String concatValues(String val1, String val2) { return “You passed values “ + val1 + “ and “ + val2; } public String setContact(Contact myContact) { return “Contact sent from server: “ + myContact.getFirstName() + “ “ + myContact.getLastName(); } public Contact getContact(String val1, String val2) { Contact myContact = new Contact(); myContact.setFirstName(val1); myContact.setLastName(val2); return myContact; } } On the Web The source code in Listing 26.3 is available in the Web site files as ROService.java in the BlazeDS WEB-INF/src folder. The compiled version of the class is stored in BlazeDS WEB-INF/classes folder. n Note The no-arguments constructor method in Listing 26.3 isn’t required as long as the class doesn’t have any other constructor methods. n Configuring Remoting Service destinations Each Java class you want to call from a Flex application with the Remoting Service must be config- ured as a destination in the BlazeDS configuration files. Remoting Service destinations are defined in remoting-config.xml in the BlazeDS WEB-INF/flex folder. The default remoting-config.xml that’s delivered with a fresh BlazeDS installation looks like this: 828
  9. Chapter 26: Integrating Flex Applications with BlazeDS and Java The element toward the bottom of the file indicates that Remoting Service communi- cations are handled by default with AMF. The my-amf channel is defined in services-con- fig.xml in the same folder and looks like this: Notice that the element includes dynamic expressions (wrapped in curly braces) that refer to the server, port, and context root from which the application is downloaded at run- time. This is how the Flex application knows which server should receive requests for remote object method calls. Each Java class you want to call from Flex should be configured as a destination. Each destination is declared as a child of the configuration file’s root element and looks like this in its simplest form: flex4bible.ROService application The element’s id property is an arbitrary value that you use in the Flex applica- tion to refer to this class as a remote object. Within the element, you declare these two values: l The element. This element is required and is set to the fully qualified name and package of the Java class that contains methods you want to call. l The element. This element is optional and is set to one these three values: l application means that a single instance of the Java class is constructed as BlazeDS starts up and is shared by all users and requests. l session means that a new instance of the Java class is constructed for each new browser session. As each user sends new requests, the session instances are tracked (via the host application server’s session management) with cookies that are automati- cally generated and tracked by BlazeDS and the hosting application server. l request (the default) means that a new instance of the Java class is constructed for each call to any of the class’s methods. 829
  10. Part IV: Integrating Flex Applications with Application Servers Tip All other things being equal, you achieve the best performance and most efficient memory usage on the server with set to application. The only reason to use the default setting of request is if the Java class has code that can’t be called safely by concurrent requests from multiple clients. n Using the RemoteObject Component You use the Flex SDK’s RemoteObject component to make calls to a server-side Java class’s pub- lic methods. Just as the HTTPService component sends and receives requests with generic XML- formatted messages and the WebService component does with SOAP-based Web services, the RemoteObject component makes requests and handles responses using the HTTP communica- tion protocol. The big difference with RemoteObject is the message format: Because AMF is binary, instead of the text-based XML languages used by the WebService and HTTPService components, mes- sages formatted in AMF are a fraction of the size generated by the other RPC components. As a result, communication is faster, less network bandwidth is used, and larger data packets can be transferred between client and server. Instantiating the RemoteObject component As with the HTTPService and WebService components, you can instantiate RemoteObject in MXML or ActionScript code. When used with BlazeDS, you instantiate the object and set its des- tination property. This MXML code creates an instance of the RemoteObject component that points to a server- side destination: The equivalent code in ActionScript looks like this: import mx.rpc.remoting.RemoteObject; private var roHello:RemoteObject = new RemoteObject(“roHello”); Alternatively, you can first declare the object and then set its destination: var roHello:RemoteObject = new RemoteObject(); roHello.destination = “roHello”; Calling remote methods You call public methods of server-side Java classes as though they were local methods of the RemoteObject. For example, the Java class in Listing 26.3 has a public method named helloWorld() that returns a simple String. As with local functions, you can call the remote 830
  11. Chapter 26: Integrating Flex Applications with BlazeDS and Java method upon any application event. For example, this code calls the server-side helloWorld() method upon a Button component’s click event: You also can call a remote method by calling the RemoteObject object’s getOperation() method to create an instance of the Operation class. The following code creates the Operation object and then calls its send() method to call the remote method: import mx.rpc.remoting.mxml.Operation; private function callIt():void { var op:Operation = roHello.getOperation(“helloWorld”) as Operation; op.send(); } This technique enables you to determine which remote method will be called at runtime, instead of having to hard code the method name. Handling RemoteObject results As with the other RPC components, you can handle data returned from a call to a remote method with binding expressions or event handlers. Binding expressions take less code and are easy to cre- ate, while an event handler gives you much more flexibility in how you receive, process, and save data to application memory. Using binding expressions A binding expression used to pass returned data to application components consists of three parts, separated with dots: l The RemoteObject instance’s id l The remote method name l The lastResult property At runtime, the method is created as an Operation object that’s a member of the RemoteObject instance with an id that matches the method’s name. The Operation object’s lastResult property is populated with data when it’s received from the server. The lastResult property is typed as an ActionScript Object, but at runtime its native type is determined by what type of data was returned from the server. A String returned from Java is translated into an ActionScript String value, so a binding expression that handles the value returned from the simple helloWorld() method can be used to pass the returned value to a Label or other text display control. The application in Listing 26.4 calls the remote helloWorld() method and displays its returned data in a Label control with a binding expression in its text property. 831
  12. Part IV: Integrating Flex Applications with Application Servers LISTING 26.4 Handling returned data with a binding expression On the Web The code in Listing 26.4 is available in the Web site files as ROWithBindings.mxml in the src folder of the chapter26 project. n Using the result event As with the other RPC components, you can handle results of a call to a remote method with the RemoteObject component’s result event in an identical fashion. This event dispatches an event object typed as mx.rpc.events.ResultEvent, the same event object that’s used by the other RPC components: HTTPService and RemoteObject. The event object’s result prop- erty references the returned data. To handle and save data using the result event, follow these steps: 1. Declare a bindable variable outside of any functions that acts as a persistent refer- ence to the returned data. 2. Cast the variable’s type depending on what you expect to be returned by the remote method. For example, if the data returned by the remote Java-based method is typed as a primitive array or an implementation of the Java List interface, the RemoteObject component casts the returned data as an ArrayCollection: import mx.collections.ArrayCollection; [Bindable] private var myData:ArrayCollection 3. 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: 832
  13. Chapter 26: Integrating Flex Applications with BlazeDS and Java private function resultHandler(event:ResultEvent):void { } 4. Within the event handler function, use the event.result expression to refer to the data that’s returned from the server. Just as with the WebService component, Result Event.result is typed as an Object. Because the expression’s native type differs depending on what’s returned by the remote method, you typically have to explicitly cast the returned data. This code expects the remote method to return an ArrayCollection: myData = event.result as ArrayCollection; 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 roHello:RemoteObject = new RemoteObject(“helloService”); roHello.addEventListener(ResultEvent.RESULT, resultHandler); roHello.helloWorld(); Listing 26.5 uses a result event handler function to capture and save data that’s been returned from a remote method. LISTING 26.5 Handling returned data with the result event
  14. Part IV: Integrating Flex Applications with Application Servers LISTING 26.5 (continued) ]]> On the Web The code in Listing 26.5 is available in the Web site files as ROResultEvent.mxml in the src folder of the chapter26 project. n Note As with the other RPC components, exceptions that occur during execution of remote methods generate a fault event. The code to handle faults is exactly the same as with the other RPC components. For a full description and some code examples, see Chapter 21 and Chapter 23. n Note As with the HTTPService and WebService components, you can pass result and fault event objects to ActionScript event handler functions using the ItemResponder and AsyncToken classes. See Chapter 21 for details. n Working with multiple methods When you need to call more than one method of a Java class on the server, you have to distinguish which event handler function should be called for each of them. You do this in MXML with the compiler tag, which is nested within a tag set. Each tag represents a remote Java method and can declare its own distinct result and event handlers. The Java class in Listing 26.6 has a number of different methods. Its helloWorld() method returns a String, getArray() returns a List, and so on. LISTING 26.6 The Java class with methods being called from Flex package flex4Bible; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; 834
  15. Chapter 26: Integrating Flex Applications with BlazeDS and Java public class ROService { public String helloWorld() { return “Hello from the world of Java”; } public List getArray() { Map stateObj; List ar = new ArrayList(); stateObj = new HashMap(); stateObj.put(“capital”, “Sacramento”); stateObj.put(“name”, “California”); ar.add(stateObj); stateObj = new HashMap(); stateObj.put(“capital”, “Olympia”); stateObj.put(“name”, “Washington”); ar.add(stateObj); stateObj = new HashMap(); stateObj.put(“capital”, “Salem”); stateObj.put(“name”, “Oregon”); ar.add(stateObj); return ar; } public String concatValues(String val1, String val2) { return “You passed values “ + val1 + “ and “ + val2; } public String handleObject(Contact myContact) { return “You Contact # “ + myContact.getContactId() + “: “ + myContact.getFirstName() + “ “ + myContact.getLastName(); } } On the Web The code in Listing 26.6 is available in the Web site files as ROService.java in the BlazeDS application’s WEB-INF/src/flex4Bible folder. The compiled version of the class is stored in WEB-INF/classes. n A Flex application that needs to call more than one of these methods would use the tag as in the following example: 835
  16. Part IV: Integrating Flex Applications with Application Servers Each method’s custom event handler function would then expect the appropriate type of data to be returned from its remote method. The application in Listing 26.7 handles the result events of multiple remote methods using an MXML declaration. LISTING 26.7 Handling multiple remote methods’ result events 836
  17. Chapter 26: Integrating Flex Applications with BlazeDS and Java On the Web The code in Listing 26.7 is available as ROMultipleMethods.mxml in the src folder of the chapter26. zip file. n Using the CallResponder class The CallResponder class enables you to define unique responses to method calls. In contrast to using the tag, which defines responses in a way that makes it difficult to modify at runtime, the CallResponder enables you to hook up method calls to particular responses using ActionScript code. You can wrap the calls with whatever logic you deem necessary to implement your application’s required logic. If you’ll be calling multiple methods from a single Java class that’s been exposed as a Remoting Service destination, you can declare one instance of the RemoteObject class and one or more instances of CallResponder. Each CallResponder can define its own result and fault event handlers: When you call a remote method, you receive an instance of the AsyncToken class. By assigning a CallResponder object’s token property to that AsyncToken object, you connect the responder to the method call: arrayResponder.token=roHello.getArray() Now when the data is returned from the server, the responder’s result event is dispatched and your custom event handler method is called to process the returned data. The application in Listing 26.8 shows the use of the CallResponder class to handle results from multiple method calls. LISTING 26.8 Handling multiple remote methods with CallResponder continued 837
  18. Part IV: Integrating Flex Applications with Application Servers LISTING 26.8 (continued) On the Web The code in Listing 26.8 is available as ROCallResponder.mxml in the src folder of the chapter26.zip file. n Passing arguments to remote methods As with WebService operation parameters, you can pass arguments to remote methods using either explicit or bound argument notation. Explicit notation means that arguments are passed in the same order in which they’re declared in the Java method. This Java method, for example, requires two String arguments and returns a concatenated String: public String concatValues(String val1, String val2) { return “You passed values “ + val1 + “ and “ + val2; } 838
  19. Chapter 26: Integrating Flex Applications with BlazeDS and Java The following ActionScript code passes arguments to this remote method with explicit syntax: roHello.concatValues(fnameInput.text, lnameInput.text); You also can use bound argument notation with XML elements for each argument wrapped in an tag set. This code binds the concatValues() method’s two arguments to values gathered from TextInput controls: {fnameInput.text} {lnameInput.text} To call the method with the bound arguments, call the operation’s send() method without any explicit arguments: roHello.concatValues.send() Caution You cannot pass arguments by name to Java-based remote methods using the Remoting Service. Although the bound arguments syntax makes it look like arguments are being matched by their names, in fact they’re passed and received in the order of declaration in the Flex application and the Java method. It may seem odd, but in bound notation with Java, the names of the argument elements don’t matter at all. n The application in Listing 26.9 passes explicit arguments to a remote method on the server and displays the returned result with a binding expression. LISTING 26.9 Passing arguments using explicit notation continued 839
  20. Part IV: Integrating Flex Applications with Application Servers LISTING 26.9 (continued) On the Web The code in Listing 26.9 is available as ROExplicitArgs.mxml in the src folder of the chapter26.zip file. Another file named ROBoundArgs.mxml, not shown here, demonstrates the use of bound arguments. n Passing data between ActionScript and Java Data passed from a Flex application to a Java class with the Remoting Service is serialized, or trans- formed, from ActionScript data types to their equivalent types in Java. When data is returned from Java to Flex, a similar serialization occur”s. Table 26.1 describes how data is serialized from ActionScript to Java and back again. TABLE 26.1 ActionScript to Java Data Serialization ActionScript To Java Back to ActionScript Array (dense, meaning there are no “holes” in List ArrayCollection the indexing) Array (sparse, meaning there is at least one Map Object gap in the indexing, or associative with non-numeric keys) ArrayCollection List ArrayCollection Boolean java.lang.Boolean Boolean Date java.util.Date Date Int/uint java.lang.Integer Int Null Null Null 840
Đồng bộ tài khoản