ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Flash Remoting for J2EE Developers
Pages: 1, 2, 3

Create a Business Delegate on the Server

To use a Service-Oriented Architecture with Flash Remoting, simply create an object in your web application to expose services to Flash. In the terminology of Sun J2EE Blueprints, this object is a Business Delegate. It presents a Flash-friendly interface, exposed through Flash Remoting, to invoke methods on EJBs or any other object in the application server.



Using a Business Delegate addresses the fact that when Flash Remoting deserializes an AMF message into Java objects, it only knows a limited set of Java objects to use in the deserialization. Any developer-defined ActionScript object becomes a flashgateway.io.ASObject in Java. Methods invokable through Flash Remoting must use flashgateway.io.ASObject in their method signatures. An ASObject represents an ActionScript object in Java. It is basically a HashMap with case-insensitive keys and an extra field named type.

ActionScript code that invokes savePlayer() on com.server.Server (the Business Delegate) would look like:

#include "NetServices.as"

NetServices.setDefaultGatewayUrl("http://localhost/gateway");
var gatewayConnection = NetServices.createGatewayConnection();
var service = gatewayConnection.getService("com.server.Service", this);

Player = function() {}

var player = new Player();
player.name = "Joe";

service.savePlayer(player);

The corresponding Java Business Delegate class might be:

package com.server;

import flashgateway.io.ASObject;
  
public class Service {
   public void savePlayer(ASObject asPlayer) {
      Player player = new Player();
      player.setName((String) asPlayer.get("name"));
    
      Roster.savePlayer(player);
   }
}

Using a Business Delegate in this manner provides a single place where Flash-Remoting-specific code is centralized. The Business Delegate is completely stateless and performs no work directly, delegating requests to other objects. For small applications, a single Business Delegate can expose all needed services to Flash. In larger application, it makes sense to create different Business Delegates for different service categories.

I recommend not implementing java.io.Serializable in the Business Delegate. If an object accessed through Flash Remoting implements java.io.Serializable, the Flash gateway will save an instance of it in the user session to use for subsequent service invocations. Since the Business Delegate is stateless and the Flash client is available to maintain state, there is no reason to maintain an instance of the Business Delegate in each user's session.

Map ActionScript Objects to Java Objects

As discussed above, when sending ActionScript objects to the server through Flash Remoting service method calls, the Java service class will either receive one of the known Java object types or an ASObject, if the object type is not known. Converting these ASObjects to model objects in the application server can be tedious and brittle:

package com.server;

import flashgateway.io.ASObject;
  
public class Service {
   public void savePlayer(ASObject asPlayer) {
      Player player = new Player();
      player.setName((String) asPlayer.get("name"));
      player.setEmail((String) asPlayer.get("email"));
      player.setAge(((Integer) asPlayer.get("age")).intValue());
    
      Roster.savePlayer(player);
   }
}

At Carbon Five, we have created an open source library for addressing this issue. ASTranslator (ActionScript Translator) is hosted on SourceForge.net at carbonfive.sourceforge.net/astranslator/, is at its 1.0 release, and has been used in several production applications.

ASTranslator has two methods. ASTranslator.toActionScript() translates Java objects in your application to ASObjects to send to Flash. We'll discuss this method shortly. ASTranslator.fromActionScript() translates ASObjects sent to Remoting service methods from Flash to Java objects, as shown here:

import flashgateway.io.ASObject;
import com.carbonfive.flash.ASTranslator;
  
public class Service {
   public void savePlayer(ASObject asPlayer) {
      Player player = (Player) new ASTranslator().fromActionScript(asPlayer);
    
      Roster.savePlayer(player);
   }
}

Note that you must cast the result of this method call to the expected return type. fromActionScript() can take any object as an argument. It will translate any object and its composite objects as deeply as possible, maintaining references as it goes.

In order for ASTranslator to know what Java class an ASObject should become, you must register your ActionScript objects in Flash MX with the Java class name to which the ActionScript object maps.

// Object definition
Player = function() {}        

// Player in Flash maps to com.server.Player in Java                      
Object.registerClass("com.server.Player", Player);  

The value with which you register the class in ActionScript--com.server.Player, in this case--is set to the value of the ASObject type field by Flash Remoting when deserializing the object from AMF. ASTranslator uses this field to know what Java object to create from the ASObject.

Use ASTranslator to Return Objects to Flash

We created ASTranslator because of an issue we found with Flash Remoting MX for J2EE. When returning Java objects from service calls to Flash, Flash Remoting serializes Java objects according to their member variable state (private, protected, or public), ignoring the publicly-declared property accessors you'd expect it to use. If you have a Java class:

package com.server;

public class Player {
   private String _name;
  
   public getName() {
      return _name;
   }
}

and a service class:

package com.server;

public class Service {
   public Player getPlayer(String name) {
      Player player = Roster.getPlayer(name);
      return player;
   }
}

calling Service.getPlayer() from Flash MX would return an ActionScript object with a property _name instead of name. This removes one of the primary values of object-oriented programming: encapsulation. ActionScript programmers in Flash can see the internal state of Java objects on the server that even other Java objects running on the server cannot see. This is bad. It can be really bad (both for performance and security) if the internal state includes more information than the object was designed to expose through its public interface.

ASTranslator uses JavaBean-style introspection to serialize Java objects for remoting. To use ASTranslator in the above example, we would change the Business Delegate Service class as follows.

package com.server;

import flashgateway.io.ASObject;
import com.carbonfive.flash.ASTranslator;
  
public class Service {
   public ASObject getPlayer(String name) {
      Player player = Roster.getPlayer(name);
      ASObject aso = (ASObject) new ASTranslator().toActionScript(player);
      return aso;
   }
}

Flash will now receive an ActionScript object with the property name.

Additionally, ASTranslator sets the type field of the ASObject as the class name of the translated Java object. If the Flash developer has registered an ActionScript class with the class name of the Java object to which it maps, the object Flash receives will be of the right object type in ActionScript (a Player, in our example). If it has not been registered, the object Flash received will just be an ActionScript Object. Using ASTranslator in this way creates a tight binding between ActionScript objects in Flash and Java objects in the application server. We have found this to be a very effective way to use Flash Remoting.

Pages: 1, 2, 3

Next Pagearrow