R1-RPC/J White Paper

R1-RPC/J White Paper

May 2008
Table of Content

Abstract  The R1-RPC/J, or RiaOne RPC for Java, is an elegant remote communication solution between server-side Java™ and Rich Internet Application (RIA) clients, especially Adobe® Flex™ and Flash™ (henceforward, Flex and Flash) applications. R1-RPC/J is well designed and devised; it is easy-to-use, robust, and versatile. As a key system component in RIAs, R1-RPC/J elicits good system design, and fosters good software engineering practices, such as test-oriented development, clear delineation of code responsibilities, and good maintainability. In addition to remote calls, R1-RPC/J includes user registration and authentication, server session time-out control, and server-side aspect-Oriented programming (AOP) support. These greatly free application developers from re-inventing such common tasks and allow them to focus on business logic implementation.

This white paper examines the background and needs, explains the rationale behind R1-RPC/J, lists its major characteristics, compares it to other RPC options available to Flex and Flash programs, and introduces its architecture and development process.


 

The Background

Rich Internet Applications (or RIAs for short) assume a classical client-server architecture. The client side of an application provides a means for users to view and manipulate data, where the server side handles business logic, including persisting data and providing services.

The Adobe® Flex framework is a great platform for developing RIAs; so is Adobe® Flash itself. For those who are not familiar with the relationship between the two, Flash is a software tool that produces animated and, most likely, interactive swf movie files that are executed within the Flash Player, an extremely popular multimedia rendering machine that runs stand-alone and within web browsers. The latest Flash and player software support ActionScript 3 (AS3) language. Most Flash Player runtime features are exposed as objects to the AS3 language, so AS3 programs can manipulate most aspects of the movies. In fact, this is the very power of the whole Flash platform. Adobe® Flex is a Graphical User Interface (GUI) framework for developing data-centric enterprise applications that run as swf movies. It comprises of a large number of GUI widgets and gadgets in a well fomulated environment, and has access to all the underlying Flash capabilities. It is a great GUI platform for developing RIAs with many unparallel advantages.

The Need of an RPC Solution for Flex and Java

Flex and Flash provide various remoting mechanisms. Some of the remoting mechanisms talk to Adobe®'s proprietary server technologies such as media streaming; others are simply low-level network accessing, including sockets, HTTP and SOAP web services. The data sent and received on both ends are typically of very primitive data types; as soon as big systems are getting developed with Flex, the need of remote data abstraction becomes obvious and imperative. R1-RPC/J is inspired by this very need.

ActionScript 3 is a strongly-typed object-oriented language, showing many marks of another popular OO language, Java, which is extremely popular on the server side. Programming to objects would be the most natural approach for Java-Flex applications. However, the reality is quite far from this seemingly innocent and reasonable wish. The R1-RPC/J framework is a remedy for this dilemma.

The Problems of Flex-Java Remoting

The wish to have Flex and Java communicate with objects has two major obstacles, logistical and conceptual.

Issue 1, statically-typed object-oriented RPC across AS3 and Java. Although AS3 and Java share many common traits, they are totally different languages. Object mapping between the two is not one-to-one at all. For instance, Java has various generic java.util. data structures; AS3 only has Object and Array and a few collection classes. Also, Java has more primitive data types than AS3. Data and object mapping is the first challenge facing a robust Flex-Java RPC mechanism.

Issue 2, serializing object webs. Even if the object mapping were not an issue, serialization of object models is always a big decision for remoting mechanisms to make. Because objects inherantly contains and/or references other objects, any object in an object model is effectively a node in an object web. How to serialize a web of objects across different agents (client and server)? We must have a definitive answer to this before even designing an RPC solution.

Introducing R1-RPC/J

The R1-RPC/J toolkit provides an elegant solution to both issues. It uses code generation to ensure faithful data and object mapping across Flex and Java, and simplifies the RPC model without effectively sacrificing liberties in system design options.

The Answer to the Object Model Serialization Issue

First, let us understand the R1-RPC/J remoting model. The following shows a general client-server architecture:

Client-Server Architecture
Figure 2. Client-Server Architecture

In client-server applciations, there are multiple object models in different tiers. At the end of the day, what matters is the Persistent Data Model, or the saved user data. The server- and client-side object models exist only to make the software internals better organized so that the software is maintainable. As this diagram shows, server- and client-side object models are for very different purposes and are usually quite different. When data is transferred back and forth between the client and server, code on either side updates the respective object models. This is the assumption of R1-RPC/J.

R1-RPC/J mandates that (a) the server-side must provide a façade class that delegates all remote calls to their real implementation, and (b) serialized user objects must be value objects (VOs) that conform to a set of simple rules. This decision does not sacrifice anything, since the two object models are different any way.

In contrast, server-page based web applications need just a single model, on the server side, because server pages are generated on server in the same program space. Client-server applications share no commonality in this respect.

The Solution of R1-RPC/J

