HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Today, the Web has become an indispensable part of our lives. The Web is built based on client/server architecture. Traditionally, the client/server model refers to a two-tier relationship with a desktop client connected over the network to some form of server such as a database server. However, today's client/server applications are shifting from traditional two-tier to multi-tier architecture as shown in Figure 1.

Figure 1
Figure 1:

Multi-tier client/server architecture offers advantages such as extensibility, greater application scalability and increased reusability of components. In the multi-tier client/server model, a middleware is essential to act as a middle man in facilitating the interaction between the clients and the servers. In a general sense, middlewares cover all the distributed software needed to support interaction between clients and servers [1]. In this article, we look only at service-specific Web middleware which manages interaction among tiers in a Web-based application within a multi-tier architecture.

The Web is pervasive in many areas like business, medicine, education, research and development, etc. The Web browser-like interface is emerging as the de facto user interface. However, end-users and applications normally need to have some knowledge about server information (e.g., processing capabilities, availability of servers, types of services provided, server name, etc.) in order to access the available resources. In this evolving and explosive information era, there is certainly a need for some form of Gateway middleman to provide one-stop transparent access of resources. In this article, we will discuss in detail how a proposed Java-based middleware is useful in providing transparent execution of software. We will also discuss how Java sockets and object serialization could be used in implementing the Gateway-like middleware.

Overview of the Gateway Middleware
In organizations where Internet/Intranets and various heterogeneous servers are deployed, end users normally need to know certain resource information such as server name, processing capability, types of services supported, etc., in order to access the resources. There is a need to provide a one stop and transparent access of services so that the users need not worry about the servers' attributes, location or network details. This gives rise to the proposed Java-based Gateway middleware, which is able to receive the clients' requests and perform the tasks without the need to specify the execution details in their requests.

The middleware is designed with the following characteristics:

  • Distributed and dynamic - Provides distributed execution based on the client's requests, and it also supports dynamic configuration of the service execution network.
  • Autonomous - Active, self-contained, independent and long-life so that it can assist the clients in performing tasks without the knowledge of the underlying detail; e.g., server location, network information.
  • Open service provider - Provides transparent and consolidated services to the client, such as location transparency.
Figure 2 shows the bird's eye view of the Gateway middleware, which includes:
  • Clients: A Web browser is used as the interface whereby the client can submit its request to the Gateway middleware and wait for the outcome.
  • Service agents: This consists of a participating pool of service agents such as Unix hosts and Microsoft NT hosts, which register themselves through the Gateway middleware with the types of services they can support.
  • Gateway middleware: It is comprised of three main components:
    a. Receptionist - Handles the incoming requests from the clients; forwards them to the Dispatcher and returns the outgoing responses forwarded by the facilitator to the respective clients
    b. Dispatcher - Main task is to dispatch the requests to the service agents based on a suitable scheduling algorithm; it also maintains a queue of the requests
    c. Registry - Service agent must register with the Gateway middleware via the Registry in order to contribute to the service pool
    d. Facilitator - Handles the responses from the service agents and redirects them back to the Receptionist

Figure 2
Figure 2:

Anatomy of the Java-based Gateway Middleware

The Java-based middleware is developed using Java JDK 1.1.3 [2] and makes use of the Channel [3]. A Channel is a high-level Java-based abstraction of a bi-directional communication component that supports a generic message format. It is developed using Java sockets and object serialization [4], which is the process of reading or writing an object to a stream of bytes suitable for storage in a nonvolatile location; e.g., file. A Channel is a generic reusable software component which starts a thread to listen for incoming messages on a specified port. Any incoming message through the channel will be buffered into a generic message object. Figure 3 shows the interaction among various components of the Java-based Gateway middleware using Channel as the underlying communication component.

Figure 3
Figure 3:

Listing 1 shows the Gateway class specification. The Java-based Gateway middleware is to be started on the same host as the Web server as a standalone application, as shown below:

> java Gateway
Java-based Gateway Middleware set up done

Upon executing, it initiates the four main components of the middleware; i.e., Facilitator, Registry, Receptionist and Dispatcher.

In the following discussion, we will describe the interactions among various components in the Gateway middleware in detail according to the steps outlined in Figure 3.

1. Service agents make their service known to the others. First, each service agent is to be started as a standalone application:

> java Service <host-name>

whereby the <host-name> indicates the location of the Gateway middleware.

Each participating service agent will register first with the Registry of the middleware to make its service known so that it can be assigned respective tasks later. For the discussion in this article, homogeneous services are assumed on all service agents. In Figure 4, the service agent contacts Registry through a Channel with a well-known address (a well known port in this case). Then, the registry will assign an unused address (port number) to the requesting service agent which will use it to accept task requests from the Dispatcher in future.

Figure 4
Figure 4:

2. Clients submit their requests: The clients submit their requests to the Receptionist through the Web browser (Here, the Hotjava [5] browser is used for illustration). Here, we use a simple example which is to compute the distance between any n-dimensional vectors as an illustration for the task request. In fact, the service can be in any form of executable which is to be executed on the Service Agent. The client submits its request for computing Euclidean distance for the specified two-dimensional vectors (3, 5) and (9, 19). In this case, a C program (euclidean.c) is written to accept data (including the dimension of the vector; i.e., 2 and the two specified vectors) from the standard input and to display the computed result to the standard output (see Listing 2). Upon receiving the request from the client, the Java-based Gateway middleware will direct the request to the respective Service agent for execution. Upon successful execution, the result of the execution will then be displayed in the TextArea box.

Listing 3 shows the class specification of the ClientApplet respectively. Upon loading of the ClientApplet, it connects to the Gateway Middlware by using a Channel with a well-known port (see Figure 5) and the client is initialized. Then, a unique address (port number in this case) and client id are assigned dynamically by the middleware.

Figure 5
Figure 5:

The assigned port for the Channel will be used subsequently for receiving the execution outcome from the Gateway middleware. Once the ClientApplet is initialized, it submits the user-specified request commands to the Receptionist after marshalling it into specific message format (see the submitGateway() method in Listing 3). Then, it listens to the channel with the assigned port number for the outcome of its execution.
3. Receptionist is always listening to the Channel, ch_reception (see the run() method of Listing 4) for any incoming request. Upon receiving any request from the clients, the Receptionist, which serves as a single contact-point between the client and the middleware, forwards the request to the Dispatcher for any action to be taken.
4. The Dispatcher delegates the task to a suitable service agent (see the run() method of Listing 5) based on the devised algorithm (a simple First-Come-First-Serve scheduling algorithm is used in this article).
5. Upon receiving the assigned task from the Dispatcher, the respective Service agent spawns the execution (see Listing 6) by creating a SpawnProcess object:

... SpawnProcess sp = new SpawnProcess(gateway_hostname, clientID, request);
sp.start();
...

The SpawnProcess object starts a new process running externally to the interpreter (see Listing 7). The input data and output result for the execution are communicated to the runtime process through standard input and output streams. This is achieved by using the getOutputStream() and getInputStream() methods of the object process shown in Listing 8. In general, the execution process can be any executable programs.

6. Upon successful execution of the spawned process, the execution result is forwarded to the Facilitator of the Gateway middleware as shown in Listing 10.

Finally, the result is relayed to the client through the Receptionist using a channel with dynamically assigned port address.

The Client communicates with the Gateway middleware through a well-defined message format (see Table 1) whereby

Table 1
  • intention indicates the nature of the request (e.g. Register, Request etc).
  • communication information includes client-id, sender, etc.
  • message body contains the content depending on the intention; e.g., task to be executed, input data etc.
The following class specification for the message format is used homogeneously between any two entities such as client-to-Gateway middleware, components of the Gateway middleware, Service Agent-to-Gateway middleware.

/**
* Message Format class.
*/
class Message implements Serializable {
protected String intention;
protected String communication;
protected Object content;


public Message() { super(); }
}

Conclusion
In this article, a prototyped Java-based Gateway middleware is discussed in detail. It is still in its infancy stage, and there is still room for improvement (some aspects of which are currently under investigation):

  • Exception handling
  • Authentication and security; e.g., encryption
  • Efficient scheduling algorithms to ensure fair and efficient dispatching of tasks
  • Load monitoring and balancing
  • Fully distributed Gateway services building upon RMI (Remote Method Invocation) [6] and CORBA (Common Object Request Broker Architecture) [7].
Currently, the Gateway middleware is being developed using Visibroker [8] (an implementation of the CORBA framework) by Visigenic and more extensive testing is also being carried out.

References

  1. Robert Orfali, Dan Harkey, Jeri Edwards (1994). Essential Client/Server Survival Guide. pp. 18-19.
  2. Javasoft. Java JDK 1.1: http://www.javasoft.com/products/jdk/1.1/docs/api/package.html
  3. Siet-Leng Lai, Joo-Hwee Lim, (1996). "Channel: A Communication Component", Java Developer's Journal, Volume 1, Issue 3, pp. 20- 27.
  4. JavaSoft. Javaª Object Serialization Specification: http://www.javasoft.com/products/rmi/doc/serial-spec/serialTOC.doc.html
  5. JavaSoft. HotJava: http://www.javasoft.com/products/hotjava
  6. Javasoft, Remote Method Invocation:
    http://www.javasoft.com/products/jdk/rmi/index.html
  7. CORBA (Common Object Request Broker Architecture): http://www.OMG.org
  8. Visigenic, Visibroker: http://www.visigenic.com
About the Authors
Siet-Leng Lai has developed a concurrent object-based language on parallel machine as well as clustered workstation environment and a multi-tasking operating system on DOS. She is now conducting research into internet/intranet middlewares using Java. She can be reached at [email protected]

Joo-Hwee Lim has proposed novel neural networks techniques for timetabling and has developed an execution monitoring engine for a complex planner. He is now a senior software engineer leading an Agent Engineering Team researching agent-based software engineering and multi-agent systems using Java. The project is funded by Japan's Real World Computing Partnership. He can be reached at [email protected]

	

Listing 1.
  
import java.io.*;  
import java.net.*;  

public class Gateway  
{  
  public static void main(String[] args)  
    {  
      Facilitator f = new Facilitator();  
      f.start();  
      Dispatcher d = new Dispatcher();  
      d.start();  
      Registry reg = new Registry();  
      reg.start();  
      Receptionist rec = new Receptionist();  
      rec.start();  

      System.out.println("Java-based Gateway Middleware Setup Done");  
    }  
}  

Listing 2.
  
  *  euclidean.c  - computation of Euclidean Distance between two N-dimensional 
vectors  
  *      (x1, x2, .... xn), (y1, y2, .... yn)  
  *      accepts  the dimension  and the two vectors from the standard input  
  *      computes  the distance  as   sqrt(  sqr( x1-y1)+ sqr(x2-y2) + ... )  
  *      displays the result on the standard output  
  */  

#include <stdio.h>  
#include <math.h>  

#define MAX  20  

main()   
{  
  int x[MAX];  
  int y[MAX];  
  int i, dimension, total=0;  
  double distance;  
   

  printf("Computation of Euclidean Distance between two n-dimensional 
vectors\n");  
  scanf("%d", &dimension);  

  printf(" no. of dimension = %d\n", dimension);  

  for (i=0; i<dimension; i++)  
      scanf("%d", &x[i]);  

  for (i=0; i<dimension; i++)  
      scanf("%d", &y[i]);  

  printf("  vector 1 = (%d", x[0]);  
  for (i=1; i<dimension; i++)   
       printf(", %d", x[i]);  
  printf(")\n  vector 2 = (%d", y[0]);  
  for (i=1; i<dimension; i++)  
       printf(", %d", y[i]);  
   printf(")\n");  
    
  for (i=0; i<dimension; i++) {  
      total = total + ((x[i] - y[i]) * (x[i] - y[i]));  
  }  

  distance = sqrt(total);  

  printf(" Computed distance = %lf \n", distance);  

  return(0);  
}  

Listing 3.
 
import java.applet.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.io.*; 
import java.net.*; 
import java.util.*; 

public class ClientApplet extends Applet implements ActionListener 
{ 
  private       int clientID; 
  private       Channel ch_client, ch_assigned_client; 
  private       String gateway_hostname; 
  private int port; 
  private       boolean quit; 
  private       String input; 
  private       TextField cmd; 
  private       TextArea result; 
  private       Button submitButton, quitButton; 
  

  public void init() { 

    int clientID; 
    String gateway_hostname; 
    Message msg; 

    Panel p1, p2, p3, p4; 
    Label header, instruction, statusLabel; 
    Font fn; 

    quit = false; 
    header = new Label("Client for the Java-based Gateway Middleware"); 
    instruction = new Label("Please enter your command :-"); 
    statusLabel = new Label("Result status"); 

    cmd = new TextField(40); 
    result = new TextArea(10, 30); 
    result.setEditable(false); 

    submitButton = new Button("Submit"); 
    quitButton = new Button("Quit"); 

    submitButton.addActionListener(this); 
    quitButton.addActionListener(this); 

    fn = new Font("TimesRoman", Font.BOLD, 24); 
    header.setFont(fn); 

    p1 = new Panel(); 
    p1.setLayout(new BorderLayout()); 
    p1.add("North", header); 
    p1.add("Center", instruction); 
    p1.add("South", cmd); 

    p4 = new Panel(); 
    p4.setLayout(new BorderLayout()); 
    p4.add("West", statusLabel); 
    p4.add("Center", result); 
  

    p2 = new Panel(); 
    p2.setLayout(new BorderLayout()); 
    p2.add("North", p1); 
    p2.add("South", p4); 

    p3 = new Panel(); 
    p3.add("West", submitButton); 
    p3.add("East", quitButton); 

    setLayout(new BorderLayout()); 
    add("North", p2); 
    add("South", p3); 

  } 
  

  public void start() { 
      Message msg; 
      int index; 

      gateway_hostname = this.getParameter("Hostname"); 
  
      // set up a temp channel to communicate with the Agate 
      ch_client = new Channel(Constant.CLIENT_PORT); 
       
      try 
        { 
          String reception; 
          reception = 
                 InetAddress.getLocalHost().getHostName(); 
   msg = new Message(); 
          msg.intention = "New Client"; 
    msg.content = reception; 
          ch_client.send(msg, gateway_hostname, Constant.RECEPTION_PORT); 
        } 
      catch (UnknownHostException e3) 
        { 
         //System.out.println(e3); 
        } 

      msg = ch_client.receive(); 
      String line = (String) msg.content; 

      System.out.println("content = "+ line); 
      clientID = Integer.parseInt((String) msg.communication); 
      port = Integer.parseInt(line); 

      output_result("Client : assigned port number is " + port+ "id = 
"+clientID); 
       
      // closing the ch_client channel 
      msg = new Message(); 
      msg.intention = "stop"; 
      ch_client.send(msg, Constant.CLIENT_PORT); 
             
      // setting up a new channel with the assigned port number 
      if (port != -1 || port != -2) 
        ch_assigned_client = new Channel(port); 
    } 
  
  

  boolean ConnectionAccepted() 
    { 
      if (port == -1) 
        { 
          //System.out.println("Client connection to Gateway rejected!"); 
          //System.out.println("Reason : Too many client connection"); 
          return false; 
        } 
      else if (port == -2) 
        { 
          //System.out.println("Client connection to Gateway rejected!"); 
          //System.out.println("Reason : Existing client connection using" + 
          //                   " current client ID detected");    
          return false; 
        } 

      else 
        { 
          //System.out.println("Client connection to Gateway accepted!"); 
          return true; 
        } 
    } 

 public void output_result(String s) 
 { 
   result.setText(s); 
   validate(); 
 } 

  public void actionPerformed(ActionEvent event) 
  { 

   String command = event.getActionCommand(); 

   if (command.equals("Submit")) { 

     input = cmd.getText(); 
     output_result("output : "+input); 
     System.out.println("input = "+input); 
     submitGateway(input); 
   } else if (command.equals("Quit")) { 
     quit = true; 
   } 

 } 
            
  public void submitGateway(String userInput) 
    { 
      int commandID, index; 
      StringTokenizer userInputTok, resultStrTok; 
      String request, argument, result, output; 
      Message msg; 
  
  

              userInputTok = new StringTokenizer(userInput, " "); 
        
              if (userInputTok.countTokens() > 0) { 

     request = userInputTok.nextToken(); 
     index = userInput.indexOf(' '); 
     userInput = userInput.substring(index + 1); 
     
              if (request.equalsIgnoreCase("exec") == true) { 

              if (userInputTok.countTokens() > 0) { 

     msg = new Message(); 
     msg.intention = "Request"; 
     msg.communication = Integer.toString(clientID); 
     msg.content = userInput; 
ch_assigned_client.send( msg,  gateway_hostname, Constant.RECEPTION_PORT); 

     System.out.println("just send"); 
     msg = ch_assigned_client.receive(); 

     result = (String) msg.content; 
     System.out.println("received "+result); 

     index = result.indexOf(' '); 
commandID = Integer.parseInt(result.substring(0, index)); 
     result = result.substring(index+1); 

     switch (commandID) { 
    case Constant.JOB_EXEC_OK: 
	{ 
    output_result(result); 
   break; 
    } 

   case Constant.JOB_AGENT_UNAVAIL:   
   { 
//System.out.println("Error : No Service agent available to " + 
// "handle the request job!"); 
   break; 
  } 
        
  case Constant.JOB_EXEC_UNSUPPORTED: 
  { 
//System.out.println("Error : Requested job is not supported " + 
//"by Gateway!"); 
      break; 
  } 

   }  
//  switch statement 
     }  
	 else {      
 //   if UserInputTok.countTokens() > 0; 
 //System.out.println("exec what?"); 

        }  
// if  request = exec   

        else if (request.equalsIgnoreCase("quit") == true) 
        { 
        String reception; 
reception = Integer.toString(Constant.RELINQUISH_CLIENT) 
+ " " + Integer.toString(clientID); 
         
//System.out.println(reception); 
   msg = new Message(); 
   msg.intention = "Done"; 
   msg.content = reception; 
ch_assigned_client.send( msg,gateway_hostname,Constant.RECEPTION_PORT); 
         
// System.exit(1); 

        } 
     
        else 
      System.out.println("bad command"); 
     } 

         }
// submitGateway() method 

} 

Listing 4.
 
import java.net.*; 
import java.util.*; 

public class Receptionist extends Thread  
{  
  private  Channel ch_reception; 
  private  PortManager client_port; 
  private  Hashtable client_table; 
  private  int assigned_id; 

  public Receptionist() 
    { 
      ch_reception = new Channel(Constant.RECEPTION_PORT); 
      client_port = new PortManager(Constant.CLIENT_START_PORT, 
                                    Constant.MAX_CLIENT_SIZE); 
      client_table = new Hashtable(); 
      assigned_id = 0; 
    }  

  public void run() 
    { 
      Message msg; 
      String command; 
  

      while (true) { 

          msg = ch_reception.receive(); 
          command = msg.intention; 
          System.out.println("Reception incoming_str : " + msg.content); 

          if (command.compareTo("New Client") == 0) { 
              new_client(msg); 
          } else if (command.compareTo("Relinquish Client") == 0) { 
              relinquish_client(msg); 
          } else if (command.compareTo("Request") == 0 ) { 
              job_request(msg); 
          } else if (command.compareTo("Result") == 0) { 
              job_result(msg); 
          } 

      } // while loop 

    } // run() method 
  

  void new_client(Message i_msg) { 
     int assigned_port, index, clientID; 
     String hostname, incoming_str; 
     Message msg; 
     CData clientdata; 
      

     incoming_str = (String) i_msg.content; 

     clientID = ++assigned_id; 
     index = incoming_str.indexOf(' '); 
     hostname = incoming_str.substring(index+1); 

     if (client_port.available()==true){ 

        if (client_table.containsKey(new Integer(clientID))==false) { 

           System.out.println("clientid="+clientID); 
           assigned_port = client_port.usePort(); 

           clientdata = new CData(hostname, assigned_port); 
           client_table.put(new Integer(clientID), clientdata); 
                 
           msg = new Message(); 
           msg.intention = "New Client"; 
           msg.communication = Integer.toString(clientID); 
           msg.content = Integer.toString(assigned_port); 

           ch_reception.send( msg, 
                  hostname, Constant.CLIENT_PORT);                

           System.out.println("Reception : Client " + clientID + 
                  " is assigned the use of port number "+ 
                  assigned_port+" client id = "+assigned_id); 

        } else { 
           msg = new Message(); 
           msg.intention = "Error"; 
           msg.content = "-2";  
           ch_reception.send( msg, 
                       hostname, Constant.CLIENT_PORT); 
           System.out.println("Registry : Client " + clientID + 
                       " request for Connection has been denied "+ 
                       "due to lack of available 
ports");                                            
        }                       
     } else {  // port available ?? 

        msg = new Message(); 
        msg.intention = "Error"; 
        msg.content = "-1";  
        ch_reception.send( msg, hostname, 
                     Constant.CLIENT_PORT); 
        System.out.println("Reception: Client " + clientID + 
                     " request for Connection has been denied" + 
                     " due to existence of another client connection" + 
                     " with the same Client ID"); 
     }       
  } // new_client() method 
  

  void relinquish_client(Message i_msg) { 

     int clientID; 
     CData clientdata; 

     clientID = Integer.parseInt((String) i_msg.communication); 
   
     clientdata = (CData) client_table.remove(new Integer(clientID)); 
     client_port.releasePort(clientdata.getPort()); 

     System.out.println("Registry : Client " + clientID + 
                " at port number " + clientdata.getPort() + 
                " has closed connection with the Agate"); 
  } 

  void job_request(Message i_msg) { 

     int clientID; 
     Message msg; 
     String incoming_str; 
  

     clientID = Integer.parseInt((String) i_msg.communication); 
     incoming_str = (String) i_msg.content; 
  

     System.out.println("Reception: " + incoming_str + 
                  " has been dispatched to the Dispatcher"); 

     msg = new Message(); 
     msg.intention = "Request"; 
     msg.communication = Integer.toString(clientID); 
     msg.content = incoming_str;  
     ch_reception.send(msg, Constant.DISPATCH_PORT); 

  }  // job_request() method 

  void job_result (Message i_msg) { 

     int clientID; 
     Message msg; 
     CData clientdata; 
     String incoming_str; 

     clientID = Integer.parseInt((String) i_msg.communication); 
     incoming_str = (String) i_msg.content; 
     
     clientdata = (CData) client_table.get(new Integer(clientID)); 
     System.out.println("Job result: "+"id="+clientID+ 
             "the rest="+incoming_str); 
     System.out.println("Job result: port sent to "+clientdata.getPort());   

     msg = new Message(); 
     msg.intention = "Done"; 
     msg.content = incoming_str;  
     ch_reception.send(msg, clientdata.getHostName(), 
               clientdata.getPort()); 
     
     System.out.println("Reception : Sending result back to" + 
               " client at port number " + clientdata.getPort() + 
                ", hostname "+  clientdata.getHostName()); 

  } // job_result() method 
  

} 

Listing 5.
 
import java.io.*; 
import java.net.*; 
import java.util.*; 

public class Dispatcher extends Thread 
{     
  private     Channel ch_dispatch; 
  private     int service_port[] = new int[Constant.MAX_PORT]; 
  private     String service_host[] = new String[Constant.MAX_PORT]; 
  private     int now, no_service; 
   
  public Dispatcher () 
    { 
      ch_dispatch = new Channel(Constant.DISPATCH_PORT); 
      now = -1; 
      no_service = -1; 
    }  
   
  public void run() 
    {         
      String line, command; 
      String incoming_str; 
      int index; 
      String in_host, in_port; 
      Message msg; 

       
      while (true) { 

          msg = ch_dispatch.receive(); 
          incoming_str = (String)msg.content; 
   System.out.println("Dispatch incoming str : " + incoming_str); 

          command = msg.intention; 

          if (command.compareTo("Request") == 0) { 
              dispatch_job(msg); 
          } else if (command.compareTo("New Service") == 0) { 
              new_service(msg); 
          } else if (command.compareTo("Relinquish Service")==0) {       
       // yet to be implemented 
          } 

      } // while loop 

  } // run() method 
  

  void dispatch_job(Message i_msg) { 

      Message msg; 
      int clientID; 
      String incoming_str; 
  

      clientID = Integer.parseInt((String) i_msg.communication); 
      incoming_str = (String) i_msg.content; 

      System.out.println(incoming_str); 
  

      if (now > -1) { 
     
          msg = new Message(); 
          msg.intention = "Dispatch"; 
          msg.communication = Integer.toString(clientID); 
          msg.content = incoming_str; 
          ch_dispatch.send(msg,service_host[now] ,service_port[now]); 
          System.out.println("Dispatch : Job sent to service agent at port 
number " + service_port[now] + ", host " + service_host[now]); 
         
          now = (now+1) % (no_service+1); 
      } else { 

    String reception; 

	reception = Integer.toString(Constant.JOB_RESULT) + " " + clientID + " " + 
                    Integer.toString(Constant.JOB_AGENT_UNAVAIL); 

// "Error : No Service agent available to handle the " + 
          //                    "request job!|"; 

          msg = new Message(); 
          msg.intention = "Error";  
          msg.content = reception; 
          ch_dispatch.send(msg, Constant.RECEPTION_PORT);                   
       } 

  }  // dispatch_job() method 
  
  

  void new_service(Message i_msg) { 

     String in_host, in_port, incoming_str; 
     int index; 
  

     incoming_str = (String) i_msg.content; 

     index = incoming_str.indexOf(' '); 
     in_host = new String(incoming_str.substring(0, index)); 
     in_port  = new String(incoming_str.substring(index + 1)); 
        
     if (no_service == -1) 
        now++; 
     no_service++; 
        
     System.out.println("Dispatch : New service agent at port number " +  
                     in_port + ", hostname " + in_host); 
     service_port[no_service] = Integer.parseInt(in_port); 
     service_host[no_service] = in_host; 

  } // new_service() method 

} 

Listing 6.
  
import java.io.*;  
import java.net.*;  

public class Service extends Thread  
{  
  private Channel ch_service, ch_assigned_service;  
  protected  String   prog_name;  
  private       String   gateway_hostname;  
  private       int port;  
    
  public Service(String gateway_hostname)  
    {  
      this.gateway_hostname = gateway_hostname;  

      // set up a temp channel to communicate with the Gateway  
      ch_service = new Channel(Constant.SERVICE_PORT);  
        
      try          
        {  
          String service =  
            InetAddress.getLocalHost().getHostName();  
          Message msg = new Message();  
          msg.intention = "New Service";  
          msg.content = service;  
          ch_service.send(msg, gateway_hostname, Constant.REGISTRY_PORT);  
        }  
      catch (UnknownHostException e)  
        {  
   System.out.println(e);  
        }  

      Message msg = ch_service.receive();  
      String line = (String) msg.content;  
        
      port = Integer.parseInt(line);  
        
      System.out.println("Service : assigned port number is " + port);  
        
      // close the ch_service channel using the default port  
      msg.intention = "stop";  
        
      ch_service.send(msg, Constant.SERVICE_PORT);  
      // System.out.println("Service : Channel ch_service closed");  
        
      // setting up a new channel with the assigned port number  
      if (port != -1)  
        ch_assigned_service = new Channel(port);  
    }  
    
  public boolean ConnectionAccepted()  
    {  
      if (port == -1)  
        return false;  
      else  
        return true;  
    }  
    
  public void run()  
    {      
      String  request, prog_name, result;  
      int clientID, index;  
        
      while (true)  
        {  
          Message msg = ch_assigned_service.receive();  
          clientID = Integer.parseInt((String) msg.communication);  
          request = (String) msg.content;  
          System.out.println("Service incoming_str : " + request);  
     
          SpawnProcess sp = new SpawnProcess(gateway_hostname, clientID, 
request);  
          sp.start();  
          System.out.println("Service : Process " + request + " spawned!");  
 }  
    }  
    
  public static void main(String args[])  
    {  
      Service service = new Service(args[0]);  
        
      if (service.ConnectionAccepted()==true)  
        service.start();  
        
      else  
        {  
          System.out.println("Gateway Service Ports are all in use");  
          System.out.println("Please attempt a connection at a later time");  
          System.exit(1);  
        }  
    }  
}  

Listing 7.
  
import java.io.*;  
import java.net.*;  

class SpawnProcess extends Thread  
{  
  private int clientID;  
  private String prog_name;  
  private String agate_hostname;  
  private String parameters;  

  public SpawnProcess(String HostName, int ClientID, String Request)  
    {  
      int index;  

      agate_hostname = HostName;  
      clientID = ClientID;    
      index = Request.indexOf(' ');  
      if (index > 0) {  
         prog_name = Request.substring(0, index);  
         parameters = Request.substring(index + 1);  
      } else {  
         prog_name = Request;  
         parameters = null;  
      }  
      System.out.println("prog name= "+prog_name+" param="+parameters);  
    }  
    
  public void run()  
    {  
      Channel ch_ps;  
      InetAddress local;  
      String hostname;  
        
      try  
        {  
          Process p = Runtime.getRuntime().exec(prog_name);  
          System.out.println("SpawnProcess : executing with" + 
prog_name+parameters);  
     
          if (parameters != null) {  
             PrintWriter pout = new PrintWriter(p.getOutputStream());  
             pout.println(parameters);  
             pout.flush();  
             pout.close();  
          }  

          DataInputStream din = new DataInputStream(new 
BufferedInputStream(p.getInputStream()));  
     
          String result, part;  
          result = new String();  
     
          while ((part=din.readLine()) != null)  
     {  
              result = result + part + "\n";  
     }  
     
          if (result.equalsIgnoreCase("")==true)  
            result = result + part;  
     
          ch_ps = new Channel(Constant.PS_PORT);            
     
          Message msg = new Message();  
          msg.intention =  "Result";  
          msg.content = Integer.toString(Constant.JOB_EXEC_OK) + " " + result;  
          msg.communication = Integer.toString(clientID);  
          ch_ps.send(msg, Constant.FACILITATION_PORT);  
          System.out.println("Spawned Process : " + result + " routed to 
facilitator at " + agate_hostname);  
          msg.intention = "stop";  
          ch_ps.send(msg, Constant.PS_PORT);  

        } catch (IOException e)  
          { System.out.println("io : " + e); }  
    }  
}  

Listing 8.
  
 …  
 try  
    {  
     Process p = Runtime.getRuntime().exec(prog_name);  
     System.out.println("SpawnProcess : executing with" + 
prog_name+parameters);  
    
     if (parameters != null) {  
       PrintWriter pout = new PrintWriter(p.getOutputStream());  
       pout.println(parameters);  
       pout.flush();  
       pout.close();  
     }  

  DataInputStream din = new DataInputStream(new 
BufferedInputStream(p.getInputStream()));  
 …  

Listing 9.
  
    Channel ch_ps;  

     ch_ps = new Channel(Constant.PS_PORT);       
     …  
    
     Message msg = new Message();  
     msg.intention = "Result";  
     msg.communication = Integer.toString(clientID);  
     msg.content = result;  
     ch_ps.send(msg, Constant.FACILITATION_PORT);  



 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.