This is a very brief intro into Java's RMI API. It is based on a simple example that invokes methods, on a remote machine, which square and cube a number. Some of the commands used assume the use of GNU/Linux so you might need to change a few things if you're using Windows.
import java.rmi.*; public interface TestRMIObject extends Remote { public int square(int x) throws RemoteException; public int cube(int x) throws RemoteException; }
import java.rmi.*; import java.rmi.server.*; public class TestRMIObjectImpl extends UnicastRemoteObject implements TestRMIObject { public TestRMIObjectImpl() throws RemoteException { } public int square(int x) throws RemoteException { return x * x; } public int cube(int x) throws RemoteException { return x * x * x; } }
NOTE: A constructor that throws the "RemoteException" seems to be required even if it doesn't contain any code.
import java.rmi.*; public class TestRMIObjectServer { public TestRMIObjectServer() { try { TestRMIObject tro = new TestRMIObjectImpl(); Naming.rebind("rmi://localhost/SquareCube",tro); System.out.println("TestRMIObject instance registered."); } catch(Exception e) {System.out.println("Exception caught: " + e);} } public static void main(String[] args) { TestRMIObjectServer tros = new TestRMIObjectServer(); } }
The "localhost" in the rebind call above could be any host name. At the moment I have only been able to register a object with an rmiregistry that is running on the same machine. I think that the most likely cause of this is the policy file, i.e. a permissions thing. When I sort that out I will update these notes. The "SquareCube" above could be anything: it is just the name that this object will be known by.
grant { permission java.net.SocketPermission "*:1024-65535","connect,accept"; permission java.net.SocketPermission "*:80", "connect"; };
At the moment all I can say about this is that it seems to tell the JVM that it is ok for it to
accept connections on ports 1024 through 65535.
I do not know all the details of what can or should go into this file to make sure that it gives an
implementation that is both usable and secure.
The above works!
This will create the normal class files.
javac TestRMIObjectServer.java
This is done by running the rmi compiler againt the class file that IMPLEMENTS the remote interface:
rmic TestRMIObjectImpl
NOTE: there is no ".class"
This will generate a further two class files:
TestRMIObjectImpl_stub.class
TestRMIObjectImpl_skel.class
But... make sure you keep a copy of the TestRMIObject_stub.class because the client needs to be compiled against it.
import java.io.*; import java.net.*; import java.rmi.*; public class TestRMIObjectClient { private TestRMIObject tro; static public void main(String[] args) { int res; TestRMIObjectClient troc = new TestRMIObjectClient(); try { res = troc.tro.square(5); System.out.println("remote square called, result: " + res); res = troc.tro.cube(10); System.out.println("remote cube called, result: " + res); } catch(Exception e) { System.out.println("Exception caught: " + e); } } public TestRMIObjectClient() { try { tro = (TestRMIObject) Naming.lookup ("rmi://laptop/SquareCube"); System.out.println("Remote object created..."); } catch(Exception e) { System.out.println ("Exception: " + e); } } }Replace "laptop" in this: "rmi://laptop/SquareCube" with either the name or IP adress of the remote machine.
[me@local_machine dir_name]$ java TestRMIObjectClient
The output should be:
25
1000