Flash Remoting for J2EE Developers
Pages: 1, 2, 3
Create a Service Proxy on the Client
Just as the Business Delegate defines a single entry point for communication coming from Flash through Flash Remoting, a Service Proxy implemented in Flash provides a single place where server-side services are exposed to the Flash application. To an ActionScript developer, the Service Proxy looks like the service provided by your application. The Service Proxy provides a central place to:
- Connect to the Flash Remoting gateway.
- Connect to an application service.
- Handle errors.
- Perform other tasks before and/or after each Flash Remoting call.
- Define the service API for the Flash developers
- Handle changes in the service interface without affecting ActionScript client code.
A Service Proxy for the example in the previous section may resemble:
#include "NetServices.as"
// define service proxy
function Service(client) {
this.client = client;
// set global status to call this
_global.System.server = this;
_global.System.onStatus = function(status) {
this.server.onStatus(status);
}
}
// initialize the service
Service.prototype.init = function(gatewayUrl) {
NetServices.setDefaultGatewayUrl(gatewayUrl);
var gatewayConnection = NetServices.createGatewayConnection();
this.service = gatewayConnection.getService("com.server.Service", this.client);
}
// define status handler
Service.prototype.onStatus = function(status) {
this.client.onStatus(status);
}
// save user service
Service.prototype.saveUser = function(user) {
this.service.saveUser(user);
}
and the ActionScript code to use it would be:
var service = new Service(this);
service.init("http://localhost/gateway");
Player = function() {}
var player = new Player();
player.name = "Joe";
service.savePlayer(player);
For many development teams, the Service Proxy will be the place where J2EE developers and Flash developers get together to agree on the service API. We have found that creating a stubbed-out Service Proxy with methods that return the same results for each call is a great way to define the integration point between Flash and a J2EE application. Both teams can work knowing that the integration is already well-defined.
Throw Exceptions to the Client
A Flash developer handles the results of a remoting call (e.g.,
service.doCall()) by implementing a
doCall_onResult(result) callback method for service calls that
execute successfully and a doCall_onStatus(error) callback method
for exceptions thrown by the Remoting gateway. The Remoting gateway will throw
exceptions when it encounters problems locating, loading, or creating the
service class and the method to invoke on it, or when the service class itself
throws an exception.
Given this behavior and my recommendation to use a service-oriented
architecture with Flash Remoting, I recommend having the service implementation
throw exceptions to be handled by the Flash MX client. In the simplest case, I
recommend having all service methods simply throw Exception.
package com.server;
import flashgateway.io.ASObject;
import com.carbonfive.flash.ASTranslator;
public class Service {
public ASObject getPlayer(String name) throws Exception {
...
}
}
This allows the Flash MX client to inspect all exceptions thrown during the service invocation and determine what to do about it at runtime. This strategy is discussed in the Flash Remoting documentation at livedocs.macromedia.com/frdocs/Using_Flash_Remoting_MX/UseActionScript8.jsp.
The type field of the error object returned to
getPlayer_onStatus() should provide the class name of the thrown
exception, allowing us to implement the callback in Flash as:
getPlayer_onStatus = function (error) {
if (error.type == "com.server.PlayerNotFoundException") {
trace("unable to find the player");
} else {
trace("an unknown error occurred");
}
}
This approach is limited in that inheritance is not taken into account. A
thrown exception that extends com.server.PlayerNotFoundException
is an instance of a com.server.PlayerNotFoundException in Java, but
would not be handled as one in the above ActionScript code. The
type field of the error object would be the class name of the
thrown exception.
A more significant limitation is that Flash Remoting MX for J2EE does not
actually send exceptions thrown by a service class to the
XXX_onStatus callback method. Because the Flash Remoting gateway
uses introspection to invoke the service methods, all exceptions thrown by
service calls are nested within a
java.lang.reflect.InvocationTargetException. Tracing the
properties of an exception thrown by a service call results in output that
looks something like:
code: SERVER.PROCESSING
level: error
description: Service threw an exception during method invocation: null
type: java.lang.reflect.InvocationTargetException
rootcause:
details: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
at flashgateway.Gateway.invoke(Gateway.java:184)
...
at java.lang.Thread.run(Thread.java:536)
Caused by: com.server.PlayerNotFoundException:
There is no player with name 'bob'
at com.server.Roster.getPlayer(Roster.java:45)
...
We would like the nested com.server.PlayerNotFoundException to
be used as exception upon which the error object is based, but it is not. This
is a known issue in the implementation of Flash Remoting for J2EE. We have not
come up with a great solution to this problem.
The best solution we have is to build a new error object in the Service
Proxy that inspects the detail field of the error returned by
Remoting to determine the correct values for description,
type, and details before calling the
onStatus method in the client. Unfortunately, the formatting of the
stack trace as provided by the details field differs, depending on
the JVM version being used on the server. Specifically, between Java 1.3 and
Java 1.4, the way in which nested exceptions are printed in a stack trace is
different. This makes inspecting the detail field brittle.
I feel strongly that having the XXX_onResult method handle
successful Remoting calls and XXX_onStatus handle the failure
cases is the best way to use Flash Remoting, but am not satisfied by with the
presented workaround. I am interested in hearing other recommendations for
dealing with this issue.
Think About Security
Because Flash Remoting uses introspection to locate, create, and invoke
methods on any class in your application server, it is important to think about
the security implications of using Flash Remoting in your application. Without
any security restrictions, a Flash movie can invoke any method on any class
that has a no-argument constructor or any object that can be found in JNDI.
This is a serious security issue. Theoretically, a Flash movie could shut down
the application server, if it knew the right object to access. At the very
least, a Flash movie could create an ArrayList and fill it until
the server runs out of memory.
There is very little information from Macromedia on this issue. Their recommended strategy for dealing with it is to modify the Java security policy file for your application server to grant or deny access to vulnerable packages in your server and application. Macromedia describes doing this for JRun 4.
Depending on your application server, you may need to edit the server's Java security policy file to grant or deny Flash Remoting access to specific classes. This Macromedia Designer and Developer Center article includes an example of editing the WebLogic security policy file to allow Flash Remoting to access classes in a specific package.
Implications
At Carbon Five, we have found that using Flash Remoting to create Flash interfaces to applications providing services through a Services-Oriented Architecture is a fun and clean way to work. It simplifies application development by removing tedious presentation-layer coding. It enables parallel development of the user experience and application functionality. It streamlines integration of work done by front-end and back-end development teams. Most importantly, it enables us to deliver powerful interfaces to the users of our enterprise Java applications.
As Web-based application development matures, we will see a proliferation of smart, stateful, feature-rich clients using Service-Oriented Applications to do the heavy hitting on the back end. Flash MX, Flash Remoting, and J2EE are powerful tools for creating these applications today.
Resources
- Download Flash MX
- Download Flash MX Remoting Components
- Download Flash Remoting MX
- Download JRun 4
- Flash Remoting MX Homepage
- Flash Remoting 101 for Java Users
- A Technical Overview of Flash Remoting MX for Java Developers (PDF)
- Common Questions About Flash Remoting
- Modifying Java Security Policy for Remoting
- Consuming Web Services with Macromedia Flash Remoting
- Consuming Amazon with Flash Remoting
- ASTranslator for Flash Remoting MX
- Flash Remoting with Java and .Net Blog
Alon Salant is an owner and co-founder of Carbon Five and a co-author of Flash Remoting: The Definitive Guide.
Return to ONJava.com.