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

Flash Builder 4 and Flex 4 Bible- P18

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

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=”
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 Flash Builder 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 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.)
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 (
/>), 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:
/>spec_121207.pdf?version=1
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.
Chapter 26: Integrating Flex Applications with BlazeDS and Java
831
method upon any application event. For example, this code calls the server-side
helloWorld()

method upon a
Button
component’s
click
event:
<s:Button label=”Click to say hello”
click=”roHello.helloWorld()”/>
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.
34_488959-ch26.indd 83134_488959-ch26.indd 831 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
832
LISTING 26.4
Handling returned data with a binding expression
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<fx:Declarations>
<s:RemoteObject id=”roHello” destination=”helloService”/>
</fx:Declarations>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<s:Label text=”Hello from BlazeDS!” fontSize=”14” fontWeight=”bold”/>
<s:Button label=”Click to say hello” click=”roHello.helloWorld()”/>
<s:Label text=”{roHello.helloWorld.lastResult}”
fontSize=”14” fontWeight=”bold”/>
</s:Application>
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
:
34_488959-ch26.indd 83234_488959-ch26.indd 832 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
833
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:
<s:RemoteObject id=”roHello” destination=”helloService”
result=”resultHandler(event)”/>
When using
addEventListener()
to create an event listener, you can designate the event
name with the
String
value result or with the
ResultEvent
class’s

RESULT
constant:
var 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
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<fx:Declarations>
<s:RemoteObject id=”roHello” destination=”helloService”
result=”resultHandler(event)”/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
private var statesData:ArrayCollection;
private function resultHandler(event:ResultEvent):void
{
statesData = event.result as ArrayCollection;
}
continued

34_488959-ch26.indd 83334_488959-ch26.indd 833 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
834
LISTING 26.5
(continued)
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<s:Button label=”Get Array” click=”roHello.getArray()”/>
<mx:DataGrid dataProvider=”{statesData}”/>
</s:Application>
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
<mx:method

>
compiler tag, which is nested within a
<mx:RemoteObject>
tag set. Each
<mx:method

>
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;
34_488959-ch26.indd 83434_488959-ch26.indd 834 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
835
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
<s:method>

tag as in the following example:
<s:RemoteObject id=”roHello” destination=”helloService”
result=”arrayHandler(event)”>
<s:method name=”helloWorld” result=”helloHandler(event)”/>
<s:method name=”getArray” result=”arrayHandler(event)”/>
</s:RemoteObject>
34_488959-ch26.indd 83534_488959-ch26.indd 835 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
836
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
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<fx:Declarations>

<s:RemoteObject id=”roHello” destination=”helloService”
result=”arrayHandler(event)”>
<s:method name=”helloWorld” result=”helloHandler(event)”/>
<s:method name=”getArray” result=”arrayHandler(event)”/>
</s:RemoteObject>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;

[Bindable]
private var statesData:ArrayCollection;
[Bindable]
private var helloString:String;
private function arrayHandler(event:ResultEvent):void
{
statesData = event.result as ArrayCollection;
}
private function helloHandler(event:ResultEvent):void
{
helloString = event.result as String;
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<s:Button label=”Get String” click=”roHello.helloWorld()”/>
<s:Label text=”{helloString}” fontSize=”14”/>

<s:Button label=”Get Array” click=”roHello.getArray()”/>
<mx:DataGrid dataProvider=”{statesData}”/>
</s:Application>
34_488959-ch26.indd 83634_488959-ch26.indd 836 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
837
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
<s:method>
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:
<fx:Declarations>
<s:RemoteObject id=”roHello” destination=”helloService”/>
<s:CallResponder id=”helloResponder” result=”helloHandler(event)”/>
<s:CallResponder id=”arrayResponder” result=”arrayHandler(event)”/>
</fx:Declarations>
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
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<fx:Declarations>
<s:RemoteObject id=”roHello” destination=”helloService”/>
<s:CallResponder id=”helloResponder” result=”helloHandler(event)”/>
<s:CallResponder id=”arrayResponder” result=”arrayHandler(event)”/>
continued
34_488959-ch26.indd 83734_488959-ch26.indd 837 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
838
LISTING 26.8
(continued)
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
private var statesData:ArrayCollection;
[Bindable]
private var helloString:String;
private function arrayHandler(event:ResultEvent):void

{
statesData = event.result as ArrayCollection;
}
private function helloHandler(event:ResultEvent):void
{
helloString = event.result as String;
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>
</s:layout>
<s:Button label=”Get String”
click=”helloResponder.token=roHello.helloWorld()”/>
<s:Label text=”{helloString}” fontSize=”14”/>
<s:Button label=”Get Array”
click=”arrayResponder.token=roHello.getArray()”/>
<mx:DataGrid dataProvider=”{statesData}”/>
</s:Application>
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;
}
34_488959-ch26.indd 83834_488959-ch26.indd 838 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
839
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
<mx:arguments>
tag set. This code binds the
concatValues()
method’s two arguments to
values gathered from
TextInput
controls:
<mx:RemoteObject id=”roHello” destination=”helloService”>
<mx:method name=”concatValues”>

<mx:arguments>
<val1>{fnameInput.text}</val1>
<val2>{lnameInput.text}</val2>
</mx:arguments>
</mx:method>
</mx:RemoteObject>
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
<?xml version=”1.0” encoding=”utf-8”?>
<s:Application xmlns:fx=”
xmlns:s=”library://ns.adobe.com/flex/spark”
xmlns:mx=”library://ns.adobe.com/flex/mx”>
<fx:Declarations>
<s:RemoteObject id=”roHello” destination=”helloService”/>
</fx:Declarations>
<s:layout>
<s:VerticalLayout horizontalAlign=”center” paddingTop=”20”/>

</s:layout>
<mx:Form>
<mx:FormItem label=”First Name:”>
continued
34_488959-ch26.indd 83934_488959-ch26.indd 839 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
840
LISTING 26.9
(continued)
<mx:TextInput id=”fnameInput”/>
</mx:FormItem>
<mx:FormItem label=”Last Name:”>
<mx:TextInput id=”lnameInput”/>
<mx:Button label=”Send Args”
click=”roHello.concatValues(fnameInput.text, lnameInput.text)”/>
</mx:FormItem>
</mx:Form>
<s:Label text=”{roHello.concatValues.lastResult}”
fontSize=”14” fontWeight=”bold”/>
</s:Application>
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
the indexing)
List ArrayCollection
Array
(sparse, meaning there is at least one
gap in the indexing, or associative with
non-numeric keys)
Map Object
ArrayCollection List ArrayCollection
Boolean java.lang.Boolean Boolean
Date java.util.Date Date
Int
/
uint java.lang.Integer Int

Null Null Null
34_488959-ch26.indd 84034_488959-ch26.indd 840 3/5/10 2:44 PM3/5/10 2:44 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

×