Context Toolkit: Tutorial: BaseObject

BaseObject supports communications between context components (widgets, servers, and interpreters) and between applications and context components. First, I'll describe the features of BaseObject and then talk about how to actually use it. Also take a look at the source code documentation for the BaseObject class.



Features

In this section, I'll describe the basic features of BaseObject. BaseObject is exactly that, a base object from which other objects are derived. BaseObject provides the basic functionality used by applications, context widgets, context interpreters, and context servers. Basically, it provides the capabilities for components to communicate with each other. The context architecture is set up as a collection of peer-to-peer entities, so BaseObject supports both client communications and server communications. In order for components to communicate, they must either subclass BaseObject or create an instance of it. Typically applications create an instance of it (due to Java's single inheritance rule) and the other components subclass from it.
Server Communications
BaseObject supports server-like communications capabilities. It listens for incoming communications on a given port and forks off threads to handle those communications, allowing for concurrent message handling. When a message is received, the protocol is stripped off, and the message is decoded. The decoded message is then routed appropriately to be handled.
Client Communications
BaseObject supports client-like communications capabilities. It allows users to send messages to other context components. It encodes the outgoing message, adds the network protocol and sends the message.
Communications
In order to run on a wide variety of platforms and to inter-operate with components written in many languages, BaseObject uses a generic encoding and protocol for communications. For the encoding language, XML is used. XML parsers are available in almost every programming language (and are simple to write, if not available for your favorite language) and require only ASCII parsing from the platform. For the network protocol, HTTP is used. HTTP libraries are also available in almost every programming language (and is easy to write, if not), and only require that the language and platform support TCP-IP communications. Because both XML and HTTP are verbose and inefficient, BaseObject supports the use of other programmer-provided encoding languages and protocols. This will be described later.

How to Use It

In this section, I'll describe how to use the generic features in BaseObject. As many of the functions are relevant to particular context components, I'll leave the discussion of those functions until I present those context components. The javadocs for BaseObject are here.
Creating a BaseObject
A parameter for BaseObject is the server port number. This is the port on which this class receives incoming communications (when acting as a server). Most users of the BaseObject class will simply provide a port number for the server to use and use this simple constructor.

  public BaseObject(int port)

Applications wanting to use the context infrastructure can either create an instance of BaseObject or can subclass from it. For those wanting more details about the other parameters, continue. Otherwise, you can move to the next section on generic messages that can be sent via the BaseObject.

 BaseObject has a number of constructors. I'll describe the most generic. The other constructors are simplifications that eventually call this constructor. The generic constructor is here.

  public BaseObject(String clientClass,
                    String serverClass,
                    int serverPort,
                    String encoderClass,
                    String decoderClass)

 BaseObject has a pluggable communications mechanism. I'll first describe how to change the communications protocol used. The default communications protocol is HTTP. To use a different protocol, simply provide the names of the classes that implements the new protocol. One class is used to handle incoming communications (server) and respond to them, and the other for outgoing communications (client) and handling the result. This first class must implement the interface context.arch.comm.CommunicationsServer and the second class must implement the interface context.arch.comm.CommunicationsClient. If the value null is provided for these classes, the default HTTP implementation is used.

 To change the communications language from the default XML, simply provide the names of the classes that implement the encoding and decoding of the desired language. The encoder class must implement the interface context.arch.comm.language.EncoderInterface. The decoder class must implement the interface context.arch.comm.language.DecoderInterface. If the value null is provided for these classes, the default XML implementation is used.

