Fall Semester 2007


Lecture Notes Seven: Transparent Networking in Java

Imagine two programs being run side by side.

Can methods from one call methods from the other?

The answer is: yes. Today we will learn how that's done and investigate some of the implications.

1. Side by Side: What is That ?

Imagine a program (a main method) being invoked at the prompt. It starts and creates an object, call it a.

Imagine a second program (a second, separate main) being invoked separately. It starts and creates another object, call it b.

Can either one of the two objects invoke any of the methods of the other? That's our problem for today, and the answer is: yes.

Details on how that can be achieved are presented below.

2. Of Clients and Servers.

We set up this situation as follows:

public class Server {
  public String reportDate() {
    try { 
      return " the time is " + new java.util.Date() + "\n   " + "    on " + java.net.InetAddress.getLocalHost() + "\n"; 
    } catch (Exception e) {
      return "Error... " + e; 
    } 
  } 
  public static void main(String[] args) {
    Server a = new Server(); 
    System.out.println(a.reportDate()); 
  } 
}
Let's just call this type of object(s), Server: it provides some kind of service.

What we truly want, in most operational terms, would be that an object of this kind:

public class Client {
  public static void main(String[] args) {
    Client b = new Client(); 
    // now what?...
  } 
}
... would be able to locate (from its main()) an existing Server and call its method reportDate().

Would this work? Is that what we have in mind:

public class Client {
  public static void main(String[] args) {
    Client b = new Client(); 
    // now what?... how about: 

    Server a = new Server(); 
    System.out.println(a.reportDate()); 

    // ... is that it?
  } 
}
This couldn't be it for two reasons:

Huh? Is that it, then?

public class Client {
  Server server; 
  Client(Server server) {
    this.server = server;
  } 
  void illustrate() {
    System.out.println(server.reportDate()); 
  } 
  public static void main(String[] args) {
    Server a = new Server(); 
    Client b = new Client(a); 
    b.illustrate(); 
  } 
}
This is much, much closer; but it still has one drawback; there is only one main here...

The requirement is that a and b be created in separate main(...) methods.

Moreover, each of the two main methods is started by an own invocation to javac at the command prompt.

3. What is a Server?

A server is very much like a business: it's something you can find listed in the Yellow Pages.

This is how we advertise:

import java.rmi.*; 

public interface ServerYellowPagesAd extends Remote {
  public String reportDate() throws RemoteException; 
}
It's a small price to pay. What else do we need to do?

4. The Mysterious, Magical NetworkPeer Class

A class is given that allows the server to be available remotely. Here's how we use it:

import java.rmi.*;

public class Server extends NetworkPeer implements ServerYellowPagesAd {
  public String reportDate() throws RemoteException {
    try { 
      return " the time is " + new java.util.Date() + "\n   " + "    on " + java.net.InetAddress.getLocalHost() + "\n"; 
    } catch (Exception e) {
      return "Error... " + e; 
    } 
  } 
  public static void main(String[] args) {
    Server a = new Server(); 
    String name = args[0], port = args[1]; 
    a.startAsNetworkServer(name, Integer.parseInt(port)); // client better know the host name (which is implicit here)
  } 
}
Before we even start thinking of this class (NetworkPeer), let's see how the clients needs to use it.

Recall, the client wants to access the server's reportDate method. Here's the client code:

import java.rmi.*; 

class Client extends NetworkPeer { 

    public static void main(String[] args) throws Exception {

        String serverHostName = args[0],   // three command line arguments 
               serverPortNumber = args[1], 
               serverName = args[2];

        Client client = new Client(); 

	client.startAsNetworkClientOf(serverHostName, 
                                      Integer.parseInt(serverPortNumber), 
                                      serverName); 

        client.illustrate(); 
    }

    public void startAsClientOf(java.rmi.Remote peer) throws java.rmi.RemoteException {
        ServerYellowPagesAd server = (ServerYellowPagesAd)peer;
	this.server = server; 
    } // this is one method that needs to be provided. It's not very complex, either.

    ServerYellowPagesAd server; // the client refers to the server by its business card 

    void illustrate() throws RemoteException { // because of reportDate() 
        System.out.println(server.reportDate()); 
    }



} 
Here we need to provide a clear definition of the NetworkPeer's class API.

Something like:

With this, we're done. The client is a remote peer too, but we don't know that (nor do we need it) at this point.

In other words NetworkPeer truly gives us peer to peer, bidirectional networking capability.

We'll take advantage of that soon. Meanwhile let's just explain how we test our application.

5. Necessities of Deployment

There needs to be a file that gives the server permission to answer the phone (take/process incoming calls):

grant { 
  permission java.net.SocketPermission "*", "connect,accept";
};
You can refine this, too. I call this file java.policy and make sure is in the same folder with everything else.

Next I compile everything:

javac *.java

Of course, it's good to always know what that means, we have these files: 

The policy file is also there, it just isn't a part of the compilation stage.

Next we invoke the RMI compiler on the classes that implement an interface that extends java.rmi.Remote:

Now we start the server:

java -Djava.security.policy=java.policy Server Dave 12009
The server is ready, and it reports that, so we can start the client.

java Client 127.0.0.1 12009 Dave
And that should do it.

6. In Class

After we verify this is working well on each machine:

We can then do the networked chat with shared whiteboard (just compile and run it).

7. Why Transparent Networking?

We can now take look at the NetworkPeer class, but maybe we shouldn't (just yet)?

Here's our original sketch of a code:

public class One {
  public static void main(String[] args) throws Exception {
    Server a = new Server(); 
    Client b = new Client(); 
    b.startAsClientOf(a); 
    b.illustrate(); 
  } 
}
Compile and run this program and it works like a charm.

So, all the networking is outside the dialog between the client and the server.

The method doesn't know (or care to know) if it's called over the network at all.

8. How Does NetworkPeer Work?

"Any sufficiently advanced technology is indistinguishable from magic." (Arthur C. Clarke)


Last updated: Nov 12, 2007. Copyright © Adrian German. All rights reserved.