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