Galaxy Communicator Documentation:

MITRE Java Bindings


The Java bindings which MITRE is providing are a modification of Java bindings produced by Intel Corp. for a previous version of the Communicator implementation. We have updated and enhanced these bindings.


Enabling Java Bindings

The configuration templates/<arch-os>/config.make is where the setting for JDK_HOME should be placed. The bindings and the examples require Java 2 (i.e., JDK 1.2) or higher. Please mail all bugs and comments to  bugs-darpacomm@linus.mitre.org.


Documentation Summary

These bindings implement a subset of the what the C libraries support, including brokering. Support for dialog control is not available in this distribution.

For documentation of the API, see:


The following demos contain Java server examples. All examples can be found in the java/ subdirectory of these demos:

Among the major differences from the C bindings are: At the moment, the source code and examples will serve as the primary documentation, though the release notes and upgrade notes also contain useful information on the bindings.


Creating a Server

There are two main classes of interest when building a Java Galaxy Communicator server. The first is galaxy.server.MainServer. This class is responsible for creating and managing connections to Hubs. The connections are embodied by the second class, galaxy.server.Server. Subclasses of this class implement the dispatch functions that are invoked by the Hub directly (e.g., based on a program file) and indirectly (e.g., on the behalf of another Galaxy Communicator server). Currently, an instance of MainServer can only start up Servers of one type. The Server type is set programmatically using MainServer.setServerClassName (see the example below).

An instance of MainServer can be configured to run in one of three modes. In the first (default) mode (using the -port command line argument described below or relying on the default port), the server listens on a port for connection requests from Hubs and instantiates a new Server for each new connection. In the second mode, MainServer can be configured to connect to one or more Hubs (using the -contact_hub command line argument). For each connection, it instantiates a Server  to handle the connection. In the third mode (using both -port and -contact_hub), MainServer acts as a Hub listener and client concurrently.

As mentioned above, the Server class encapsulates a connection to a Hub. When you extend this class, all operations defined by serverOpOperationName will be interpreted as operations that a Hub or another Galaxy Communicator server can call. serverOpOperationName is equivalent to "operation_name" in Hub program file syntax. When a Java server receives an operation name in a frame, it follows these steps to convert the operation into the name of a Java method. First, it removes all underscore (_) characters and converts the letter after the underscore to uppercase (e.g., "operation_name" becomes "operationName"). Second, it converts the first letter of the operation name to uppercase ("operationName" becomes "OperationName"). Finally, it prepends "serverOp" to the operation name ("OperationName" becomes "serverOpOperationName"). Keep these rules in mind when specifying operation names in program files and Java code.

Below is an example of a Java main method that starts a Galaxy Communicator server. The instance of MainServer is initialized with the command line arguments (see descriptions below), and the Server type for the server is set by the call to MainServer.setServerClassName. Calling MainServer.start starts the server.

 public static void main(String[] args)
 {
     MainServer mainServer = new MainServer(server name, args);
     mainServer.setServerClassName(name of a subclass of galaxy.server.Server);

     try {
         mainServer.start();
     } catch(Exception e) {
         System.out.println(e.toString());
     }
 }

A third class, galaxy.server.ui.ServerUI, is useful for embedding a server in a simple user interface. This class instantiates a  MainServer and provides a user interface with logging capability and the ability to start and stop the server.   Below is an example of a Java main method that creates an instance of ServerUI.

public static void main(String[] args)
{
    ServerUI ui = new ServerUI(args) {
          protected void init() {
              serverClassName = name of a subclass of galaxy.server.Server;
              port = optional default port number;
              serverName = server name;
          }
    };
}

The examples in this distribution tend to use  ServerUI, though the source code for the basic Java server example does contain examples of how to created UI-less servers.

Command Line Arguments

The following are of the built-in command line arguments for Java Galaxy Communicator servers:
 
