TechDoc: Method Calls and Events on Remote Objects

Posted on May 19, 2011

0


Remote Objects

A Remote Object is – in principle – any object that extends the BaseRemoteObject class.

Remote Objects are representatives of one single Object, but distributed over multiple locations.

Purpose 1: synchronizing objects

When the user changes the values on a Remote Object and that change is submitted to the Cluster, we want those changes to reflect everywhere.

For this we have an Event containing the JSON of the Remote Object, wrapped in a Remote Object Message Object. The Remote Object and its events within your application are discussed in some detail below.

Purpose 2: calling methods in Remote Objects

When we call a method on a Remote Object, like “Remove from database”, we want that event to happen where it matters: at the host that provides us access to the database.

As you will find out, we can do that on Static Methods (“Remoteclass.removeObjectFromDB( objectID )”) and directly on the Remote Object itself (“this.removeObjectFromDB()”).

This call or “Request” will be sent to anyone who is listening to your Remote Object Class, as you have no clue who can- and wants to respond.

In general, you will limit the amount of Classes that will respond.

Events

A Remote Object can send and receive events from any SandBox it is connected to, including:

  1. Requests – Very much like a Remote Method Call. A request expects a return value from anyone who responds. The Request Object is held in memory, to deal with responses.
  2. Responses – Very much like the “return” statement in a method. It is sent directly to the Requester, based on the “senderRemoteClientID” which contains the Socket Client ID and the IP number of the Server to which the requester is attached.
  3. Calls – Very much like a method call to a method returning: “void”. Calls do not expect a return value. The Call Object is not held in memory as it expects no Reply.
  4. Commands – Contains a serialized Command Object to be unwrapped at the receiving side. When unwrapped, the Command Object will be executed.
  5. Remote Objects – Serialized to JSON and automatically unwrapped to an object. It uses a Remote Object ID which is based on the object ID plus the Class Identifier and the SandBox it houses in. When an object already exists, the values in the Remote Object will be injected in the existing object and a: “onDatachange” event will be fired on the object.

Scope of a Remote Object

The scope of a Remote Object is determined by:

  1. The SandBox a Remote Object is part of – Any Remote Object can have multiple instances in multiple Sandboxes, but only Remote Objects in the same SandBox are considered to be equal.
  2. The Class Identifier – A Remote Object lives in a specific Class (is of type <Class>).
  3. The Remote Object ID – Which is the unique Identifier with which Remote Objects can identify themselves over the Application Cluster.
This scope can also be found back in how Remote Objects and their Events are managed. You will always have to state the Sandbox, Class Identifier and Remote Object ID to an Event Handler when you send a Message (Event) from an Object.
In general Events will never appear outside their Sandbox and be directly sent to the Class that is – via a listener on the Sandbox – mapped using the SandBox name and the Class Identifier Name.
Similar Remote Objects not being updated, due to the fact that they belong to another SandBox.

SandBoxes and Events

SandBoxes are – in most cases – covered by the Framework where it regards Events.
When your Class receives a Remote Object from a specific SandBox, it will link that Remote Object specifically to that SandBox. This means that the only thing you have to do from a Remote Object is to send the message. All the scoping will be done behind the scenes.

Messages and Observers

Everything between Remote Objects in the HotForestGreen framework is based on Events, packaged in messages. If you dig deep enough in the code, you will find SandBox Event Listeners and something similar to SandBox Event Dispatchers sending out and receiving messages.
On the Server side it is even simpler: Every Message passing is in the basis an Event Package to be dispatched to Observers.

Registering Observers

Each Remote Object Class is observing one or more SandBoxes once it is registered to those SandBoxes. When a Message arrives in the SandBox of a Remote Object Client, it will check the Observers listed in that Message and dispatch the Message to any Observer that has registered itself on the Client side.

Keeping it simple

When an Remote Object Class registers itself to a SandBox, it uses a standardized String value for the Event it wants to observe, including two elements:
  1. The Class Identifier – Which is shared throughout  the entire application. For instance: “Door” for a class representing doors in a house.
  2. A generic string value stating it is a Class observing – In this case: “object_class_identifier_”
When we send an Remote Object Update to all listeners, we do that to the SandBox the object is registered to and using the:  “object_class_identifier_” base name to identify the Observers who will receive the Update. The Class itself, using Static Methods, will resolve the Message from that point on.

Sending an Event

An Event is always sent to anyone who is listening. Events are packaged as:
  1. Requests
  2. Calls
  3. Commands
  4. Remote Objects

Clarification – Request and Reply

In the image above, you see a scenario where one Remote Object sends a Request to all its Peers and receives a Reply from one.
In principle any Remote Object can send a Reply back to the Requester, but to avoid an overload, best is to limit this to only a few.

