Sie sind auf Seite 1von 9

Remote Method Invocation (RMI) Remote Method Invocation (RMI) allows a Java object that executes on one machine

to invoke a method of a Java object that executes on another machine.This is an important feature, because it allows you to build distributed applications. Here is a simple example describes basic principles involved. A Simple Client/Server Application Using RMI This section provides step-by-step directions for building a simple client/server application by using RMI. The server receives a request from a client, processes it, and returns a result. In this example, the request specifies two numbers. The server adds these together and returns the sum. Step One: Enter and Compile the Source Code This application uses four source files. The first file, AddServerIntf.java, defines the remote interface that is provided by the server. It contains one method that accepts two double arguments and returns their sum. All remote interfaces must extend the Remote interface, which is part of java.rmi. Remote defines no members. Its purpose is simply to indicate that an interface uses remote methods. All remote methods can throw a RemoteException. import java.rmi.*; public interface AddServerIntf extends Remote { double add(double d1, double d2) throws RemoteException; } The second source file, AddServerImpl.java, implements the remote interface. The implementation of the add( ) method is straightforward. All remote objects must extend UnicastRemoteObject, which provides functionality that is needed to make objects available from remote machines. import java.rmi.*; import java.rmi.server.*; public class AddServerImpl extends UnicastRemoteObject implements AddServerIntf { public AddServerImpl() throws RemoteException { } public double add(double d1, double d2) throws RemoteException { return d1 + d2; } }

The third source file, AddServer.java, contains the main program for the server machine. Its primary function is to update the RMI registry on that machine. This is done by using the rebind( ) method of the Naming class (found in java.rmi). That method associates a name with an object reference. The first argument to the rebind( ) method is a string that names the server as AddServer. Its second argument is a reference to an instance of AddServerImpl. import java.net.*; import java.rmi.*; public class AddServer { public static void main(String args[]) { try { AddServerImpl addServerImpl = new AddServerImpl(); Naming.rebind("AddServer", addServerImpl); } catch(Exception e) { System.out.println("Exception: " + e); } } } The fourth source file, AddClient.java, implements the client side of this distributed application. AddClient.java requires three command line arguments. The first is the IP address or name of the server machine. The second and third arguments are the two numbers that are to be summed. The application begins by forming a string that follows the URL syntax. This URL uses the rmi protocol. The string includes the IP address or name of the server and the string AddServer. The program then invokes the lookup( ) method of the Naming class. This method accepts one argument, the rmi URL, and returns a reference to an object of type AddServerIntf. All remote method invocations can then be directed to this object. The program continues by displaying its arguments and then invokes the remote add( ) method. The sum is returned from this method and is then printed. import java.rmi.*; public class AddClient { public static void main(String args[]) { try { String addServerURL = "rmi://" + args[0] + "/AddServer"; AddServerIntf addServerIntf = (AddServerIntf)Naming.lookup(addServerURL);

System.out.println("The first number is: " + args[1]);

double d1 = Double.valueOf(args[1]).doubleValue(); System.out.println("The second number is: " + args[2]); double d2 = Double.valueOf(args[2]).doubleValue(); System.out.println("The sum is: " + addServerIntf.add(d1, d2)); } catch(Exception e) { System.out.println("Exception: " + e); } } } After you enter all the code, use javac to compile the four source files that you created. Step Two: Generate Stubs and Skeletons Before you can use the client and server, you must generate the necessary stub. You may also need to generate a skeleton. In the context of RMI, a stub is a Java object that resides on the client machine. Its function is to present the same interfaces as the remote server. Remote method calls initiated by the client are actually directed to the stub. The stub works with the other parts of the RMI system to formulate a request that is sent to the remote machine. A remote method may accept arguments that are simple types or objects. In the latter case, the object may have references to other objects. All of this information must be sent to the remote machine. That is, an object passed as an argument to a remote method call must be serialized and sent to the remote machine. Recall from Chapter 17 that the serialization facilities also recursively process all referenced objects. Skeletons are not required by Java 2. However, they are required for the Java 1.1 RMI model. Because of this, skeletons are still required for compatibility between Java 1.1 and Java 2. A skeleton is a Java object that resides on the server machine. It works with the other parts of the 1.1 RMI system to receive requests, perform deserialization, and invoke the appropriate code on the server. Again, the skeleton mechanism is not required for Java 2 code that does not require compatibility with 1.1. Because many readers will want to generate the skeleton, one is used by this example. If a response must be returned to the client, the process works in reverse. Note that the serialization and deserialization facilities are also used if objects are returned to a client. To generate stubs and skeletons, you use a tool called the RMI compiler, which is invoked from the command line, as shown here: rmic AddServerImpl This command generates two new files: AddServerImpl_Skel.class (skeleton) and AddServerImpl_Stub.class (stub). When using rmic, be sure that CLASSPATH is set to include the current directory. As you can see, by default, rmic generates both a stub and a skeleton file. If you do not need the skeleton, you have the option to suppress it.

