13.6 Migrating and Non-Migrating Objects

 < Day Day Up > 



13.6 Migrating and Non-Migrating Objects

Before describing how to use RMI in an application, an important concept in RMI is that some objects can be sent across the network to run on a remote computer, and some of them can be run on a local computer. I will call objects that run on a remote computer migrating objects because they move (migrate) from one computer to another computer. Objects that run on the computer on which they are created are called non-migrating objects because they do not move across the network; instead, they are called remotely from the system that uses them. [1] Because migrating objects must move across the network, they must have a representation that can run on any computer and hence must be serializable. Non-migrating objects do not have to be serializable, but must follow the rules for creating a server object, as discussed in Section 12.5.2.

Program13.2 (Exhibits 8 through 12) and Program13.3 (Exhibits 13 and 14) illustrate the difference between a migrating and a non-migrating object. In both of these programs, a server is created that implements a sendMessage method. This method takes a printMessage object created on the client computer and sent via the sendMessage method to the server. The only difference between Program13.2 (Exhibits 8 through 12) and Program13.3 (Exhibits 13 and 14) is that in Program13.2 (Exhibits 8 through 12) the PrintMessage object is a migrating object, so it is serializable and runs in the remote server's process (the message will print in the DOS window where the server was started). In Program13.3 (Exhibits 13 and 14), the PrintMessage object is a non-migrating object. When the PrintMessage object is passed to the server, it continues to run on the client and only passes a reference to the PrintMessage object to the server. The PrintMessage object thus runs on the client, and when the print method is called on the server it will run in the client's process (the message is printed in the window where the client is running).

Exhibit 8 (Program13.2a), Exhibit 9 (Program13.2b), and Exhibit 10 (Program13.2c) show the implementation of the Server interface, ServerImp, and Client classes for the migrating object. These classes are exactly the same for the non-migrating object and will not be shown with Program13.3 (Exhibits 13 and 14). As with the HelloWorld program, the Server object simply registers with rmiregistry and waits for the client to call its methods. The Client object retrieves the Server object from rmiregistry and calls the sendMessage method on the Server object, sending the PrintMessageImp object.

Exhibit 8: Program13.2a: Server Interface

start example

 interface Server extends java.rmi.Remote {   public void sendMessage(PrintMessage pm)     throws java.rmi.RemoteException; } 

end example

Exhibit 9: Program13.2b: ServerImp Class

start example

 import java.rmi.*; import java.rmi.server.UnicastRemoteObject; import java.io.*; class ServerImp extends UnicastRemoteObject      implements Server, Serializable {   public ServerImp() throws java.rmi.RemoteException {     super();   }   public void sendMessage(PrintMessage pm) {     try {       pm.print();     } catch (Exception e) {       e.printStackTrace();     }   }   public static void main(String argv[]) {     try {       ServerImp thisExample = new ServerImp();       Naming.rebind("/Server," thisExample);       System.out.println("bound in registry");     } catch (Exception e) {       System.out.println("HelloGuy err: "+ e.getMessage());       e.printStackTrace();     }   } } 

end example

Exhibit 10: Program13.2c: Client Class

start example

 import java.rmi.*; class Client {   public static void main(String argv[]) {     try {       Server server = (Server)Naming.lookup(         "// localhost/Server");       server.sendMessage(         new PrintMessageImp("Created on Client"));     } catch(Exception e) {       e.printStackTrace();     }   } } 

end example

The differences between Program13.2 (Exhibits 8 through 12) and Program13.3 (Exhibits 13 and 14) are completely in the PrintMessage and PrintMessageImp objects, and these are examined here. In Program13.2 (Exhibits 8 through 12), the PrintMessage interface and PrintMessageImp class are normal serializable objects in that they do not use any of the RMI infrastructures; therefore, when the object is created on the client and passed to the server, the actual object is sent to the server. Thus, the PrintMessageImp class must exist on the server (not just the interface and stub classes) because the actual PrintMessageImp object will be run on the server. When the print method is called, the message prints out in the window running the server process. The PrintMessage interface and PrintMessageImp class are shown in Exhibit 11 (Program13.2d) and Exhibit 12 (Program13.2e).

Exhibit 11: Program13.2d: PrintMessage Interface

start example

 public interface PrintMessage {   public void print(); } 

end example

Exhibit 12: Program13.2e: PrintMessageImp Class

start example

 import java.io.Serializable; public class PrintMessageImp implements     PrintMessage,Serializable {   String message;   public PrintMessageImp(String message) {     this.message = message;   }   public void print() {     System.out.println(message);   } } 

end example

Program13.3 (Exhibits 13 and 14) is similar to Program13.2 (Exhibits 8 through 12), but the PrintMessage and PrintMessageImp classes now implement the infrastructure to use RMI. Also, when compiling these programs rmic must be run on PrintMessageImp, and the PrintMessageImp_Stub.class file (not the PrintMessageImp.class file) must be copied to the directory containing the server. This is because the PrintMessageImp class is only run on the client, not the server, so the PrintMessageImp.class file need only exist on the client, but the stub file must be accessible to the server so that it can call back to the client. When the print method is called on the server, the message is passed back to the client, and the message comes out in the window running the client. Exhibit 13 (Program13.3a) and Exhibit 14 (Program13.3b) show the implementation of the PrintMessage interface and PrintMessageImp objects for the migrating objects example.

Exhibit 13: Program13.3a: PrintMessage Interface for Migrating Object

start example

 public interface PrintMessage extends java.rmi.Remote {   public void print() throws java.rmi.RemoteException; } 

end example

Exhibit 14: Program13.3b: PrintMessageImp Class for Non-Migrating Object

start example

 import java.rmi.*; import java.rmi.server.UnicastRemoteObject; public class PrintMessageImp extends UnicastRemoteObject      implements PrintMessage {   String message;   public PrintMessageImp(String message) throws java.rmi.       RemoteException {     this.message = message;   }   public void print() throws java.rmi.RemoteException {     System.out.println(message);   } } 

end example

One last note is that the PrintMessageImp object did not need to register with rmiregistry, because rmiregistry is only used to find an object. In this case, the object was passed as a parameter to the server, so it is already known and it does not have to be looked up in rmiregistry. The actual communications are not handled by rmiregistry, so in that sense it is not really an object request broker (ORB). The communications are handled completely in the stub and skeleton classes.

This behavior of allowing objects to migrate or not has many uses; for example, it can be used to create agents that can roam across the network looking for computers on which they can run. In the next section, the dichotomy between a migrating and non-migrating object is used to implement a simple chat program.

[1]The Java references refer to non-migrating objects as remote and migrating objects as non-remote. This is because a non-migrating object stays on the computer on which it was created and is thus called remotely when it is called. A migrating object moves to another computer, so when its methods are called they are called non-remotely. I will use the terminology of migrating and non-migrating because it seems more intuitive to talk about what happens to the objects, not the semantics of the method call. It also helps to make the difference between objects that must be serializable vs. objects that implement UnicastRemoteObject more understandable.



 < Day Day Up > 



Creating Components. Object Oriented, Concurrent, and Distributed Computing in Java
The .NET Developers Guide to Directory Services Programming
ISBN: 849314992
EAN: 2147483647
Year: 2003
Pages: 162

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net