By clearly defining the remoting issues and assumptions, R1-RPC/J uses code generation technique and provides a remoting runtime engine to make application development completely painless in terms of RPC. The following diagram depicts the architecture and usage of R1-RPC/J.

R1-RPC/J Application Architecture
Figure 3. R1-RPC/J Application Architecture

As you see from the diagram, almost all the attention is given to implementing business logic on the server side and creating user interface on the client side. The only exception is a thin server-side façade class and its VOs. The server-side façade and VO classes are all mapped into the client side, so that you feel like you are calling the Java classes in your Flex and Flash code.

Using the code generation technique, R1-RPC/J can automatically generate a unit testing application for RPC. All you have to enable this is to provide the unit test input and output to each façade method, then run an Ant script to automatically create an RPC unit test application. This can and should be done before your start coding your Flex client! The following is a screenshot of a generated RPC testing program:

An RPC Unit Testing Screenshot
Figure 4. An RPC Unit Testing Screenshot

You can find this sample in your R1-RPC/J distribution under samples/datatype_test. The following is a partial listing of the DeepTestFacade class, of which its test run result is shown in the screenshot:

package datatype_test;

import java.util.*;

/**
 * @ASTestGlobal
 *      public static function createVO():MyTestVO {
 *          return new MyTestVO({
 *              valboolean:   true,
 *              valdouble:    8.08,
 *              valfloat:     9.09,
 *              valint:       10,
 *              vallong:      11,
 *              valshort:     12,
 *              valBoolean:   false,
 *              varDouble:    1,
 *              valFloat:     2,
 *              valInteger:   3,
 *              valLong:      4,
 *              valShort:     5,
 *              valString:    "xyz",
 *              varVector:    [ "a" ],
 *              varDate:      new Date(),
 *              valVO:        createVO1()
 *          });
 *      }
 *
 *      public static function createVO1():MyTest1VO {
 *          return new MyTest1VO();
 *      }
 */
public class DeepTestFacade implements r1.rpc.RemoteFacade
{
    /**
     * @ASTestInput  [ [ [ createVO() ] ] ]
     * @ASTestResult x[0][0].valint == 10
     */
    public ArrayList deeptest_List_of_VO_array_in(ArrayList x) { return x; }

    /**
     * @ASTestInput  [ { a: [ createVO() ] } ]
     * @ASTestResult x.a[0].valint == 10
     */
    public Hashtable deeptest_Map_of_VO_array_in(Hashtable x) { return x; }
}

The R1-RPC/J Software

The R1-RPC/J software is a toolkit that includes code generation tools, Java and Flex runtime libraries on both ends, and Ant build scripts.

Functionally, the R1-RPC/J runtime engine and programming model not only sports a robust object-based RPC, but also includes user registration and authentication, server session time-out control, server-side aspect-Oriented programming (AOP) support, and RPC-biggy-backed messaging service.

Compare with BlazeDS and Other RPC Mechanisms

In the Flex world, there are at least these RPC options:

Low-Level Network Services

Low-level network services transmit unstructured streams between the client and server. E4X in AS3 makes XML programming a lot easier, but structure your data with XML still requires a lot of plumbing on both ends. These low-level remoting mechanisms suffice for small applications and demos. For any real applications, more functional RPCs are required.

Home-Grown RPC Solutions

Many projects have experienced this growing pain and devised their own RPC mechanisms atop the basic network services aforementioned. In most cases, due to the pressure of time-to-market, lack of focus and devotion and possibly lack of enough expertise, these solutions have problems of various natures and magnitudes. Afterall, this is such a hidden (albeit important) system component; why should business developers waste too much time on that? It makes business sense to externalize this effort to get better designed, developed, supported and maintained solutions, as many Flex project managers have come to realize.

Blaze Data Services or LiveCycle Data Services

Another well-known RPC option is the Blaze Data Services (also known as BlazeDS). It is the open-source version of Adobe®'s LiveCycle Data Services product. Because it is a Adobe® product, the client-side support is already incorporated in the Flex framework. The true power (and value) of BlazeDS or LiveCycle is its true-push real-time messaging capability. The somewhat misnomer RemoteObject class can be used to support object-based RPC in an essentially dynamic fashion. With some plumbing code, statically-typed RPCs can be achieved.

Comparisons Betweeen R1-RPC/J, BlazeDS and DWR

In the AJAX world, DWR (Direct Web Remoting) is making its way to dominance as a Java server-side solution. It allows JavaScript clients to make object-based RPCs to the server-side Java objects. Another option for AJAX server-side Java RPC is Java JSON RPC, which, not surprisingly, does very much the same as DWR. They share a lot of common features with Flex-Java RPC bridges, therefore one of them, DWR, is compared alongside here.

The following table compares R1-RPC/J, BlazeDS and DWR. The criteria are chosen for their relevance in decision making. Hopefully they cover all the interesting aspects.

  R1-RPC/J BlazeDS DWR
