EQUIP2 simple Remote Procedure Call support

Chris Greenhalgh, 2006-05-02; last updated 2007-06-06

Introduction

For core functionality, EQUIP2 has a general-purpose object marshalling framework, including an implementation of the Cauche Hessian binary serialisation. This document describes an optional part of EQUIP2 which provides support for simple Remote Procedure Calls (RPCs), which leverages this common marshalling framework.

Design

Protocol

The RPC classes are in package equip2.rpc and sub-packages. A request is represented by a serialised version of an instance of class equip2.core.marshall.MethodCallRequest and a response is represented by a serialised version of an instance of calss equip2.core.marshall.MethodCallReply. (These classes are generated using Simple_Bean_Generator from ../etc/equip2.core.marshall.MethodCallRequest.xml and ../etc/equip2.core.marshall.MethodCallReply.xml. The definitions are based directly on the Hessian request and reply formats.

Client API

An abstract client stub implementation is provided by equip2.rpc.GenericHessianClient which extends equip2.rpc.GenericAbstractClient. This maps a generic request made as a call to (the GenericAbstractClient-defined):

  Object doRpc(String method, Object arguments[]) throws equip2.rpc.RpcException;

onto a call to its own abstract method:

  java.io.InputStream doRpc(byte request[], int offset, int length) 
throws equip2.rpc.RpcException;

which passes a Hessian encoded request as the contents of the request byte array, and will attempt to read a Hessian encoded reply from the returned InputStream.

A client can work with a normal application-specific API, rather than the above generic API, by using a build-time generated custom client class or using J2SE reflection (java.lang.reflect.Proxy). A simple application-specific client class can be generated using the provided XLST scripts, etc/interface2javainterface.xsl (which generates a Java interface) and etc/interface2javaclient.xsl (which generates a client (..._client) which implements the interface and delegates actual invocations to a constructor-provided subclass of equip2.core.GenericAbstractClient).

These expect the interface to be defined in a simple XML format, of which the following is a representative example:

<?xml version="1.0"?> 
<interface package="equip2.rpc.test" class="TestInterface1">
<description>test interface (API)</description>
<method name="reverse">
<description>reverse a given value.</description>
<argument name="input" javatype="java.lang.String">
<description>the value to be reversed</description>
</argument>
<return name="input" javatype="java.lang.String">
<description>the input, but reversed</description>
</return>
<exception javatpye="equip2.rpc.test.TestException">
<description>Refuses to reverse strings which are palindromes</description>
</exception>
</method>
</interface>

Client implementations

The following transport-specific extensions of equip2.rpc.GenericHessianClient are intended:

Server

Server support is provided by the class equip2.rpc.j2se.GenericDelegatingServer, which uses J2SE reflection to despatch generic requests to a delegate the class (the real server implementation) which implements the client interface. In particular, it supports the following methods:
  GenericDelegatingServer(Object delegate);
...
MethodCallReply handleRequest(MethodCallRequest request);
byte[] handleRequest(InputStream requestStream) throws RpcException;

Note that exceptions should normally be trapped and encoded in a suitable MethodCallReply object.

Alternatively, where reflection is not available (e.g. J2ME or C++) the XSLT script etc/interface2javaserver.xslt will generate a server skeleton (..._server) which extends the abstract equip2.rpc.GenericAbstractServer, implementing its main method:

  public MethodCallReply doRpc(MethodCallRequest request) throws RpcException

 and mapping the request to calls on a delegate object implementing the original Java interface (provided to the skeleton constructor), e.g.:

  public IRemoteDataspace_server(IRemoteDataspace delegate) ...

As yet there is no standard server framework for using the generated skeleton, but it would be quite simple to adapt the GenericDelegatingServer to use the generated skeleton (replacing the use of reflection in the method handleRequest).

Server implementations

The following transport-specific server implementations are intended (current reflection-based only):

Known Issues

Change log

2007-06-06
2006-05-02