Java RMI-IIOP Application
Page content

RMI was developed as a simple distributed-objects programming model for Java. Simplicity has its advantages, e.g. better performance, but it is also RMI’s primary weakness. RMI cannot be used in situations where other programming languages (such as C or C++) are used in the implementation of the remote interfaces or clients.

CORBA (Common Object Request Broker Architecture) is another distributed-objects programming model implemented to support remote method invocation among objects written in different programming languages.

IIOP (Internet Inter-Object-Request-Broker Protocol) was developed to address the problem of interoperability among CORBA products from different vendors. The developer of CORBA and IIOP is the Object Management Group (OMG) which manages the CORBA and IIOP specification.

To address the weakness of RMI, a new version of RMI that integrates CORBA compliant distributed computing directly into Java was jointly developed by Sun and IBM. The result is RMI-IIOP (RMI over Internet Inter-ORB Protocol).

RMI-IIOP brings RMI and CORBA together. Remote interfaces in RMI-IIOP can be written in Java and implemented using Java RMI APIs. At the same time, remote interfaces can be implemented using other programming languages so long as the languages are supported by an OMG mapping and by an Object Request Broker (ORB) for those languages.

With RMI-IIOP, clients need not necessarily be written in Java; they can be written in other programming languages and using IDL (Interface Definition Language) derived from the Java remote interfaces. An RMI-IIOP client written in Java, therefore, can interact with an RMI Server (written in Java), RMI-IIOP Server (written in Java) or a CORBA Server (written in any language).

To illustrate the concept of RMI-IIOP, we will revisit the AddServer example and discuss how we can use RMI-IIOP to achieve the same purpose of AddServer.

Altogether there are eight steps in the RMI-IIOP application development process:

  1. Define the remote interface for the AddServer object

  2. Implement the remote interface with AddServerImpl class

  1. Write a server application to start the remote object

  2. Generate Stub and Tie class

  3. Start the transient name server

  4. Run the server application

  5. Write a client application to invoke the add() method of the AddServer object

  1. Run the client application

Define the remote interface for the AddServer object

The remote interface of the AddServer object is given in Code 5.1.

Code 5.1: AddServer interface using RMI-IIOP

1. package addRmiIiop;

2. import java.rmi.Remote;

3. import java.rmi.RemoteException;

4. public interface AddServer extends Remote {

  1. // this method is invoked by remote clients.

  2. double add(double n1, double n2) throws RemoteException;

7. }

Implement the remote interface with AddServerImpl class

The implementation of the add() method is provided by the implementing class AddServerImpl whose code is given in Code 5.2.

Code 5.2: AddServerImpl using RMI-IIOP

1. package addRmiIiop;

2. import java.rmi.RemoteException;

3. import javax.rmi.PortableRemoteObject;

4. public class AddServerImpl extends PortableRemoteObject

