CS262 Introduction to Distributed Computing Assignment 2

For this assignment, you are to build and deploy a simple RMI service. The service itself is defined by the following interface:

/*
 * Hello.java
 *
 * 
 */

package edu.harvard.cs262;


import java.rmi.RemoteException;

/**
 * Interface for the service that is the core of
 * the second assignment. The service that implements
 * this interface will need to return an object that
 * implements the GradeInfo interface. The test program
 * will find the RMI service that implements this
 * interface, will get the object supplied by that service
 * that implements the GradeInfo interface, and will
 * then call the object obtained to get the number of
 * students who worked in the group, the names of those
 * students, and the grades that each student should be
 * given on the assignment.
 * 
 */

public interface Hello extends Remote{
    /**
     * obtains a local copy of in GradeInfo object. This object
     * is only defined by the interface; the actual implementation 
     * object will come from the service that is called
     */
    public GradeInfo getInfo() throws RemoteException;
    
    /**
     * Shut down the remote server. The service should first 
     * clean up its registration with the RMI registry, and then
     * gracefully exit. If this were a real-world application, there
     * would be some security around this method to insure that it
     * couldn't be called by random code.
     */
    boolean shutDown() throws RemoteException;
    
}

    
    
The main method in this interface will return an object that implements the GradeInfo interface, which is
    /*
     * GradeInfo.java
     *
     */
    
    package edu.harvard.cs262;
    
    /**
     * The interface that characterizes the objects returned
     * by the Hello interface. This object will be obtained
     * and then used locally by the testing program.
     *
     * @author waldo
     */
    public interface GradeInfo {
        /**
         * returns the number of students who worked on 
         * this project (and who will share the grade)
         */
        public int getNumber();
        
        /** Returns the name of the ith student to work
         * on the project, which i < the value returned
         * by the getNumber() method
         */
        public String getName(int i);
        
        /** Returns the grade that all of the students
         * who worked on this project will receive on the
         * project. This is an I.Q. test, not a 
         * humility test
         */
        public String getGrade();
    }
    
The first method of this interface will return the number of students who worked on the project (together). The second will take an integer (less than the number who worked on the project) and will return the name of one of the students who did the work (all students should have their name returned for some value of i < number who worked on the project; the indexing is 0 based, because we are computer scientists). The final method returns the letter grade that the students will receive for their work.

The second method, when called, will cause the service to shut itself down. The service should remove its registration with the RMI registry, and once it has succeeded in doing that return true to the caller, and then exit. If the method cannot unregister with the RMI registry, it should return false (but this shouldn't happen).

Clearly, the problem here is not the code; it will be deploying the service. Your service needs to be running on one of the machines we have set up for this course. These machines should have an RMI registry running on them, and will have a web server running that will serve files out of your public_html directory. You should register your service using the last name of one of the participants in the project.

I will grade this project by running a test program that will go to the lab machines, grab all of the services registered under the name of anyone taking the class, get the GradeInfo object from that service, and make calls to the GradeInfo object to find out how many of you worked on the project, who you are, and what your grade is. You will have passed the assignment when I have a grade for you.

As before, feel free to work in small groups.

Some Hints

Early returns indicate that the broad hints that I gave in class were too subtle (a charge that is rarely leveled against me); the usual errors are being made and the usual frustrations are being vented. So here are some hints on doing this assignment that may be of use.

Downloading code


The core of this problem is the ability to move a Java object, complete with the code that implements that object, from one computer to another (recall, that is the real innovation behind Java RMI). The problem set defines the interfaces that these downloaded objects will have; you need to supply the implementation of one of them (the class that will implement the GradeInfo interface) while the other (the proxy object for your service) will be defined by the RMI infrastructure from your server. But you will also need to make the interface definitions available.

To make these classes available, you will need to have an http server that can be used to load them. It doesn't matter which one (there are ones running on each of the class servers that will serve files out of your homeDirectory/public_html directory). So, for example, if you want to make a class with the name
edu.harvard.cs262.FooBar
available for download, you will need to do one of two things, and then specify in your server how to find the downloaded content.

The first way to make the content available is to have a classfile by the name of FooBar.class available in the directory public_html/edu/harvard/cs262. The other way to do this is to have a jar file in public_html that contains the file edu/harvard/cs262/FooBar.class. If there are other files that need to be available (like the classfiles that contain the definitions of the interfaces) they need to be located either in the directory or in the jar file. I personally prefer the jarfiles, since you can add files to them as needed. If you are using a jarfile, make sure that you add the file with the full pathname and not simply the classfile FooBar.class, since the package structure needs to be reflected in the directory structure (for reasons too heartbreaking to document here-- if you really want to know, ask in class).

The classes do not need to be available from the same server that is running the implementation of the RMI server. Any http server that is available on the network will do.

Finally, when you run your server, you need to set the codebase, which is where the classes that will be downloaded can be found. You do this by specifying a Java property. The easiest way to do this is on the command line; your starting command should look something like

java -Djava.rmi.server.codebase=http://eecs.harvard.edu/~myName/dl_classes.jar -jar myserver.jar

if your classes are in a jar file (and assuming that your server is in the myserver.jar file), or

java -Djava.rmi.server.codebase=http://eecs.harvard.edu/~myName/ -jar myserver.jar

if your classes are in the directory edu/harvard/cs262/ under the public_html reachable as ~myName on server eecs.harvard.edu. Note that if you are putting your downloaded classes in a jar file, you name the jar file; if you are putting them in the file system, your codebase needs to end with a /. By the way, make sure that you use a fully qualified URL for your codebase, since you can't know where I'm going to be testing. It may be in the eecs domain, but it may not.

It is also important that any class that is going to be downloaded (except the proxy for your service, which is generated by RMI so you don't need to worry) must be serializable, which means that it must implement the marker interface java.io.Serializable. Also, being serializable, you should make sure that there is a private static long field that is the serialVersionUID. This field is used to determine version equivalence, and can be set to most any value (convention now has it set to 1, but it doesn't really matter). This is another long story that I can tell you about if asked...

Note that you don't have to download code for everything to work if all of the code can be found in your classpath. This is why you will often find that your programs run just fine on your own machine, but don't run on the class servers. This is because on your own machine you have developed both the client and the server in the same place, so all of the classes that the server would generally need to export and the client download are available to the client through the file system. If it works on your machine but not on the class servers, don't blame the class servers. It is almost certainly a problem with the way you have set up your codebase. A good thing to do is to develop your client used to test the server in a different directory on your own machine. That makes it more likely that you will find these problems when run on your own machine.

If this doesn't give you enough information to get the work done, there is an excellent tutorial on the subject in the standard Java documentation. Go to the overall Java documentation index, and follow the link to the RMI section. There is a tutorial called Dynamic code downloading using Java RMI. You will save much of your time (and mine) by reading it...

Types

In Java, types matter; RMI is built to utilize Java, so types matter here, as well. The types defined by the Hello and GradeInfo interfaces are the central communication mechanisms for the assignment. That means that if you change those interfaces, or have your implementation classes implement something different from those interfaces, your implementation will not work.

This doesn't mean that your implementations can't implement other interfaces as well. But they need to implement exactly the assigned iterfaces. Implementing something else, even if you know that they are the same, won't do. And remember that Java is a name-equivalence language, not a structural equivalence language. Changing the name of the type makes it a different type, which will keep things from working.


Jim Waldo