Targeted Client Flex and Flash Flex AJAX
Strongly-Typed RPC yes yes yes
Statically-Typed RPC by nature need coding no
Messaging cooperative polling and RPC-piggyback ??? PRC-piggyback or long-living HTTP connection
Remote Call Syntax regular method call constructed programmatically or via <mx:RemoteObject> tag regular method call
Client Code Generation very rich ? no
User Login and Registration CHAP and plain-text password no plain-text password
Authorized RPC by login and/or J2EE container by J2EE container custom programming
Server-side Object Registration unnecessary yes yes
Configuration very light; static heavy; Java class dependent heavy; Java class dependent
Automated RPC Unit Testing yes no no
Documentation good good good
Open Source no yes yes
Client Library Size 26K 0 100K
Licensing commercial GNU LGPL 3.0 or commercial (LiveCycle) Apache 2.0
Support commercial Community or commercial Community
Pros and Cons

Pros:

  1. Conceptually clean: AS3 can naturally "call" Java.
  2. Powerful VO class code generation.
  3. CHAP user registration and login.
  4. Light-weight messaging.
  5. Automated RPC unit testing!
  6. Commercial quality software and support.
  7. Light-weight and small.
  8. For Flex and Flash!

Cons:

  1. Not open source.
  2. Paid license.

Pros:

  1. For RPC, enables mx::RemoteObject.
  2. Open source; LGPL licensed.
  3. Created by Adobe®.

Cons:

  1. Overhead of excessive configuration.
  2. Java remotable objects must all be configured.
  3. Confusion of serializing object models between server and client.
  4. Added plumbing coding.
  5. Flex only; not for Flash.
 
Summary R1-RPC/J is designed for Flex/Flash-Java RPC. It adds little noise to your design, development and deployment. Automated RPC unit testing is invaluable. Systems with R1-RPC/J are clean, business-focused and easy-to-maintain. The licensing is simple and low-cost. BlazeDS open-sources a subset of LiveCycleDS, leaving out substantial features of the latter. Its intent is reasonable from the business point of view: Adobe is trying to lure you into BlazeDS to eventually buy LiveCycleDS, which shall be good for the health of the Flex technology. However, BlazeDS as an RPC solution is an overkill. It is bloated with messaging remnants that requires complicated configuration but is not really needed for a lean-mean RPC mechanism. DWR, like other Java AJAX bridges, does the right thing for object-based RPC for AJAX. It allows natural method call syntax on the client side, and requires server-side configuration to expose and limit remotable Java objects.

Table 1. Comparing R1-RPC/J, BlazeDS and DWR

Developing with R1-RPC/J in a Nutshell

For the real impatient, let us take a quick look at the samples/simple_rpc in the software distribution. On the server side, we have a façade class FriendlyFacade:

package sample;

import r1.rpc.RemoteFacade;

public class FriendlyFacade implements RemoteFacade
{
    /**
     * @ASTestInput [ 'James' ]
     * @ASTestResult x == 'Hello, James!'
     */
    public String sayHi(String name) {
        return "Hello, " + name + '!';
    }
}

Note the unit test case entries in the javadoc comment. In the development process, first of all, use the R1-RPC/J code generation tool to generate a client-side counterpart class:

package sample
{
import r1.core.r1_internal;
import r1.rpc.RPC;
import r1.rpc.RPCFacade;

public class FriendlyFacade extends RPCFacade
{
    public function FriendlyFacade(rpc:RPC=null, encoding:int=0) {
        super(rpc, encoding);
    }

    public function sayHi(receiver:*, name:String):void {
        r1_internal::call("sayHi", [name], receiver);
    }
}
}

With this class on the client side, the UI simply calls the sayHi().

<?xml version="1.0" encoding="utf-8"?>
<mx:Application layout="absolute"
    xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
    creationComplete="RPC.initSingleRPC('rpc')">

<mx:Script><![CDATA[
import r1.rpc.RPC;
import r1.rpc.RPCResult;
import sample.FriendlyFacade;

private var facade:FriendlyFacade = new FriendlyFacade();

private function sayHiCB(result:String, rpcResult:RPCResult):void {
    if (!rpcResult.success) {
        output.text = "Error: " + rpcResult.errorDetail.message
    } else {
        var txt:String = output.text;
        if (txt == null || txt == '')
            output.text = result
        else
            output.text = txt + '\n' + result
    }
}
]]></mx:Script>

    <mx:Form label="Direct Call" width="100%">
        <mx:FormItem label="Name:" direction="horizontal">
            <mx:TextInput id="myName"/>
            <mx:Button label="Say Hi!" click="facade.sayHi(sayHiCB, myName.text)"/>
        </mx:FormItem>
        <mx:FormItem label="Output:" width="100%">
            <mx:TextArea id="output" width="100%" height="200"/>
        </mx:FormItem>
    </mx:Form>

</mx:Application>

The UI is simple enough:

Screenshot for the simple_rpc Sample
Figure 5. Screenshot for the simple_rpc Sample

Get Started

To use R1-RPC/J, start with these documents: