SDSU CS 696 Emerging Technologies: Java Distributed Computing
Spring Semester, 1999
Dynamically Downloading Classes
Previous    Lecture Notes Index    Next    
© 1999, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 16-Mar-99

Contents of Doc 16, Dynamically Downloading Classes


References


Java Remote Method Invocation Specification, pp. 16-17, 34-35
Local HTML Copy: http://www-rohan.sdsu.edu/java/jdk1.2/docs/guide/rmi/spec/rmiTOC.doc.html
Sun HTML Site: http://java.sun.com/products/jdk/1.2/docs/guide/rmi/spec/rmiTOC.doc.html

RMI mailing list ( mailto:RMI-USERS@JAVA.SUN.COM)

Archives of mailto:RMI-USERS@JAVA.SUN.COM, http://archives.java.sun.com/archives/rmi-users.html

Private communications

Doc 16, Dynamically Downloading Classes Slide # 2

RMI, http and Downloading Class files


Classes can be automatically downloaded at runtime to an RMI client. Following conditions must be met for a class to be dynamically downloaded:


For example the stub class is not explicitly referenced in the client, but is used in the client. If the class is explicitly referenced, then the classloader throws an exception if the class is can not be found in the classpath of the client. There are a number of ways a client can use a class, call it classA, but not directly reference the class. First, the classA can be a field in another class that the client directly references. Second classA can implement an interface, abstract class or normal class and the client can directly reference the interface, abstract class or parent class of classA. Third, the client can receive a reference to a classA object, but place it in a variable of type Object. The client can use reflection to invoke methods on the classA object.

Currently the URL must be either for http protocol or file (for access on the local machine.) The class can be available on a remote machine via http. However, the client needs the proper permission to contact that machine. In Java 2 (JDK 1.2) this means even client applications need permissions in a policy file set to allow opening a connection.

The java.rmi.server.codebase property must be set to the URL at which the class is available. This property can be set either on the client side or the server side. The details are different between setting it on the client side and setting it on the server side.

Doc 16, Dynamically Downloading Classes Slide # 3

Client Side java.rmi.server.codebase


There are three things you must do in setting the codebase property on the client side.

Normally, if client finds any of the classes it needs in its classpath, it will only search for the classes in its classpath. This setting tells the client to search for classes in the URL given by the codebase property.
Without the RMISecurityManager, the client will not download classes.

The following is an example of setting the codebase on the client side.
java -Djava.rmi.server.useCodebaseOnly=true -Djava.rmi.server.codebase=http://eli.sdsu.edu:8888/ whitney.rmi.examples.codebase.RogerClient
The URL must end in a "/" and must be to the directory containing the full package directory structure of the classes that the client will down load. See the examples later for more details.

Doc 16, Dynamically Downloading Classes Slide # 4

Server Side java.rmi.server.codebase


Setting the java.rmi.server.codebase property on the server side is more involved. If you set the property on the server side correctly, then the property need not be set on the client side.

This applies to the stub class(es) and classes that the stub class depends on. If the rmiregistry can not find the stub class & related classes in its classpath, it will download them via http and include the url in the stub. The client will use this url to download the class.
When the server is registered with the rmiregistry, the url indicated by the codebase property is passed to the rmiregistry.


Doc 16, Dynamically Downloading Classes Slide # 5

http Server for Examples


