Guido Schryen
CHAIMS Project
README
RMI Wrappers 1.1 (for CHAIMS 2.0) - How To Wrap
September 11, 1998
In this README, I will introduce the steps necessary to wrap a
Java megamodule.
Structure of the wrapper and overview of the work that has to be done in order to
wrap a megamodule:
The class LocalObjectWrapper is the main part of the link between the server
side of the wrapper and the client side of the wrapper. The server side contains
all classes which are fixed and don't have to be customized by the wrapping
person, so not being intering for the wrapping person; the client side
consists of one class for each method of the magamodule and has to be written by
the wrapping person (there is a template for doing that). The LocalObjectWrapper has
to be sligthly adapted for each magamodule.
***********************
* wrapper's * **********************
* server side *<----------->* LocalObjectWrapper *
*********************** ********************** /
/ | \
/ | \
/ | \
/ | \
*********************** / | \
* wrapper's * / | \
* client side * / | \
* * | \
* * * * * * * * * * * *********************************************************
* / | \ *
* ******************** ******************** ******************** *
* * Method_A_Wrapper * * Method_B_Wrapper * . . . * Method_Z_Wrapper * *
* ******************** ******************** ******************** *
* *
*******************************************************************************
Detailled description of the wrapping TODOs:
1. LocalObjectWrapper
You can use the existing class LocalObjectWrapper by doing some adaption:
(terms in braces correspond to the current implementation)
a) Define a String constant for each method in the megamodule and one
associated with an invalid invocation.
(INVALID, FIRSTTEST, SECONDTEST)
b) Declare an object of the remote interface.
(private TestObject obj = null; since TestObject is the (remote) interface
of the megamodule TestObjectImpl
)
c) Adapt the lookup to the server in order to gain access on it.
For details about the lookup procedure have a look at
the RMI stuff.
d) Adapt the method getLocalObjectMethodID. You can do it straightfoward,
each method is supposed to have the attribut METHOD_NAME.
e) Adapt the method getNewMethodWrapper. This is a trivial procedure, as you only
have to replace the names of the methods (see a) )and the class names of the methods
(remember that for each method in the megamodule there has to be a corresponding
class in the wrapper, Method_A_Wrapper e.g.)
2. Wrapper class for each method
Each wrapper class inherits the class LocalMethodWrapper, but from the wrapping
point of view knowledge about its content is not necessary.
You only have to know that you have to implement its abstract methods
- public abstract void callMethod(ChaimsAttrValContainer c, Object obj, ChaimsClientRecord clientRecord );
- public abstract void initializeParameters();
Remember that you have to write one class for each megamodule's method.
Just proceed following steps (compare to the class FirstTestWrapper or
SecondtestWrapper !!!):
a) Define some constants whose values have to be identical with those one
in the repository.
- METHOD_NAME
- for each return item you have to declare an object of the corresponding class
(NameAdressObject)
and the name of this return item (since there might be a couple of return
values and blobs, respectively .
b) The constructor (having no parameters) contains only one instruction:
super( METHOD_NAME );
c) Implement the method initializeParameters. For each parameter of the megamodule's method
that becomes just wrapped, you have to introduce its name (the same one as in the
repository !) and to add it to the parameter container (see the examples).
d) Implement the method callMethod. The work can be divided into four parts:
1. Transform the parameters (blobs) into objects which the method expects. For each
parameter you have to do (compare to class FirstTestWrapper):
// declaration
= null; (NameAddressObject param = null;)
// find the correct blob (lookup into tables with default values is included)
blob = findParameterBlob( c, (String) (parameterNames.elementAt(i) ), clientRecord );
// i is the index of the current parameter, it goes from 0 up to (#parameters-1)
// convert the blob into the object
=
convertBlobTo( (String) parameterNames.elementAt( i ), blob );
// (example: param =
// convertBlobToNameAddressObject( (String) parameterNames.elementAt( 0 ), blob );
//
// note: you have to implement this conversion routine for each parameter type
2. Perform the remote method invocation(s) (now you have all the information for that).
3. Convert the result(s) into (a) blob(s):
byte[] = convertToBlob(, );
//( byte[] resultBlob = convertNameAddressObjectToBlob(resultName, result);)
Note: For basic types as int, char ... this is easier (see SecondTestWrapper).
4. As soon as you got a result (there might be a couple if the method is invoked
several times for example in order to return several values), put it into a
ChaimsAttrValObject and add it to the (thereby growing) result container.
ChaimsAttrValObject =
new ChaimsAttrValObject( , );
setPartialResult( val_object );
If this was the last object you wanted to add to the result container then
declare this invocation as FINISHED by the instruction
setResultDone();
This is important, as it marks the corresponding call entry as "DONE".
e) For each parameter type you have to implement the method
convertBlobTo,
and for each return type you have to implement
convertToBlob.
This work means the most sensitive part in future, I guess, as it's difficult
to automate this. Right now you have to deal with blobs and gentypes in order to get
parameters or to ship results back.
For an example conversion see FirstTestWrapper.
Note: For basic types as int, char ... you don't have to implement those methods.
You can use some already existing (see SecondTestWrapper).