TechDoc: Calling remote methods – Sending requests and responses

Posted on May 18, 2011

0


Requests and Responses

Requests – Are comparable to method calls, but then to all objects in the scope of your applation

Responses – Are responses to your Request.

Static and on Objects

There are two types of remote methods:

  1. Static methods – Which are implemented on Class-level and are called via ClassName.myStaticMethod();
  2. Methods on an Object – Which relate to a specific object
Both can be used.

Always between objects with the same Class Identifier

To keep the Request / Response model simple, we send them between objects with the same Class Identifier.

// Remote method "getData"
myRemoteObject.getData()

Will be addressed by the “local” application via:

// Local - getRemoteData will request action from the method "getData" 
myRepresentativeOfTheRemoteObject.getRemoteData()

From our local objects, we can then take extra actions.

Use something like “Remote” in your Remote Calls

The Local Request is executed on Remote Side via reflection. This means that by default all Classes – including the one you use to to Remote Calls – can receive a Remote Request. If you do do not take precautions, this might lead to unwanted calls all over your application.

Steps

  1. Register a Class to a SandBox – using the SandBox name and the Class Identifier (which is a usually a single word representative like “user” and “door”)
  2. Extend BaseRemoteObject on Remote and Local sides – To be able to send and receive Requests and Replies
  3. Making a Request with a handler to deal with the Reply – As the process is Asynchronous, we use a Handler to deal with the Reply that comes form the Remote Objects
  4. Define Methods on the Remote Side – To be called from the Requester side
  5. Execute a “sendResponse” on the Remote side – When the Request is handled and data has to be sent back to the Requester

Using Request Multicast and Single Receipient Reply

The SmartSpaces Remote Objects framework uses a Request Multicast and will only receive replies from those objects programmed to do so.

Remote Methods

Requests can be used to call Methods in Remote Objects. These Remote Methods are executed using Object Reflection on the Remote side.

Registering Object Classes to a SandBox

Before we can start receiving anything from a specific Sandbox, we need to register our Classes to that specific SandBox.

We do this via the following code:

string sandBoxName = "MySandbox";
string classIdentifier = "Door";
MyRemoteObject.registerToSandbox(sandBoxName, classIdentifier);

Extend BaseRemoteObject

Extending the BaseRemoteObject goes as follows:

// Extending in C# 
class MyRemoteObject: BaseRemoteObject
{
   // Do your magic
}

Making a Request with Reply Handler at the Requester side

From the caller-perspective, this is how you do it:

// Example code in an object called: "UserDataConnection"
pubic void get_UsersByName()
{
   string remoteMethod="getUsersByName";
 // We ask for all users with the name "John"
   object[] arguments= { "john" }
 // Send the request 
 this.sendRequest(remoteMethod, arguments, onDataReply_UsersByName)
}

// Our callback when the request is processed
private void onDataReply_UsersByName(
      Object dataObject, EventArgs eventArguments)
{
    // Do something with the data
}

The BaseRemoteObject Class will deal with the right addressing to the right observers in the SandBoxes you want to address.

By default (and in this case), the correct SandBox and Class Identifier name are retrieved from a private variable in BaseRemoteObject, containing the name of the SandBox as injected by the code from the message our Class received.

Sending a Response on the Remote Side

On the Remote side, we have something like the following:

// Our remote method in "UserDataConnection"
public string getUsersByName(string username)
{
     Object[] userdata;
     // DO SOME MAGIC to get userdata

    // Define which original request we answer to
     string requestName = "getUsersByName"
     // Return it to the requester. Data is form 
     this.sendResponse( requestName, userdata)
}

Behind the scenes on the Remote Side

When we receive a Request, the BaseRemoteObject class will deal with that as follows:

  1. The Request will be split into:
    1. The requestName – The name of our method to be called, for instance “getUsersByName”
    2. The Object ID – Pointing either to “static” or to a specific Object, for instance: “yourSandBox_user_23”
    3. The JSON objects – Representing the arguments we sent
  2. The JSON objects will be translated – To an Object we can use to inject Arguments into the Method we want to call
  3. The Method will be called with the Parameters – As passed via JSON
  4. The Command / Message will be stored – In memory, using the requestName and the Object ID as reference, to use to send the reply to the Requester
When the Remote Side is done, it will explicitly send a Response to the Caller.
The BaseRemoteObject will deal with the proper mapping, based on the values derived from internal variables.

Observers

When a Remote Class is registered, it registers an observer to the SandBox, using the following construction:

string observerName = "object_class_identifier_" + classIdentifier;

For instance:

string observerName = "object_class_identifier_Door";

Where classIdentifier is the global identifier through which we can find the Object Classes in which we want to inject values.

When an Observer is triggered by a Request or a Reply, it will process that Request / Reply and act accordingly to the local code.

Keeping in touch – Persistent Request Messages

Each Remote Object holds an internal overview:

  1. To which Sandbox it belongs – So that when we send a reply on a request, we know where it should go to
  2. To which Class Identifier it belongs – So that it ends up in the right Class and Object
  3. How to create the proper Observer Name – To send its messages to
When we send a Reply to a Request, we send that directly to the Requester. To do this:
  1. We store a persistent version of the Request Message – For reference, in order to build a reply to the right address
  2. We restore our Persistent Request Message – And read all the data that will tie or Reply to that specific Sender.
  3. We inject all the data needed to address the Reply to the Requester – So that it will only arrive where needed.

Asynchronous by default

Requests and Responses are Asynchronous by default. This means that a response (or multiple responses) will be returned on a later time, while your application already moved to the next steps to execute.

Object scope

All objects within a SmartSpace exist in a specific scope. This scope can be broken down in the following order:
  • Sandbox – The Sandbox in which our application runs and to which we are listening
    • Object Class – The Object Class in which our methods run
      • Object – The Object we want to address

Referencing a specific object

An object is referenced globally by using the following parameters:
  1. SandBox name – The name of the sandbox in which our Object lives
  2. Global Class Identifier – The Class-Identifier through which we access specific objects and classes in our Smart Space
  3. Object ID – The ID of a specific Object. Either generated on the fly, via a record ID in a database or via hardcoded values
The reference key for an individual object looks as follows:
  • “<SandBox Name>_<Class Identifier>_<Object ID>”
  • or: “Sandbox5_Door_23”

Why object references are so specific

Within a SmartSpace cluster it is possible we have multiple SandBoxes running. Each SandBox is a closed environment and data inside that SandBox should not leak to other SandBoxes, unless we explicitly build it that way.

If we have defined a “Door 1” in “SandBox 1” and copied this definition for a similar house in “SandBox 2”, we want “Door 1” only to open in “SandBox 1” and not in both.

Extending the base class BaseRemoteObject

When you want to create a Remote Object, you can use the BaseRemoteObject class as your Base class.

BaseRemoteObject contains methods to:

  1. Register your class to a Sandbox – In order to be able to send and receive data
  2. Send and receive messages – For instance to update objects or do a request

Sending a Request

A request is always sent:
  1. Within a specific SandBox
  2. To a specific Object Class – Using the Object Class Identifier
Advertisements
Posted in: Uncategorized