5. implements AddServer {

  1. public AddServerImpl() throws RemoteException {

7. super();

  1. }

  2. // implementation of the add() method

  3. public double add(double n1, double n2)

  1. throws RemoteException {

  2. System.out.println(“Number added are " + n1 + " " + n2);

  3. System.out.println(“Total is " + (n1+n2));

  4. return n1 + n2;

  5. }

16. }

Write a server application to start the remote object

We write a server application to start the remote object. The code for the server application is given in Code 5.3.

Code 5.3: AddServerApp using RMI-IIOP

1. package addRmiIiop;

2. import javax.naming.*;

3. import java.util.Properties;

4. public class AddServerApp {

5.

6. static final String FACTORY =

7. “java.naming.factory.initial”;

8. static final String FACTORY_NAME =

9. “com.sun.jndi.cosnaming.CNCtxFactory”;

10. static final String PROVIDER = “java.naming.provider.url”;

11. static final String PROVIDER_URL = “iiop://localhost:900”;

12.

  1. public static void main(String args[]) {

  2. try {

  3. AddServerImpl addServerImpl = new AddServerImpl();

16.

  1. // Create initial context

18. Properties props = new Properties();

19. props.put(AddServerApp.FACTORY,

20. AddServerApp.FACTORY_NAME);

21. props.put(AddServerApp.PROVIDER,

22. AddServerApp.PROVIDER_URL);

23. InitialContext ic = new InitialContext(props);

24.

  1. // Bind the object to the IIOP registry

26. ic.rebind(“AddServer”, addServerImpl);

27.

  1. System.out.println(“AddServer Started \n”);

  2. } catch (Exception ex) {

  3. ex.printStackTrace();

  4. }

  1. }

33. }

Generate Stub and Tie class

To generate the stub and tie classes (CORBA terminology for stub and skeleton) that support the IIOP protocol, we invoke the rmic tool with the –iiop option as follows:

rmic -iiop addRmiIiop.AddServerImpl

Without the –iiop option, rmic generates a stub and skeleton class for the JRMP protocol.

Start the transient name server

We will use the transient name server bundled with J2SE to provide the IIOP CosNaming services for clients to lookup objects. This name server is started by the following command at the command prompt:

start tnameserv

A new window opens with the following printout. The default port for the Transient Name Server is 900:

Initial Naming Context:

IOR:000000000000002b49444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f6e746578744578743a312e300000000000010000000000000080000102000000000e3136392e3235342e31382e333100038400000035afabcb0000000020f54239b30000000100000000000000010000000d544e616d65536572766963650000000000000004000000000a0000000000000100000001000000200000000000010001000000020501000100010020000101090000000100010100

TransientNameServer: setting port for initial object references to: 900

Ready.

If you would like to change the port to another number, use the –ORBInitialPort operator. For example, the following start the transient name server at port 2222:

start tnameserv –ORBInitialPort 2222

Run the Server Application

To run the AddServerApp, we execute:

java addRmiIiop.AddServerApp

The following output is produced when the AddServerApp executes successfully:

AddServer Started

Write a client application to invoke the add() method of the AddServer object

To test the RMI-IIOP application, we will produce a client application to get a reference of the remote object, invokes the latter’s add() method and displays the return value. The client application is given in Code 5.4.

Code 5.4: AddClientApp using RMI-IIOP

1. package addRmiIiop;

2. import javax.rmi.PortableRemoteObject;

3. import javax.naming.InitialContext;

4. import java.util.Properties;

5. public class AddClientApp {

6.

7. static final String FACTORY =

8. “java.naming.factory.initial”;

9. static final String FACTORY_NAME =

10. “com.sun.jndi.cosnaming.CNCtxFactory”;

11. static final String PROVIDER = “java.naming.provider.url”;

12. static String providerUrl = “iiop://”;

  1. public static void main(String args[]) {

  2. if (args.length < 3) {

  1. System.out.println(“Usage: java addRmiIiop.AddClientApp” +

  2. " : ”);

  3. System.exit(0);

  4. }

19.

  1. try {

  2. // Make iiop URL

22. AddClientApp.providerUrl = AddClientApp.providerUrl + args[0];

  1. // Create initial context

24. Properties props = new Properties();

25. props.put(AddClientApp.FACTORY,

26. AddClientApp.FACTORY_NAME);

27. props.put(AddClientApp.PROVIDER,

28. AddClientApp.providerUrl);

29. InitialContext ic = new InitialContext(props);

30.

  1. // Obtain a reference to the Servant Object

32. AddServer addServer = (AddServer) PortableRemoteObject.narrow(

33. ic.lookup (“AddServer”), AddServer.class );

34.

  1. // Display numbers

  2. System.out.println(“First number is: " + args[1]);

  3. double n1 = Double.valueOf(args[1]).doubleValue();

  4. System.out.println(“Second number is: " + args[2]);

  1. double n2 = Double.valueOf(args[2]).doubleValue();

  2. // Invoke remote method and display result

  3. double result = addServer.add(n1, n2);

  4. System.out.println(“Result is: " + result);

  5. } catch (Exception ex) {

  1. ex.printStackTrace();

  2. }

  3. }

47. }

48.

Run the client application

We are now ready to execute the client application. Enter the following in a new command window:

java addRmiIiop.AddClientApp 127.0.0.1 3 4

127.0.0.1 refers to the localhost (i.e. the server and client are running on the same computer). To connect to another computer, replace 127.0.0.1 with the IP address of the server computer. If there is no error, the following output is produced:

First number is: 3

Second number is: 4

Result is: 7.0

At the same time, the following output is displayed at the server:

Number added are 3.0 4.0

Total is 7.0

This post is part of the series: Client/Server Computing

Programs have often been written to run on one computer. What if there are more than one computers available? Can we have a software program to run on more than one computers? How do we maximize the performance of these machines? How does Client/Server Computing address this need?

  1. A Guide to Client/Server Computing: Part One
  2. A Guide to Client/Server Computing: Part Two
  3. A Guide to Client/Server Computing: Part Three
  4. Java Naming and Directory Interface (JNDI)
  5. An RMI-IIOP Application