Any Web server can be used to download class files to a client. JavaSoft provides a small http server (ClassFileServer) written in java for downloading classes. The source code can be found at: " ftp://ftp.javasoft.com/pub/jdk1.1/rmi/class-server.zip". The examples will use ClassFileServer as the web server. Jini comes with a web server written in Java. Jrun ( http://www.jrun.com/) is another java web server you can download.

Doc 16, Dynamically Downloading Classes Slide # 6

Example – Download Stub


The first example involves three classes and one interface:

Roger
A serializable class
An instance is passed from GetRogerServer to GetRogerClient
GetRoger
Remote interface that the GetRogerServer implements
GetRogerClient - The client
GetRogerServer - The server


GetRogerClient references Roger & GetRoger explicitly, so we can only dynamically download the class GetRogerServer_Stub to the client.

The instructions that follow are for Java 2 (jdk1.2) on a Unix machine. Instructions for Windows/NT are not given.

Doc 16, Dynamically Downloading Classes Slide # 7
Starting the Web Server

The command line arguments for ClassFileServer are:

java ClassFileServer <port> <classpath>
where
port is the port number the ClassFileServer uses
classpath is the root of the classpath for the classes to be dynamically downloaded

Since the classes in the example are in the package whitney.rmi.examples.codebase and the root of the package is in the directory /export/home/whitney/java the following command line was used to test the example:

java ClassFileServer  8888  /export/home/whitney/java
Note: The files ClassFileServer and from Sun are in the package examples.classServer. To simplify the presentation, I removed them from the package. Otherwise the command line would be: java examples.classServer.ClassFileServer 8888 /export/home/whitney/java

The ClassFileServer, the rmiregistry, and the server object in this example will all run on the machine eli.sdsu.edu

Doc 16, Dynamically Downloading Classes Slide # 8

Client Side codebase

Server Side
The source files on the server side are:
Roger.java
GetRoger.java
GetRogerServer.java

Note: GetRogerServer uses the class sdsu.io.ProgramProperties. This class is on my classpath on both the server and client side. This class can be downloaded at: http://www.eli.sdsu.edu/java-SDSU/index.html

All classes on the server side are in the package:
whitney.rmi.examples.codebase.

I placed all the source files in the directory:
/export/home/whitney/java/whitney/rmi/examples/codebase
on eli.sdsu.edu. Since the ClassFileServer points to the directory /export/home/whitney/java, it will read all .class files generated on the server side.

Compile the server classes with
   javac *.java
Generate the stub class via rmic
   rmic whitney.rmi.examples.codebase.GetRogerServer

Start rmiregistry with
   rmiregistry &

Create and register the server object via the command:
java whitney.rmi.examples.codebase.GetRogerServer -label=ClientTest

Doc 16, Dynamically Downloading Classes Slide # 9
Client
The source files on the client side are:
Roger.java
GetRoger.java
GetRogerClient.java

Note: GetRogerServer uses the class sdsu.io.ProgramProperties. This class is on my classpath on both the server and client side. This class can be downloaded at: http://www.eli.sdsu.edu/java-SDSU/index.html

Compile the server classes with
   javac *.java

Run the client with the command:

java -Djava.rmi.server.useCodebaseOnly=true 
      -Djava.rmi.server.codebase=http://eli.sdsu.edu:8888/ 
      whitney.rmi.examples.codebase.RogerClient 
         -host=eli.sdsu.edu -label=ClientTest
The stub class for the server will be downloaded to the client via http when the client needs the stub.

Doc 16, Dynamically Downloading Classes Slide # 10

Server Side codebase

Server Side
The source files on the server side are:
Roger.java
GetRoger.java
GetRogerServer.java

Note: GetRogerServer uses the class sdsu.io.ProgramProperties. This class is on my classpath on both the server and client side. This class can be downloaded at: http://www.eli.sdsu.edu/java-SDSU/index.html

All classes on the server side are in the package:
whitney.rmi.examples.codebase.

I placed all the source files in the directory:
/export/home/whitney/java/whitney/rmi/examples/codebase
on eli.sdsu.edu. Since the ClassFileServer points to the directory /export/home/whitney/java, it will read all .class files generated on the server side.

Compile the server classes with
   javac *.java
Generate the stub class via rmic
   rmic whitney.rmi.examples.codebase.GetRogerServer

Start rmiregistry making sure that classes generated above are not in its classpath

   rmiregistry &

Create and register the server object via the command:
java -Djava.rmi.server.codebase=http://eli.sdsu.edu:8888/  
   whitney.rmi.examples.codebase.GetRogerServer -label=ServerTest &

Doc 16, Dynamically Downloading Classes Slide # 11
Client
The source files on the client side are:
Roger.java
GetRoger.java
GetRogerClient.java

Note: GetRogerServer uses the class sdsu.io.ProgramProperties. This class is on my classpath on both the server and client side. This class can be downloaded at: http://www.eli.sdsu.edu/java-SDSU/index.html

Compile the server classes with
   javac *.java

Run the client with the command:

java whitney.rmi.examples.codebase.RogerClient 
         -host=eli.sdsu.edu -label=ClientTest
The stub class for the server will be downloaded to the client via http when the client needs the stub.

Doc 16, Dynamically Downloading Classes Slide # 12

Classes

Roger

package whitney.rmi.examples.codebase;
import java.io.Serializable;
public class Roger implements Serializable {
   private String data;
   
   public Roger( String message) { data = message; } 
   
   public String toString() { return "Roger( " + data + ")"; }
}

GetRoger

package whitney.rmi.examples.codebase;
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface GetRoger extends Remote {
   public abstract Roger get() throws RemoteException;
}

Doc 16, Dynamically Downloading Classes Slide # 13

RogerClient

package whitney.rmi.examples.codebase;
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.*;
import java.rmi.registry.Registry;
import sdsu.util.ProgramProperties;
public class RogerClient  {
   public static void main(String args[]) throws Exception  {
         System.setSecurityManager(new RMISecurityManager());
         String server = getHelloHostAddress( args);
         GetRoger remote = (GetRoger) Naming.lookup( server );
         Roger message = remote.get();
         System.out.println( message.toString() );
   }
   private static String getHelloHostAddress( String args[] ) 
      throws IOException {
      ProgramProperties flags = 
         new ProgramProperties( args );
      String host = flags.getString( "host" );
      int defaultPort = Registry.REGISTRY_PORT;
      int port = flags.getInt( "port", defaultPort );
      
      String serverLabel = flags.getString( "label" );
      return "rmi://" + host + ":" + port + "/" + serverLabel;
   }
}

Doc 16, Dynamically Downloading Classes Slide # 14

GetRogerServer

package whitney.rmi.examples.codebase;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.registry.Registry;      // for port number
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
import java.text.DateFormat;
import java.util.Date;
import sdsu.util.ProgramProperties;
public class GetRogerServer 
   extends UnicastRemoteObject  implements GetRoger {
   public GetRogerServer() throws RemoteException {};
   
   public Roger get() { return new Roger( date() ); }
   
   private String date() {
      Date today = new Date();
      return DateFormat.getDateTimeInstance().format( today);
   }
   private static String getRegistration( String args[] ) 
      throws IOException {
      ProgramProperties flags = 
         new ProgramProperties( args );
      int defaultPort = Registry.REGISTRY_PORT;
      int port = flags.getInt( "port", defaultPort );
      String serverLabel = flags.getString( "label" );
      return "rmi://" + ":" + port + "/" + serverLabel ;
   }
 

Doc 16, Dynamically Downloading Classes Slide # 15
   /**
    * The commandline is of the form:
    *  java GetRogerServer  -label=objectlabel  -port=rmiregistryPort
    *   rmiregistryPort is the port used by the rmiregistry and is optional
    *      if the registry uses the standard port
    *   objectlabel is the label that the server object is stored under in the 
    *      rmiregistry
    * (You need to add the package name to the class above)
    */
   public static void main(String args[]) throws Exception {
      System.setSecurityManager(new RMISecurityManager());
      String serverAddress = getRegistration( args );
      GetRogerServer serverObject = new GetRogerServer();
      
      Naming.rebind( serverAddress, serverObject);
      System.out.println("Server bound in registry");
      }
   }

Copyright ©, All rights reserved.
1999 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 16-Mar-99    Next