CLASSPATH
of both the client and the server
Service.java
public class ServiceImpl implements Service {...}
javac *.java
rmic
will generate stubs from an
implementation object
rmic ServiceImpl
rmic -v1.2 ServiceImpl
ServiceImpl_Stub
it must be copied to a directory where an httpd
server can deliver it to clients
cp ServiceImpl_Stub.class /var/httpd/html/classes/ServiceImpl_Stub.class
Remote
interface
RemoteException
interface RemoteFileClassifier extends java.rmi.Remote {
public String getMIMEType(String fileName)
throws java.rmi.RemoteException;
}
java.io.Serialisable
java.rmi.server.UnicastRemoteObject
import java.io.*;
import java.rmi.server.UnicastRemoteObject;
public class RemoteFileClassifierImpl extends UnicastRemoteObject
implements RemoteFileClassifier {
public RemoteFileClassifierImpl()
throws java.rmi.RemoteException {
}
public String getMIMEType(String fileName)
throws java.rmi.RemoteException {
// implementation code
if (fileName.endsWith(".gif")) {
return new String("image/gif");
} else if (fileName.endsWith(".jpeg")) {
return new String("image/jpeg");
} else
// fill in lots of other types,
// but eventually give up and
return null;
}
}
java.rmi.server.codebase
to a URL
import java.rmi.RemoteException;
import java.rmi.Naming;
public class Server {
public static void main(String[] args) {
RemoteFileClassifier classifier = null;
try {
classifier = new RemoteFileClassifierImpl();
} catch(RemoteException e) {
e.printStackTrace();
System.exit(1);
}
// make it public - advertise it
try {
Naming.rebind("rmi://localhost/FileClassifier", classifier);
} catch(RemoteException e) {
e.printStackTrace();
System.exit(1);
} catch(java.net.MalformedURLException e) {
System.out.println(e);
System.exit(1);
}
// main can now finish. An RMI thread keeps the server alive
}
}
import java.io.*;
import java.rmi.Naming;
public class Client {
public static void main(String[] args) {
RemoteFileClassifier classifier = null;
// find the object
System.setSecurityManager(new java.rmi.RMISecurityManager());
try {
classifier = (RemoteFileClassifier)
Naming.lookup("rmi://130.194.67.203/FileClassifier");
} catch(java.net.MalformedURLException e) {
System.out.println(e);
System.exit(1);
} catch(java.rmi.NotBoundException e) {
System.out.println(e);
System.exit(1);
} catch(java.rmi.RemoteException e) {
System.out.println(e);
System.exit(1);
}
// then call it
try {
System.out.println(classifier.getMIMEType("picture.gif"));
} catch(java.rmi.RemoteException e) {
System.out.println(e);
System.exit(1);
}
System.exit(0);
}
}
Naming.rebind(String advertisedName, Object obj);
rmi://host/advertisedName
(Note: the host should not be localhost
since that will break as soon as you use two or more
machines)
Object Naming.lookup(String url)
rmiregistry
RMISecurityManager
should be used when
dealing with remote code
interface RemoteFileClassifier extends java.rmi.Remote {
public String getMIMEType(String fileName)
throws java.rmi.RemoteException;
}
import java.io.*;
import java.rmi.server.UnicastRemoteObject;
public class RemoteFileClassifierImpl extends UnicastRemoteObject
implements RemoteFileClassifier {
public RemoteFileClassifierImpl()
throws java.rmi.RemoteException {
}
public String getMIMEType(String fileName)
throws java.rmi.RemoteException {
// implementation code
if (fileName.endsWith(".gif")) {
return new String("image/gif");
} else if (fileName.endsWith(".jpeg")) {
return new String("image/jpeg");
} else
// fill in lots of other types,
// but eventually give up and
return null;
}
}
import java.rmi.RemoteException;
import java.rmi.Naming;
public class Server {
public static void main(String[] args) {
RemoteFileClassifier classifier = null;
try {
classifier = new RemoteFileClassifierImpl();
} catch(RemoteException e) {
e.printStackTrace();
System.exit(1);
}
// make it public - advertise it
try {
Naming.rebind("rmi://localhost/FileClassifier", classifier);
} catch(RemoteException e) {
e.printStackTrace();
System.exit(1);
} catch(java.net.MalformedURLException e) {
System.out.println(e);
System.exit(1);
}
// main can now finish. An RMI thread keeps the server alive
}
}
-
Client
import java.io.*;
import java.rmi.Naming;
public class Client {
public static void main(String[] args) {
RemoteFileClassifier classifier = null;
// find the object
System.setSecurityManager(new java.rmi.RMISecurityManager());
try {
classifier = (RemoteFileClassifier)
Naming.lookup("rmi://130.194.67.203/FileClassifier");
} catch(java.net.MalformedURLException e) {
System.out.println(e);
System.exit(1);
} catch(java.rmi.NotBoundException e) {
System.out.println(e);
System.exit(1);
} catch(java.rmi.RemoteException e) {
System.out.println(e);
System.exit(1);
}
// then call it
try {
System.out.println(classifier.getMIMEType("picture.gif"));
} catch(java.rmi.RemoteException e) {
System.out.println(e);
System.exit(1);
}
System.exit(0);
}
}
-
Permissive policy file (save as
policy.all
)
grant {
permission java.security.AllPermission "", "";
};
-
Run in separate windows each of the following commands
rmiregistry
java -Djava.rmi.server.codebase=... Server
java -Djava.security.policy=policy.all Client
Non-remote objects
-
A remote method call may have parameters or result
that are themselves objects
-
The parameter may be a variety of objects
-
It could be the stub for a server-side object
-
It could be a client-side object that has a stub
that can be exported
-
It could be a client-side object that is
Serialisable
-
It could be a client-side object that does not have an
exportable stub and does not implement
Serialisable
-
this is an error and will either throw an exception or
pass a null
object
-
The result may be
-
A server-side object with a stub that can be exported
-
A server-side object that implements
Serialisable
-
A server-side that does neither - this is an error
Example
A FireStation
may have a method
FireEngine raiseAlarm(FireEvent evt)
A home may get a stub for a fire station, to raise alarms when a fire event
occurs. In return, it gets a fire engine.
Under the hood - UnicastRemoteObject
-
A remote object usually inherits from this class, or calls
exportObject()
on it
-
When an object is exported, a server is set up to listen to
remote requests for the object
-
The server reads requests from the network, unmarshals them,
calls methods on the remote object, marshals the result
and sends it back
-
The class also creates a stub object using reflection
Under the hood - stub object
-
An RMI server programmer never sees the stub object
-
Special code in the Java runtime looks out for remote objects
and substitutes the stub object - this is a bit strange
-
For example, in
Naming.rebind(Remote)
, the
stub is substituted and sent to the naming service
JRMP
-
JRMP is Java Remote Method Protocol
-
It defines the wire format for RMI messages
Alternative mechanisms
-
RMI is similar to CORBA and other remote method/procedure call systems
-
So it should be possible to have RMI-like mechanisms in these other systems
-
RMI-IIOP is RMI for CORBA, using the CORBA wire format IIOP
-
Jeri (Jini extensible remote invocation) is a cleaned-up version of RMI
that can use lots of different transport mechanisms
RMI-IIOP
-
CORBA allows objects in different languages on different machines to interact
-
RMI allows Java objects on different machines to interact
-
If an interface is defined as both an RMI and a CORBA interface, then
it is possible to create both RMI and CORBA objects
-
The
rmic
stub generator has options to create the RMI stub
which uses IIOP instead of JRMP
-
By then treating it as a CORBA object, it can be run from a CORBA server,
registered with a CORBA naming service or accessed by a CORBA client
-
This is Java-specific - you cannot get a Java RMI object to talk to
a C++ object
-
The mechanism is supported by Enterprise Java Bean containers
Jan Newmarch <jan@newmarch.name>
Last modified: Tue Sep 19 15:22:51 EST 2006
Copyright © Jan Newmarch, Monash University, 2007
This work is licensed under a
Creative Commons License
The moral right of Jan Newmarch to be identified as the author of this page has been asserted.