Using internal events on Objects and Classes

When a Remote Object Class receives an Object this can be either:

  1. A new object – Not yet registered in the local repository
  2. An update on an existing object – Which we already have and will update with the data in the JSON object
The events we dispatch within our local Object Model are:
  1. “Object Updated” – Both on:
    1. The actual object  – Helping anyone using or displaying the data inside that object to take action update their things as well.
    2. The Class containing that object – Helping us on a broader scale to manage the object and do some more global actions. for instance: in Flash we do not want to listen to individual objects, but simply refresh the (visible part of the) list as a whole when something changes.
  2. “Object Added” – Only on:
    1. The Class containing that object – Helping us on a broader scale to manage the object and do some more global actions
  3. “Object removed” – Both on
    1. The actual object  – Helping anyone using or displaying the data inside that object to take action update their things as well.
    2. The Class containing that object – Helping us on a broader scale to manage the object and do some more global actions. For instance: on lists and list items. We do not want to listen to individual objects, but simply refresh the (visible part of the) list as a whole when something changes.
You can add your listener / observer to an object and class
In the image above, you see a Remote Object sending a Remote Object Update.
The Command can (and in the case of the Update) will trigger an event on the receiving side.
You can use this event form a Remote Object to update things on your screen, or initiate successive actions Client side.

Using this model – an example

Request and Reply – Use to call methods on Representatives of your Remote Object.  If your local Object has a method “myDoor.openDoor()”, let this method call the “openDoor()” method on the object representing.
The Reply can be a: “door opened successfully” or “failed”.
Request and Object Update – As a result of a request from the Client side, the Object that successfully handles that request can send an Object Update to all other Remote Objects, resulting in their
In the image above you see the scenario of Request and Object Update simplified. One Requests for Change is sent to all corresponding Remote Objects.
Only one Remote Object handles the Request. All others do not (dead requests).
As a result of the Successful Request, on the last Remote Obbject, that Remote Object is updated and within our setup, that Object will broadcast its updated state to all others.

The Inner Scope of Remote Objects

Remote Objects operate within their own Scope. For all events fired from within a Remote Object, nothing else but other Remote Object representing the exact same Object is relevant. We call this the “inner scope” of a Remote Object.
This approach allows you to set up Remote Objects which have predictable behavior.
  1. Using the inner scope of Remote Objects – Remote Objects locally initiated objects which keep a “hotline” with their peers. The “inner scope” of a Remote Object is basically any other representant of the Remote Object within the SandBox. Tied to Remote Objects are:
    1. “Updated” Event – The main event in a Remote Object is: “onDatachange”, which will be fired when the content of a Remote Object is injected in the instance of that Remote Object
    2. Internal Remote Method Calls – Each Remote Object can do a Request within its own Remote Object Scope. This request will be sent to anyone, using a Event Handler callback via the Request Object. When a Response is received, the Event Handler of the Request will be dispatched, thus updating the containing Remote Object that a response is received.
  2. Using Commands – Commands are tied to Command Objects. These Command Objects have an internal logic which can be executed when called. Commands are based on Remote Objects, but their life span is for the duration of the Command. After that they are destroyed.

Addressing Remote Static Classes – when you need more

When you need more than individual objects, you can access Remote Classes. The principle is exactly the same as with individual Remote Objects, but in this case, the reference “Remote Object ID” the Class is listening to is the word: “static”.
Any message sent using “static” as the Remote Object ID will be intercepted and executed in the Static scope by the Class itself.

Benefits: global API, reduction of complexity

Using Remote Static Methods allows you to access the entire Object Pool within that Static Class without being dependent of an Object being instantiated on the Remote side.
This can – for instance – be handy when you want to access a Database and expect a simple call to do the work for you.
The Class will operate as a Global API you can access and which will return and can produce objects it already had, or created newly for your benefit.
It also reduces code complexity.
In general my findings are that using Static APIs reduces a the code and complexity of an application. Especially when the Static API is dealing with the management of objects within its own scope.
Instead of building layers of managers around your Base Classes, you let these classes manage themselves and deliver you anything you need.

Dealing with return values in your Reply

When a Reply comes back to the Requester, this Reply can contain:

  1. A single Object
  2. A List of objects.

In principle this is a problem to be solved at the receiving end and by negotiating what will be returned from the Requested party. In other words: your code will define what you can expect and thus: how you should parse the return values.

The BaseRemoteObject Class contains a parser for any data, including lists which assures that Objects which already have been parsed will simply be updated instread of created anew.

This is only for Objects being part of your RemoteObjects family (created by extending the BaseRemoteObject Class).

Advertisements
Posted in: Uncategorized