Server Handler


Introduction

To support modularity and still allow for fault tolerance in the framework, we have split the design of the communication layer into two sublayers. The first of them is the set of required functionalities that are required for fault-tolerant behavior of the framework for communication purposes. We call this sublayer meta-protocol (which is an abstract sublayer, described as an interface called ClientSideProtocolInterface in the framework). The second sublayer, the protocol is any construct that supplies these minimum required functionalities.

The minimum required functionalities for the meta-protocol (on the client side) are:

  1. Provide the means to connect to the server;
  2. Provide the ability to disconnect from the server;
  3. Provide the ability to probe the connection status to the server;
  4. Provide the means to convert abstract server jobs to protocol specific ones if necessary; and
  5. Provide the means to submit a job to the server.

Any class that implements these functionalities is a proper client side communication protocol. Note that there is an analogous set of requirements on the server side as well. This will be covered in the client handler tutorial.

What is the server handler?

The server handler sits on the client side and handles the communication between the client and the server. It ensures the proper delivery of the jobs from the client to the server and informs the client (through listeners) in the case of successful delivery of a job to the server. When the server handler informs the client of the delivery, it passes through the server reply as well.

This fault tolerance includes cases where the server is unavailable (due to network problems, downtime, high load, etc). It also includes cases where the telemonitoring node (or is properly closed) in the interim between the request to submit a job and the actual (physical) submission of the job. These jobs are backed up using a backup cabinet and is restored the next time the telemonitoring node is restarted.

How to use the server handler?

In order to initialize a server handler object, you need a client side protocol object. We have implemented an example protocol on top of TLS (or SSL if you choose) that is ready for use called TIProtocol. We will use this protocol for this tutorial (but any protocol/object that implements ClientSideProtocolInterface works). The following is a snippet of code that initializes a protocol object and then uses it to initialize a server handler:

where context  is the Android context used for the purposes of the server handler (such as scheduling, etc) and connectionInterval is the time interval between consecutive trials of job submissions (thereafter: job sync) in milliseconds, or 0 for immediate job sync (after every request, see next) or -1 for manual job sync (has to be manually invoked as  serverHandler.manualOffload() .

A job object  jobExample can be submitted to the server handled by the server handler serverHandler by invoking  serverHandler.sendJob(jobExample) . This requires preparing a job object from the telemonitoring primitives required. In order to ease the process even more, a couple of methods were implemented to handle submitting data jobs and request jobs. Those methods are respectively:

  1. serverHandler.sendData(dataId, jobHandler) : prior to using this method, the data encapsulator identified by the identifier  dataId has to be registered with the server handler by invoking  serverHandler.registerData(encapsulator, isVolatile)  where you can pass isVolatile=false if you want the server handler to handle the backup of the data in the encapsulator and  isVolatile=true  otherwise.
  2. serverHandler.sendRequest(requestId, requestHandler): Where requestId is the request identifier (of type RequestJobIdentifier)

Why and how to ensure server handlers are unique (SingletonServerHandler)?

Only one  ServerHandler instance should exist for each server connection. However, due to Android’s peculiarities, it is possible that multiple instances exist at a given moment even if your application only instantiates it once. To prevent this from happening, we highly recommend creating a singleton class from  ServerHandler, which guarantees that only one instance exists.

You can create your own singleton class by extending from ServerHandler, as shown in the code template for a  SingletonServerHandler below. A description of how to use it follows.

The basic idea of SingletonServerHandler is that it cannot be directly instantiated and accessed. Instead, it is always accessed through its own getInstance() method. This method is responsible for both instantiating and allowing access to the instance, and makes sure that only one instance exists. Its use will be explained in greater detail below.

How to configure SingletonServerHandler?

Before the very first call to getInstance(), the update period and protocol of the server handler must be configured. They can be set by calling the setSingletonSyncRate() and the setSingletonProtocol() methods, respectively, with their desired values as arguments. If this is not done, an attempt to get an instance of  SingletonServerHandler will result in a thrown ServerHandlerException.

If an instance of  SingletonServerHandler already exists, then its update period can be reconfigured through the setSingletonSyncRate() method. However, the protocol of the server handler cannot be reconfigured, and any attempt to do so will simply have no effect.

How to use SingletonServerHandler?

Once configured, you can get an instance of SingletonServerHandler by calling its  getInstance() method instead of calling its constructor. In fact, the singleton class’s constructor is private to ensure that it is never accidentally called outside of getInstance(), which makes sure that there is never more than one instance. In other words, call getInstance() wherever you would normally call the constructor.

How to deal with multiple server handlers?

For each server handler you need, you would have to create a separate singleton class that extends ServerHandler exactly like the SingletonServerHandler example, but with a different class name. This inconvenience unfortunately arises from limitations in the Java programming language. However, we still highly recommend this as standard practice when using server handlers, as not doing so may lead to unpredictable behavior of your application, especially when data is transmitted from client nodes to servers.

Running Example

(TODO: complete)