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.
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:
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.
-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.
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;
}
}
}
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.
Methods on the interface of galaxy.server.Server:
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