Document Information

Last modified:
2011/02/22 12:31 (external edit)

This is documentation for qooxdoo 0.8.x only. You might be interested in consulting the latest docs.

RPC (Remote Procedure Call)

qooxdoo includes an advanced RPC mechanism for direct calls to server-side methods. It allows you to write true client/server applications without having to worry about the communication details.

The qooxdoo RPC is based on JSON-RPC as the serialization and method call protocol, and qooxdoo provides server backends for Java, PHP, and Perl projects. A Python backend library is also provided by a third party. All parameters and return values are automatically converted between JavaScript and the server-side language.

Setup

To make use of the RPC, you need to set up a server backend first. See theintroduction to RPC with further information on the available backends.

Making remote calls

Basic call syntax

To make remote calls, you need to create an instance of the Rpc class:

var rpc = new qx.io.remote.Rpc(
    "http://localhost:8080/qooxdoo/.qxrpc",
    "qooxdoo.test"
);

The first parameter is the URL of the backend (in this example a Java backend on localhost). The second is the name of the service you'd like to call. In Java, this is the fully qualified name of a class. (The Java backend includes the qooxdoo.test service used in the example. The class name is lowercase to keep it in sync with the PHP examples - in Java-only projects, you would of course use standard Java naming conventions.)

When you have the Rpc instance, you can make synchronous and asynchronous calls:

// synchronous call
try {
    var result = rpc.callSync("echo", "Test");
    alert("Result of sync call: " + result);
} catch (exc) {
    alert("Exception during sync call: " + exc);
}
 
// asynchronous call
var handler = function(result, exc) {
    if (exc == null) {
        alert("Result of async call: " + result);
    } else {
        alert("Exception during async call: " + exc);
    }
};
rpc.callAsync(handler, "echo", "Test");

For synchronous calls, the first parameter is the method name. After that, one or more parameters for this method may follow (in this case, a single string). Please note that synchronous calls typically block the browser UI until the result arrives, so they should only be used sparingly (if at all)!

Asynchronous calls work similarly. The only difference is an additional first parameter that specifies a handler function. This function is called when the result of the method call is available or when an exception occurred.

You can also use qooxdoo event listeners for asynchronous calls - just use callAsyncListeners instead of callAsync. More details can be found in the API documentation.

One difference between the qooxdoo RPC and other RPC implementations are client stubs. These are small wrapper classes that provide the same methods as the corresponding server classes, so they can be called like ordinary JavaScript methods. In qooxdoo, there are no such stubs by default, so you have to provide the method name as a string. The advantage is that there's no additional build step for generating stubs, and it's also not necessary to "register" your server classes at runtime (which would be a prerequisite for dynamic stub generation). If you really want or need client stubs, you currently have to write the stubs (or a generator for them) yourself. Future qooxdoo versions may include such a generator.

Parameter and result conversion

All method parameters and result values are automatically converted to and from the backend language. Using the Java backend, you can even have overloaded methods, and the correct one will be picked based on the provided parameters.

The following table lists the data types supported by the Java backend and the corresponding JavaScript types:

Java type JavaScript type
int, long, double, Integer, Long, Double number
boolean, Boolean boolean
String String
java.util.Date Date
Array (of any of the supported types) Array
java.util.Map Object
JavaBean Object

The first few cases are quite simple, but the last two need some more explanation. If a Java method expects a java.util.Map, you can send any JavaScript object to it. All properties of the object are converted to Java and become members of the Java Map. When a Map is used as a return value, it's converted to a JavaScript object in a similar way: A new object is created, and then all key/value pairs in the map are converted themselves and then added as properties to this object. (Please note that "properties" is used here in the native JavaScript sense, not in the sense of qooxdoo properties.)

JavaBeans are converted in a similar way. The properties of the JavaBean become JavaScript properties and vice versa. If a JavaScript object contains properties for which no corresponding setters exist in the JavaBean, they are ignored.

For performance reasons, recursive conversion of JavaBeans and Maps is performed without checking for cycles! If there's a reference cycle somewhere, you end up with a StackOverflowException. The same is true when you try to send a JavaScript object to the server: If it (indirectly) references itself, you get a recursion error in the browser.

Besides the fully-automatic conversions, there's also a class hinting mechanism. You can use it in case you need to send a specific sub-class to the server (see below for details). However, it can't be used to instantiate classes without a default constructor yet. Future qooxdoo versions may provide more extensive class hinting support.

Aborting a call

You can abort an asynchronous call while it's still being performed:

// Rpc instantiation and handler function left out for brevity
 
var callref = rpc.callAsync(handler, "echo", "Test");
 
// ...
 
rpc.abort(callref);
  // the handler will be called with an abort exception

Error handling

When you make a synchronous call, you can catch an exception to handle errors. In its rpcdetails property, the exception contains an object that describes the error in more detail. The same details are also available in the second parameter in an asynchronous handler function, as well as in the events fired by callAsyncListeners.

The following example shows how errors can be handled:

// creation of the Rpc instance left out for brevity
 
var showDetails = function(details) {
    alert(
        "origin: " + details.origin +
        "; code: " + details.code +
        "; message: " + details.message
    );
};
 
// error handling for sync calls
try {
    var result = rpc.callSync("echo", "Test");
} catch (exc) {
    showDetails(exc.rpcdetails);
}
 
// error handling for async calls
var handler = function(result, exc) {
    if (exc != null) {
        showDetails(exc);
    }
};
rpc.callAsync(handler, "echo", "Test");

The following origins are defined:

Constant Meaning
qx.io.remote.Rpc.origin.server The error occurred on the server (e.g. when a non-existing method is called).
qx.io.remote.Rpc.origin.applicationThe error occurred inside the server application (i.e. during a method call in non-qooxdoo code).
qx.io.remote.Rpc.origin.transport The error occurred in the communication layer (e.g. when the Rpc instance was constructed with an URL where no backend is deployed, resulting in an HTTP 404 error).
qx.io.remote.Rpc.origin.local The error occurred locally (when the call timed out or when it was aborted).

The code depends on the origin. For the server and application origins, the possible codes are defined by the backend implementation. For transport errors, it's the HTTP status code. For local errors, the following codes are defined:

ConstantMeaning
qx.io.remote.Rpc.localError.timeoutA timeout occurred.
qx.io.remote.Rpc.localError.abortThe call was aborted.

Cross-domain calls

Using the qooxdoo RPC implementation, you can also make calls across domain boundaries. On the client side, all you have to do is specify the correct destination URL in the Rpc constructor and set the crossDomain property to true:

var rpc = new qx.io.remote.Rpc("http://targetdomain.com/appname/.qxrpc");
rpc.setCrossDomain(true);

Information

Last modified:
2011/02/22 12:31 (external edit)

Account

 
 
A book on qooxdoo RIAs, authored  by community members
JS Tutorial, JavaScript Tutorial, JavaScript Guide, Learn JavaScript JS, How To Learn JS, Learning JavaScript
 

Bad Behavior has blocked 0 potential spam attempts in the last 7 days.