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,55 KB
Nội dung
Chapter 26: Integrating Flex Applications with BlazeDS and Java 821 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 <?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”> <fx:Declarations> <s:HTTPService id=”contactService” useProxy=”true” url=”http://127.0.0.1:8400/blazeds/flex4bible/data/contacts.xml” result=”resultHandler(event)” fault=”faultHandler(event)”/> </fx:Declarations> <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 { myData = event.result.contacts.row; } private function faultHandler(event:FaultEvent):void { Alert.show(event.fault.faultString, event.fault.faultCode); } ]]> </fx:Script> <s:Button label=”Get Data” click=”contactService.send()”/> <mx:DataGrid dataProvider=”{myData}”/> </s:Application> 34_488959-ch26.indd 82134_488959-ch26.indd 821 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part IV: Integrating Flex Applications with Application Servers 822 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 <url> 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 <dynamic-url> elements, it can proxy multiple Web resources. 34_488959-ch26.indd 82234_488959-ch26.indd 822 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 26: Integrating Flex Applications with BlazeDS and Java 823 To create a named destination for HTTPService that serves as an alias for a single Web resource, add a single <url> element nested within the destination’s <properties> element. Set the <url> 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: <destination id=”contactsXML”> <properties> <url> http://127.0.0.1:8400/blazeds/flex4bible/data/contacts.xml </url> </properties> </destination> In the Flex application, set the HTTPService object’s destination property to the id you configured in BlazeDS: <mx:HTTPService id=”contactService” destination=”contactsXML” result=”resultHandler(event)” fault=”faultHandler(event)”/> 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 FlashBuilder menu, and name the new file NamedProxyDestination.mxml . 3. Locate the <mx:HTTPService> tag. 4. Remove the url and useProxy properties. 5. Add a destination property set to contactsXML . The HTTPService declaration should look like this: <mx:HTTPService id=”contactService” destination=”contactsXML” result=”resultHandler(event)” fault=”faultHandler(event)”/> 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 34_488959-ch26.indd 82334_488959-ch26.indd 823 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part IV: Integrating Flex Applications with Application Servers 824 You also can include <dynamic-url> elements in a named destination, either along with or instead of the <url> element. This declaration uses the same destination and a dynamic url : <destination id=”contactsXML”> <properties> <dynamic-url>http://localhost:8400/blazeds/*</dynamic-url> </properties> </destination> 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: <mx:HTTPService id=”contactService” destination=”contactsXML” url=”http://127.0.0.1:8400/blazeds/flex4bible/data/contacts.xml” result=”resultHandler(event)” fault=”faultHandler(event)”/> 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 <soap> property that points to the endpoint Uniform Resource Identifier (URI) where service requests should be sent and, optionally, a <wsdl> element that indicates the location of the service’s Web Services Description Language (WSDL) service description: <destination id=”contactsWS”> <adapter ref=”soap-proxy”/> <properties> <wsdl>/myapp/services/contactService?wsdl</wsdl> <soap>/myapp/services/contactService</soap> </properties> </destination> The WebService object in the Flex application then declares just the destination and sends requests to execute service operations to BlazeDS: <s:WebService id=”myService” destination=”contactsWS” result=”resultHandler(event)” fault=”faultHandler(event)”/> 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. 34_488959-ch26.indd 82434_488959-ch26.indd 824 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 26: Integrating Flex Applications with BlazeDS and Java 825 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 andFlex 1.x. The newer version, known as AMF3, is supported by the current versions of ColdFusion, LiveCycle Data Services, and BlazeDS. Flex 3 andFlex4 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.) 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 AMF Documentation 34_488959-ch26.indd 82534_488959-ch26.indd 825 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part IV: Integrating Flex Applications with Application Servers 826 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() 34_488959-ch26.indd 82634_488959-ch26.indd 826 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 26: Integrating Flex Applications with BlazeDS and Java 827 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 34_488959-ch26.indd 82734_488959-ch26.indd 827 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part IV: Integrating Flex Applications with Application Servers 828 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: <?xml version=”1.0” encoding=”UTF-8”?> <service id=”remoting-service” class=”flex.messaging.services.RemotingService”> <adapters> <adapter-definition id=”java-object” class=»flex.messaging.services.remoting.adapters.JavaAdapter» default=»true»/> 34_488959-ch26.indd 82834_488959-ch26.indd 828 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 26: Integrating Flex Applications with BlazeDS and Java 829 </adapters> <default-channels> <channel ref=»my-amf»/> </default-channels> </service> The <channel> 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: <channel-definition id=”my-amf” class=”mx.messaging.channels.AMFChannel”> <endpoint url=”http://{server.name}:{server.port}/ {context.root}/messagebroker/amf” class=”flex.messaging.endpoints.AMFEndpoint”/> </channel-definition> Notice that the <endpoint> 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 <service> root element and looks like this in its simplest form: <destination id=”helloService”> <properties> <source>flex4bible.ROService</source> <scope>application</scope> </properties> </destination> The <destination> 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 <properties> element, you declare these two values: l The <source> 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 <scope> 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. 34_488959-ch26.indd 82934_488959-ch26.indd 829 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Part IV: Integrating Flex Applications with Application Servers 830 Tip All other things being equal, you achieve the best performance and most efficient memory usage on the server with <scope> 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: <s:RemoteObject id=”roHello” destination=”helloService”/> 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 34_488959-ch26.indd 83034_488959-ch26.indd 830 3/5/10 2:44 PM3/5/10 2:44 PM Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... class called from the Flex application in Listing 26.12 is shown in Listing 26.3 n Working with BlazeDS Data Connections in FlashBuilder 4 Flash Builder 4 includes tools for data centric development that introspect server-side components and then generate client-side ActionScript proxy classes These classes make it easy to get started integrating application servers into your Flex applications In this... properties, you can define your ActionScript value object classes with implicit getter and setter accessor methods and private properties In Chapter 2, I describe how Flash Builder 4 can generate the required getter and setter code for you based on existing public property declarations n The Flex application in Listing 26.12 sends and receives instances of value object classes When it sends an ActionScript value... declared as a private field of the class and has its values set at runtime with public set and get accessor methods The Java class in Listing 26.10 has three private fields with matching accessor methods and is suitable for use in a Flex application 841 Part IV: Integrating Flex Applications with Application Servers LISTING 26.10 A Java-based value object class package flex4 Bible; public class Contact { private... describe how to set up BlazeDS to take advantage of these tools and then how to introspect and generate proxy classes for your Remoting Service destinations 845 Part IV: Integrating Flex Applications with Application Servers Enabling RDS with BlazeDS BlazeDS 4. 0 uses the RDS (Remote Development Service) protocol to communicate with Flash Builder 4 RDS has been a part of development tools for ColdFusion for... channels, and destinations Creating Flex messaging applications Using producers and consumers Sending and receiving simple messages Working with complex messages Filtering messages on the server Debugging message traffic 849 Part IV: Integrating Flex Applications with Application Servers In this chapter, I describe how to use the Flex framework and BlazeDS to create and deploy an application that shares... 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... to the server, the Java method extracts the received object’s properties and returns a concatenated value When the Flex application sends two String values, the server’s method builds a strongly typed value object and returns it to Flex 843 Part IV: Integrating Flex Applications with Application Servers LISTING 26.12 Sending and receiving strongly typed value object classes ... 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 flex4 Bible; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; 8 34 Chapter 26: Integrating Flex Applications with BlazeDS and Java public class ROService { public String helloWorld() { return “Hello... 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 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... describing the fully qualified name and package of the matching Java class: [RemoteClass(alias= flex4 Bible.Contact”)] This is a two-way mapping: When an ActionScript version of the object is sent to the server, the Remoting Service gateway creates a Java-based version and passes the received object’s property 842 Chapter 26: Integrating Flex Applications with BlazeDS and Java values to the server-side . import java.util.List; import java.util.Map; 34_ 488959-ch26.indd 8 343 4 _48 8959-ch26.indd 8 34 3/5/10 2 :44 PM3/5/10 2 :44 PM Please purchase PDF Split-Merge on www.verypdf.com. uint java.lang.Integer Int Null Null Null 34_ 488959-ch26.indd 840 34_ 488959-ch26.indd 840 3/5/10 2 :44 PM3/5/10 2 :44 PM Please purchase PDF Split-Merge on www.verypdf.com