6.7 Remote Procedure Calls

This section defines how code executing at the Xma client can invoke XMA server code. The highlighted elements in the following figure shows the context of the problem:

RPC context

Figure 6.8. RPC context


From time to time, the code executing in the client-half of a particular component must call some business logic in the server component, for example to query a legacy system or store data in the database. The built-in XMA RPC mechanism has the following properties:

  • XMA supports synchronous calls (that we term RPC in this section), i.e., the execution of the client code blocks until the server finished processing.

  • All widget models are synchronized automatically between client and server. When the flow of control leaves the client and before the server method gains control, all widget models that have been changed at the client are transferred to the server. Likewise, at the end of the server method, before the control is transferred back to the client code again, modified models at the server are transferred to the client. The net effect is that the programmer always accesses the same state of the models, whether he's executing client or server-code.

The XMA programmer initiates the RPC at the client side. He (she) does this either at the component or at the page level through calling one of the following methods:

PageClient.newRemoteCall (namEvent : String) : RemoteCall
ComponentClient.newRemoteCall (namEvent : String) : RemoteCall
Either methods internally use the right RemoteCall constructor (actually a constructor in the class RemoteCallClient ). Method execute in class RemoteCallClient actually does the remote call. Therefore, a typical code fragment within a Page or Component would look like:
newRemoteCall ("searchClients").execute ();    
This is the very short version of the following code snippet:
RemoteCallClient call = new RemoteCallClient (this, "searchClients");
RemoteReply reply = call.execute();
Explicitly dealing with RemoteCallClient and RemoteReply objects is necessary if the programmer wants to transmit custom data.

At the server side, the programmer must implement a method which is the endpoint of the call using the following signature:

public void <namEvent> (RemoteCall call, RemoteReply reply);    
where the name of the method must be equal to the name used at the client side in the construction step of the RemoteCallClient object. Note that this method must be located in the component or page that is the server side buddy of the client component or page where the call is launched. In the example above, the server side page or component is required to include the following method:
public void searchClients (RemoteCall call, RemoteReply reply);    

The concept of XMA mandates that data is primarily transferred via widget models since we are within the scope of a light client, i.e., a client which just executes presentation related logic and definitely not business logic that is unrelated to presentation aspects. Nevertheless, situations might arise where the transfer of custom data might make sense. Therefore, both RemoteCall and RemoteReply might be supplied with custom data which must be added/queried using the following methods in class RemoteOperation , that is the base class of RemoteCall and RemoteReply .

RemoteOperation.setParameter (int index, Object value)
Object RemoteOperation.getParameter (int index)     
Objects are added using positional indexes as keys and java.lang.Objects as values. Values might be complex Java objects abiding to the following restrictions:
  1. Values must implement java.io.Serializable .

  2. The set of objects in the serialized object tree spanned by traversing non-transient object references from value must also implement java.io.Serializable .

  3. All classes (and superclasses and superinterfaces) of objects defined by the previous point must be available in the client half deployment unit of the component, since they must be deserialized at the client side.

  4. Since ordinary Java serialization is used to map the values to transport byte[] and vice versa, all restrictions of Java serialization (known and unknown ones) apply. Since this facility may only be used in rare cases, the following architectural guide lines apply (this is normative, not just a recommendation):

  5. Java serialization is inefficient . Have a look at the transferred data volume which is output to the console at every RPC at the XMA developers seat.

  6. The feature must not be used if the serialized Java classes (defined by point 3 above) would increase the size of the client component jar file by more than 10 %. Keep in mind that client jar files are dynamically deployed to the client. Client component jar files must be kept small in size, on the order of no more than 20 KBytes. You cannot include class files of, say 100 KBytes just to be able to deserialize a object at the client.

[Tip]

Now and then, you may include a parameter in a RPC that is of a built-in type, like java.lang.String or java.lang.Integer .

[Tip]

If some business logic at the server constructs a Notification that should be displayed at the client, you may use the parameter feature to transmit the Notification back to the client.

[Caution]

If you are including the same parameter in every RPC, you should use a hidden widget model or an internal component property instead. A hidden widget model is a widget model that has no UI-representation. You may define a hidden widgets and component properties in the UI designer.

[Caution]

You must not include exceptions as parameters. Exceptions are transferred automatically by the XMA runtime.

[Caution]

Since the class-files of custom parameters need to be available at the Xma client, they must be included in some downloaded jar-file. This increases the download size and makes the XMA client increasingly fat.

[Caution]

Including parameters of types that are not simple wrapper types from java.lang is inefficient.

The RemoteOperation indices are defined as int. To use a name like mechanism a class with int constants must be defined which is available at the XMA client and server. Let's assume this class is named at.spardat.test.constants.RPCParamter. To make this class available at the client and server side search in the build.xml of your XMA project for the common.jar target. Add entries like shown in the example. These include the class in the commonclient.jar and commonserver.jar:

<target name="common_jars" depends="compile">

    <!-- add your shared client files here: -->
    <fileset dir="${classDir}" id="commonclient_fileset">
        <include name="at/spardat/xma/security/*.properties"/>
        <include name="at/spardat/test/constants/RPCParamter.class"/>
    </fileset>

    <!-- build common client jar file -->
    <jar jarfile="${libDir}/commonclient.jar" update="true">
        <fileset refid="commonclient_fileset"/>
    </jar>

    <xmachecksum file="${libDir}/commonclient.jar"/>

    <!-- build common server jar file -->
    <!-- add your common package files here   -->
      <fileset id="commonserver_fileset" dir="${classDir}">
          <include name="at/spardat/xma/security/*.properties"/>
          <include name="root.properties"/>
          <include name="at/spardat/test/constants/RPCParamter.class"/>
      </fileset>

    <jar jarfile="${libDir}/commonserver.jar">
        <fileset refid="commonserver_fileset"/>
    </jar>

</target>

Now the RPCParamter class can be used for paramter setting and reading:

RemoteOperation.setParameter (RPCParamter.PDF_PRINT , someObject)
Object RemoteOperation.getParameter (RPCParamter.PDF_PRINT)