-port <port number> Specifies the port on which this server will listen for connections.
-verbosity <verbosity level> The logging verbosity level. Currently, the only valid values are 0 (no logging) or 1 (all logging on, the default).
-assert Prevent the server from searching for a free port if the specified port (or default port if there is no -port argument) is not available.
-maxconns <max number of connections> Maximum number of client connections supported by this server's listener (if not > 0, no limit is set). If this argument is used, but no value is specified, a default of 1 is used.
-validate Validate Server method signatures.
-contact_hub <host:port ...> Hosts and ports of Hubs to contact on startup. Note that host/port pairs are separated by whitespace, and multiple host/port pairs must be enclosed in double quotes, e.g., -contact_hub "localhost:123 localhost:456".
-session_id <id> If -contact_hub is used, lock this client to the specified Hub session.
-server_locations_file <file> A file of lines of the form: <server name> <host:port> [hub|server]. This file defines the locations of the listeners to use (be they in servers or Hubs).
-ui Starts the server's user interface. If this argument is not used, the user interface is not displayed and all output is sent to standard error (typically the display screen). This argument is only processed by ServerUI-based servers.
-no_output Starts the server and doesn't print any output anywhere. This argument is only processed by ServerUI-based servers.
-start Automatically starts the server (you don't need to click the Start button in the user interface). This argument is only processed by ServerUI-based servers.
-log <log file name> Sets the name of the log file. This argument is only processed by ServerUI-based servers.
-append_log If the log file already exists, append to it. This argument is only processed by ServerUI-based servers.
-main_server_class <server class name> The name of the MainServer class to start. This argument is only processed by ServerUI-based servers.
-help Displays descriptions of the above command line arguments.

Subclasses of MainServer and ServerUI can access their parent class's instance of galaxy.server.ServerArgParser (for subclasses of MainServer, this parser object is only useful if the constructor that takes the argument list was used). The methods on the interface of ServerArgParser (the useful methods are actually implemented by its parent class, galaxy.util.ArgParser) can be used to examine the argument list (e.g., to extract the values of custom-defined arguments). The ServerArgParser constructor that takes a second string argument allows developers to add information on custom command line arguments to the usage message that is displayed by the -help command line argument.

Continuations

When you wish to call a dispatch function from a server and allow the Hub to send the sending server other messages BEFORE the reply to the dispatch function is sent back to the server, you must call the dispatchFrameWithConinuation method on the server's current call environment (of type galaxy.server.Environment). The current environment can be obtained from a galaxy.server.Server via the server's getCurrentEnvironment method:

public boolean dispatchFrameWithContinuation(GFrame frame, Continuation continuation,
                                             Object continuationState)

This method's arguments include the frame that is to be dispatched to the Hub, a continuation object (discussed below), and state data used by the continuation. A continuation object implements the galaxy.server.Continuation interface:

public interface Continuation
{
    public GFrame run(GFrame frame, int msgType, Object continuationState, Environment env);
}

When the server receives the reply to a dispatch function that was called with dispatchFrameWithConinuation, it looks up the appropriate continuation object and invokes its run method, passing in the Hub's reply frame, the message type of the message that contained the reply frame, the state data that was passed into the original call to dispatchFrameWithConinuation, and the call environment from when the server originally dispatched the frame (i.e., no necessarily the server's current call environment). The run method is responsible for processing the reply just as if it had been returned immediately after the server called the dispatch function. The code segment below (from DoubleServer.java) illustrates this new functionality.

    Example

    public class DoubleServer extends galaxy.server.Server {

    ...

    public GFrame serverOpContinuationComplexTwice(GFrame frame)
    {
     GFrame newFrame = new Clause("multiply");
     int i = ((Integer)frame.getProperty(":int")).intValue();
     newFrame.setProperty(":int", i);
     ContinueComplexTwice continueComplexTwice = new ContinueComplexTwice();
     getCurrentEnvironment().dispatchFrameWithContinuation(newFrame, continueComplexTwice, frame);
     return (GFrame) null;
    }

    class ContinueComplexTwice implements Continuation
    {
         public GFrame run(GFrame frame, int msgType, Object continuationState, Environment env)
         {
             GFrame origFrame = (GFrame) continuationState;
             GFrame returnFrame;
             GFrame twiceFrame;
             String progName;

             if (frame == null) {
              logWarning("Didn't hear back from multiply");
              return (GFrame) null;
             }

             switch (msgType) {
             case GalaxyMessage.GAL_REPLY_MSG_TYPE:
                  progName = origFrame.getString(":program");
                  if (progName == null)
                      progName = "main";

                  twiceFrame = new Clause("twice");
                  twiceFrame.setProperty(":program", progName);
                  int i = ((Integer)frame.getProperty(":int")).intValue();
                  twiceFrame.setProperty(":int", i);
                  returnFrame = serverOpTwice(twiceFrame);
                  return returnFrame;
             case GalaxyMessage.GAL_ERROR_MSG_TYPE:
                  return (GFrame) null;
             default:
                  return (GFrame) null;
             }
         }
    }
 

Calling Dispatch Functions From Incoming Brokers

Incoming brokers can now call dispatch functions on servers by using the Hub connection of the galaxy.server.Server that created the broker. This is done by calling the dispatchFrame method on the interface of the broker's galaxy.server.Environment object (NOTE: use the broker's local environment object; do NOT use the current environment of the galaxy.server.Server that created the broker). In addition, the broker can register with the galaxy.server.Server object that created it by calling galaxy.server.DataInBroker.registerWithServer. This registration will force the server to destroy the broker if the server loses its connection to the Hub. This prevents the broker from trying to send messages to the Hub on a connection that no longer exists. Use galaxy.server.DataInBroker.unregisterFromServer to unregister from the server.