Generic Messages
There are only 2 generic messages that BaseObject can send. One is to query context components about their version number and the other is to ping a component to check if it is alive.

 The following is an example of an application working with a PersonPresence widget on the local machine, port 5555. The application creates a BaseObject, requests the version of a PersonPresence widget and pings it.

  BaseObject server = new BaseObject(7777); // create BaseObject running on port 7777

  DataObject dataVersion = server.getVersion("localhost",5555,"PersonPresence_here"); // request the version number
  String versionError = new Error(dataVersion).getError();
  if (versionError.equals(Error.NO_ERROR)) {
    System.out.println("Version is:" +(String)version.getDataObject(WPersonPresence.VERSION).getValue().firstElement();
  }
  else {
    System.out.println("Error = "+versionError);
  }
  DataObject dataPing = server.pingComponent("localhost",5555,"PersonPresence_here"); // ping
  String pingError = new Error(dataPing).getError();
  System.out.println("Ping results = "+pingError);
If the result of either query is Error.NO_ERROR, the query was successful. Otherwise, there was an error, specified in the returned error result. Both of these queries return their results in the form of a DataObject. DataObject is an data storage object used in communications. It is used as an intermediate step between communication language-specific (default is XML) data structures and the data structures used by the context infrastructure. If a developer replaces the default XML implementation with the implementation of a different language, the interfaces they must support include the ability to convert back and forth between language specific data structures and DataObjects. Similarly, all the data structures in the context infrastructure have methods that allow them to be converted to and from DataObjects.
Message Handling
When an message incoming message has been decoded, BaseObject either handles the message automatically, if it is able to, or routes it to someone who can. This is done in BaseObject's runMethod.This method checks to see if the incoming message is the result of a subscription to another component. If so, the message is error-checked and passed on to the handler that is responsible for this subscription callback. BaseObject is also able to handle version queries, pinging, and handling the results of an asynchronous service (in the case of a BaseObject requesting a service be run by another component). If the message does not fall into any of these categories, it calls runUserMethod. This method does nothing and is overridden by each of the other context components that subclass from it.

Useful Classes

This is a list of useful classes, in case you're being brave and want to see what's happening beneath the covers of BaseObject.
CommunicationsObject
The CommunicationsObject object is responsible for listening for messages on a given port and sending out messages. When messages arrive, it strips off the network protocol and decodes the message. When messages are being sent out, it encodes the message and adds the network protocol. It is through this object that users are allowed to specify their own network protocol, if the default HTTP is not desired. This object uses two other objects, a CommunicationsServer and a CommunicationsClient.
CommunicationsServer
The CommunicationsServer is really an interface that indicates what methods a server must support.
HTTPServerSocket
The HTTPServerSocket object implements the CommunicationsServer interface using the HTTP network protocol.
CommunicationsClient
The CommunicationsClient is really an interface that indicates what methods a client must support.
HTTPClientSocket
The HTTPClientSocket object implements the CommunicationsClient interface using the HTTP network protocol..
ParserObject
The ParserObject is responsible for providing the encoding and decoding of outoing and incoming messages. It is through this object that users are allowed to specify their own language to use for encoding and decoding, if the default XML is not desired. This object uses two other objects, an EncoderInterface and a DecoderInterface.
 
EncoderInterface
The EncoderInterface is an interface that indicates what methods a class responsible for encoding outgoing messages must support.
XMLEncoder
The XMLEncoder object implements the EncoderInterface using XML
DecoderInterface
The DecoderInterface is an interface that indicates what methods a class responsible for decoding incoming messages must support.
SAX_XMLDecoder
The SAX_XMLDecoder object implements the DecoderInterface using XML (and in particular, the uses the SAX XML decoder).
Handlers
BaseObject creates an instance of a Handlers object. The Handlers object is responsible for maintaining the mapping between subscriptions made via this BaseObject and the objects that will handle the subscription callbacks. Also see Handler. More information on this will come in the discussion of widget subscriptions.
AsyncServiceHandlers
BaseObject creates an instance of an AsyncServiceHandlers object. The AsyncServiceHandlers object is responsible for maintaining the mapping between asynchronous service calls made via this BaseObject and the objects that will handle the results of the asynchronous services. Also see AsyncServiceHandler. More information on this will come in the discussion of widget services.


Back to the Table of Contents.

Back to the Components section.
Forward to the Context Widgets section.


Context Toolkit Home
Last Modified: Feburary 11, 2000
Comments to: anind@cc.gatech.edu