ProblemThe client looks good on paper, but it will be lonely without a server to talk to. SolutionYou need to write two parts for the server, an implementation class and a main method. These can be in the same class or separated for clarity. DiscussionThe server-side code has to do a bit more work; see the sidebar.
This implementation divides the server into the traditional two parts a main program and an implementation class. It is just as feasible to combine these in a single class. The main program shown in Example 22-3 simply constructs an instance of the implementation and registers it with the lookup service. Example 22-3. DateServer.javapackage darwinsys.distdate; import java.rmi.*; public class DateServer { public static void main(String[] args) { // You may want a SecurityManager for downloading of classes: // System.setSecurityManager(new RMISecurityManager( )); try { // Create an instance of the server object RemoteDateImpl im = new RemoteDateImpl( ); System.out.println("DateServer starting..."); // Locate it in the RMI registry. Naming.rebind(RemoteDate.LOOKUPNAME, im); System.out.println("DateServer ready."); } catch (Exception e) { System.err.println(e); System.exit(1); } } } The Naming.bind( ) method creates an association between the lookup name and the instance of the server object. This method fails if the server already has an instance of the given name, requiring you to call rebind( ) to overwrite it. But since that's exactly where you'll find yourself if the server crashes (or you kill it while debugging) and you restart it, many people just use rebind( ) all the time. The implementation class must implement the given remote interface. See Example 22-4. Example 22-4. RemoteDateImpl.javapackage darwinsys.distdate; import java.rmi.*; import java.rmi.server.*; import java.util.*; public class RemoteDateImpl extends UnicastRemoteObject implements RemoteDate { /** Construct the object that implements the remote server. * Called from main, after it has the SecurityManager in place. */ public RemoteDateImpl( ) throws RemoteException { super( ); // sets up networking } /** The remote method that "does all the work". This won't get * called until the client starts up. */ public Date getRemoteDate( ) throws RemoteException { return new Date( ); } } Using the serverOnce you've compiled the implementation class, you can run rmic (the RMI compiler) to build some glue files and install the class files (for the interface, the stub, and any data classes) into the client's CLASSPATH: $ jikes -d . RemoteDateImpl.java $ ls darwinsys/distdate DateApplet$1.class DateClient.class RemoteDate.class DateApplet.class DateServer.class RemoteDateImpl.class $ rmic -d . darwinsys.distdate.RemoteDateImpl $ ls darwinsys/distdate DateApplet$1.class DateServer.class RemoteDateImpl_Skel.class DateApplet.class RemoteDate.class RemoteDateImpl_Stub.class DateClient.class RemoteDateImpl.class $ You must also ensure that TCP/IP networking is running and then start the RMI registry program. If you're doing this by hand, just type the command rmiregistry in a separate window or start it in the background on systems that support this. See AlsoSee the JDK documentation in docs/guide/rmi/getstart.doc.html. |