Sending Messages to the Hub

The new, preferred way to send new messages and replies to the Hub from an instance of galaxy.server.Server  is to use galaxy.server.Server.getCurrentEnvironment to get a reference to the current call environment and use the methods on its interface (writeFrame, reply, error, error (second version), destroyToken, dispatchFrame) to send messages to the Hub. This replaces the use of writeMessage, writeErrorMessage, writeFrame, writeDestroyMessage and dispatchFrame on the interface of galaxy.server.Server (these methods have been deprecated as of 3.0).

Contacting a Hub at Runtime

It is now possible to establish a client connection to a Hub at runtime using the contactHub method on the interface of galaxy.server.MainServer. This would typically be done from a class that extends galaxy.server.Server, but it can be done from any class that has a reference to a MainServer . If a connection is established, a new Server object of the type supported by the MainServer instance  is created. However, the reference to this new connection is not returned to the caller due to the variability in the connection policies supported by contactHub (discussed below).

    Example

            MainServer mainServer;
    ...
    mainServer.contactHub("localhost", 12345, "foo",
          MainServer.GAL_HUB_CLIENT_CONNECT_FAILURE_NOOP |
          MainServer.GAL_HUB_CLIENT_DISCONNECT_SHUTDOWN);

The first two arguments to contactHub are the host name and port of the Hub to contact. The third argument is the initial session id of the connection that is to be created. The fourth argument is a flag that specifies the connection policy to use (if this is -1, the connection policy of the invoked MainServer  is used). This last argument is either set to MainServer.DEFAULT_HUB_CONTACT_POLICY or an or'ed (using the Java bitwsie or, |, operator) combination of one of

MainServer.GAL_HUB_CLIENT_CONNECT_FAILURE_RETRY: Indicates server should keep trying to contact Hub until initial connection is established.
MainServer.GAL_HUB_CLIENT_CONNECT_FAILURE_SHUTDOWN: Indicates server should shutdown if initial connection to Hub can not be established.
MainServer.GAL_HUB_CLIENT_CONNECT_FAILURE_NOOP: Indicates server should do nothing if initial connection to Hub can not be established.

and one of

MainServer.GAL_HUB_CLIENT_DISCONNECT_RETRY: Indicates server should keep trying to re-establish contact to Hub if the connection is lost.
MainServer.GAL_HUB_CLIENT_DISCONNECT_SHUTDOWN: Indicates server should shutdown if connection to Hub is lost.
MainServer.GAL_HUB_CLIENT_DISCONNECT_NOOP: Indicates server should do nothing if connection to Hub is lost.

The default policy (MainServer.DEFAULT_HUB_CONTACT_POLICY )  is to keep trying to establish the initial connection to the Hub until successful. If the connection to the Hub is later lost, keep trying to reconnect. The default policy of a MainServer  can be set and get with the methods setHubContactPolicy and getHubContactPolicy and you can set and get the policy of a given  Server object with its own  setHubContactPolicy and getHubContactPolicy methods.

Server and Session Properties

The Hub keeps track of properties for servers and sessions. There are various methods on the interfaces of galaxy.server.Server and galaxy.server.Environment for accessing and manipulating these values. See the discussion of properties in the C binding documentation for more details on the use of properties.

Methods on the interface of galaxy.server.Server:

Methods on the interface of galaxy.server.Environment (note that these methods act on the server and session associated with the invoked environment object):

Setting Session Id

There are now methods on the interface of galaxy.server.Environment that allow the environment's session id to be changed:

Postponing a Reply

When a galaxy.server.Server dispatch function is invoked by the Hub, the server can call galaxy.server.Environment.postoneReply on the current environment to inform the Hub that the response to its message will be delayed, but that in the meantime it's available for other incoming messages.


Change Log

January 2002

June 2001

December 2000

August 2000

February 2000

January 1999



Please send comments and suggestions to: bugs-darpacomm@linus.mitre.org
Last modified January 9, 2002

Copyright (c) 1998-2002
The MITRE Corporation
ALL RIGHTS RESERVED