Step Three: Install Files on the Client and Server Machines Copy AddClient.class, AddServerImpl_Stub.class, and AddServerIntf.class to a directory on the client machine. Copy AddServerIntf.class, AddServerImpl.class, AddServerImpl_Skel.class, AddServerImpl_Stub.class, and AddServer.class to a directory on the server machine. Note RMI has techniques for dynamic class loading, but they are not used by the example at hand. Instead, all of the files that are used by the client and server applications must be installed manually on those machines. Step Four: Start the RMI Registry on the Server Machine The Java 2 SDK provides a program called rmiregistry, which executes on the server machine. It maps names to object references. First, check that the CLASSPATH environment variable includes the directory in which your files are located. Then, start the RMI Registry from the command line, as shown here: start rmiregistry When this command returns, you should see that a new window has been created. You need to leave this window open until you are done experimenting with the RMI example. Step Five: Start the Server The server code is started from the command line, as shown here: java AddServer Recall that the AddServer code instantiates AddServerImpl and registers that object with the name AddServer. Step Six: Start the Client The AddClient software requires three arguments: the name or IP address of the server machine and the two numbers that are to be summed together. You may invoke it from the command line by using one of the two formats shown here: java AddClient server1 8 9 java AddClient 11.12.13.14 8 9 In the first line, the name of the server is provided. The second line uses its IP address (11.12.13.14). You can try this example without actually having a remote server. To do so, simply install all of the programs on the same machine, start rmiregistry, start AddSever, and

then execute AddClient using this command line: java AddClient 127.0.0.1 8 9 Here, the address 127.0.0.1 is the loop back address for the local machine. Using this address allows you to exercise the entire RMI mechanism without actually having to install the server on a remote computer. In either case, sample output from this program is shown here: The first number is: 8 The second number is: 9 The sum is: 17.0

CORBA
CORBA (Common Object Request Broker Architecture) is the standard distributed object architecture developed by the Object Management Group (OMG) consortium. Since 1989 the mission of the OMG has been the specification of an architecture for an open software bus, or Object Request Broker (ORB), on which object components written by different vendors can interoperate across networks and operating systems. This standard allows CORBA objects to invoke one another without knowing where the objects they access reside or in what language the requested objects are implemented. The OMG-specified Interface Definition Language (IDL) is used to define the interfaces to CORBA objects. CORBA objects differ from typical programming language objects in these ways: CORBA objects can be located anywhere on a network. CORBA objects can interoperate with objects on other platforms. CORBA objects can be written in any programming language for which there is a mapping from OMG IDL to that language. (Mappings currently specified include Java, C++, C, Smalltalk, COBOL, and Ada.)

CORBA Concepts in a Nutshell


The diagram below shows a method request sent from a client to a CORBA object implementation in a server. A client is any code (perhaps itself a CORBA object) that invokes a method on a CORBA object. The servant is an instance of the object implementation - the actual code and data that implements the CORBA object.

The client of a CORBA object has an object reference for the object and the client uses this object reference to issue method requests. If the server object is remote, the object reference points to a stub function, which uses the ORB machinery to forward invocations to the server object. The stub code uses the ORB to identify the machine that runs the server object and asks that machine's ORB for a connection to the object's server. When the stub code has the connection, it sends the object reference and parameters to the skeleton code linked to the destination object's implementation. The skeleton code transforms the call and parameters into the required implementation-specific format and calls the object. Any results or exceptions are returned along the same path. The stub and skeleton files are generated by the idltojava compiler for each object type. Stub files present the client with access to IDL-defined methods in the client programming language. The server skeleton files glue the object implementation to the ORB runtime. The ORB uses the skeletons to dispatch methods to the object implementation instances (servants).

Defining and Implementing CORBA Objects


