Galaxy Communicator Documentation:

MITRE Java Bindings

License / Documentation home / Help and feedback

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

See the installation documentation for how to enable the Java bindings. JDK 1.2 or later is required.

On Windows, you can invoke a Communicator-compliant server as follows:
C:\> set GC_GAR=%GC_HOME%\contrib\MITRE\bindings\java\lib\galaxy.jar
C:\> java -classpath .;<your_class_paths>;%GC_JAR% <class_name>


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;
          }
    };
}
 

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.
-assert Prevent the server from searching for a free port if the specified port is not available. The specified port is one of
a) port specified in a server location file (see -server_locations_file below), b) the port specified by the -port argument, c) a port passed into a MainServer  constructor, or d) the default port (1201). Note that the port specification in the server location file takes precedence over the -port argument, which takes precedence over programmatically-specified ports, which take precedence over the default port.
-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 multiple host/port pairs are separated by whitespace and 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>[:<tag>] 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).
-slf_name <tag> This is used to force the server to use the server location information (in the file specified with the -server_locations_file argument) that corresponds to the server name specified by <tag>.
-verbosity <verbosity level> The logging verbosity level. Valid values are the integers 0 (no logging) through 6 (very verbose logging on). The default level is 3.
-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 out and 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., not 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.

Using Broker Proxies

galaxy.server.DataOutBrokerProxy  and galaxy.server.DataInBrokerProxy  have been introduced to simplify the use of data brokers. These objects can be used in place of galaxy.server DataOutBroker and galaxy.server.DataInBroker respectively. Also, the galaxy.lang.BrokerProxy object has been introduced to encapsulate the information that an inbound broker needs in order to connect to an outbound broker. galaxy.lang.BrokerProxy  objects can be encoded in Galaxy Communicator messages and broker data streams, allowing this connection information to be passed between servers in a standard way.

Two types of galaxy.server.DataOutBrokerProxy  objects can be created. The first type is configured to broker an object of a particular type (e.g., an array of 32-bit integers). If the type is set to -1, the broker can handle any type of data, including heterogeneous objects (e.g., both 32-bit integer arrays and 64-bit floating point arrays). The write method is normally used to write the data to this first type of outbound broker. If the broker is brokering an ArrayObject or a GVector (i.e., expandable data objects), the addArrayToArray and addObjectToList methods can be used to write array or list data respectively. Also, if the broker is brokering arrays or lists or it has been configured to broker any type of data (i.e., type set to -1), then it is crucial that you invoke close when you are done writing data to the broker. This happens automatically in all other cases.

The second type is configured to broker one specified object. As in the case of the first type of broker proxy, you may use the addArrayToArray and addObjectToList methods to write data to brokers that are brokering  ArrayObject or  GVector  objects respectively. Also, if you are brokering an array or list, you must invoke close when you are done writing data to the broker. Note that if the object being brokered is a GVector, then the list elements are brokered as individual objects (i.e., the list is not brokered as one monolithic object).

galaxy.server.DataInBrokerProxy has two methods for accessing the brokered data. getObject  returns the complete brokered object (or null if it is not available yet). receivedObject  is called each time the associated in broker receives data (this method should be overriden by the developer to handle the data as desired). If the target outbound broker is configured to broker any type of data (i.e., was configured with object type -1), the inbound broker should use receivedObject  to access the incoming data, since, in this case, there is no way to know when all the data has been received until the broker proxy's disconnectReceived method is invoked (signifies that the associated outbound broker has sent all its data).

Timestamps

The timestamp of the token associated with a particular environment can be accessed by invoking galaxy.server.Environment.getTokenTimestamp  on the environment. You can also "inherit" the timestamp of the current token such that it is associated with all new messages sent from a particular environment. To do this, invoke galaxy.server.Environment.inheritTokenTimestamp  on the environment.

Service Provider Id

The provider id of the server that sent a message can be obtained by invoking galaxy.server.Environment.getOriginatingProvider on the environment that is associated with the message. In addition, a server can send messages to a particular server based on provider id by using one of galaxy.server.Environment.writeFrameToProvider,galaxy.server.Environment.dispatchFrameToProvider  or galaxy.server.Environment.dispatchFrameToProviderWithContinuation.


Change Log

May 2002

January 2002

June 2001

December 2000

August 2000

February 2000

January 1999


License / Documentation home / Help and feedback
Last modified August 8, 2002