The goal in CORBA object development is the creation and registration of an object server, or simply server. A server is a program which contains the implementation of one or more object types and which has been registered with the ORB. For example, you might develop a desktop publishing server which implements a "Document" object type, a "Paragraph" object type, and other related object types.

CORBA Object Interfaces


All CORBA objects support an IDL interface; the IDL interface defines an object type. An interface can inherit from one or more other interfaces. IDL syntax is very similar to that of Java or C++, and an IDL file is functionally the CORBA language-independent analog to a C++ header file. IDL is mapped into each programming language to provide access to object interfaces from that language. With Java IDL, these IDL interfaces can be translated to Java using the idltojava compiler. For each IDL interface, idltojava generates a Java interface and the other .java files needed, including a client stub and a server skeleton. An IDL interface declares a set of client accessible operations, exceptions, and typed attributes (values). Each operation has a signature that defines its name, parameters, result, and exceptions. A simple IDL interface that describes the classic "Hello World" program, follows.
module HelloApp { interface Hello { string sayHello(); }; };

An operation may raise an exception when an error condition arises. The type of the exception indicates the kind of error that was encountered. Clients must be prepared to handle defined exceptions and CORBA standard exceptions for each operation in addition to normal results.

Java Language-based Implementation


Once the IDL interfaces have been defined and the idltojava compiler run on the .idl file, .java files containing the method implementations may be written. The .java implementation files are then compiled and linked with the idltojava -generated .java files and the ORB library to create an object server. An object implementation defines the behavior for all the operations and attributes of the interface it supports. There may be multiple implementations of an interface, each designed to emphasize a specific time and space trade-off, for example. The implementation defines the behavior of the interface and object creation/destruction. Since only servers can create new CORBA objects, a factory object interface should be defined and implemented for each object type. For example, if Document is an object type, a DocumentFactory object type with a create method should be defined and implemented as part of the server. (Note that "create" is not reserved; any method name may be used.) The implementation of the create method can then use new to create the object. For example:
DocumentServant document orb.connect(document); = new DocumentServant():

A destroy method may be defined and implemented on Document; or, the object may be intended to persist indefinitely. (Again, "destroy" is not reserved and any name may be used.)

The Java IDL ORB supports transient objects only - objects whose lifetime is limited by the server process lifetime. Although a transient object dissapears when its server process stops running, the object may be implemented to store its state in a file and to re-initialize itself from this file at creation time.

Client Implementation
Client code is linked with idltojava-generated .java files and the ORB library. Examples of application and applet clients are provided in the Hello World example. Clients may only create CORBA objects via the published factory interfaces that the server provides. Likewise, a client may only delete a CORBA object if that object publishes a destruction method. Since a CORBA object may be shared by many clients around a network, only the object server is in a position to know when the object has become garbage. The client code's only way of issuing method requests on a CORBA object is via the object's object reference. The object reference is an opaque structure which identifies a CORBA object's host machine, the port on which the host server is listening for requests, and a pointer to the specific object in the process. Because Java IDL supports only transient objects, this object reference becomes invalid if the server process has stopped and restarted. Clients typically obtain object references in the following ways: from a factory object. For example, the client could invoke a create method on DocumentFactory object in order to create a new Document. The DocumentFactory create method would return an object refererence for Document to the client. from the nameservice. For example, the client could obtain an object reference for the DocumentFactory by issuing a request on the nameservice. From a string that was specially created from an object reference

Once an object reference is obtained, the client must narrow it to the appropriate type. IDL supports inheritance; the root of its hierarchy is Object in IDL, org.omg.CORBA.Object in Java. (org.omg.CORBA.Object is, of course, a subclass of java.lang.Object.) Some operations, notably name lookup and unstringifying, return an org.omg.CORBA.Object, which you narrow (using a helper class generated by the idltojava compiler) to the derived type you want the object to be. CORBA objects must be explicitly narrowed because the Java runtime cannot always know the exact type of a CORBA object.

Java IDL Transient Name Server


The Java IDL Transient Nameservice is an object server provided with Java IDL. Use tnameserv at the command line prompt to start the Name Server. This object server conforms to the standard object implementation and invocation techniques described in

the previous sections of this page. The Name Server stores object references by name in a tree structure similar to a file directory. A client may lookup or resolve object references by name. Because the Name Server is an ordinary Java IDL transient server, the entire directory structure of names is lost each time tnameserv stops running.

Das könnte Ihnen auch gefallen