ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Local Invocation for CORBA

by Giuseppe Naccarato
10/23/2002

OBV (Object by Value) was introduced in CORBA 2.3 to allow the exchange of CORBA Object value types. This powerful extension is very useful, for example, to design mutable applications. You can combine OBV with RMI-IIOP to allow Java clients to obtain a copy of remote object.

Before the OBV introduction, CORBA did not enable applications to transfer objects from the server to the client by copying. This is an annoying restriction in developing your Java/CORBA applications based on a CORBA vendor implementation, which does not support OBV. In this article, I'm going to explain how you can simulate the pass-by-value strategy in CORBA so that a client virtual machine can locally invoke methods implemented on a remote CORBA server.

Generally in CORBA, a client dial with a reference of a distributed object. Unlike CORBA, RMI -- since its first version -- allows passing of objects both by reference and by copy. In the first case, the behavior is the same as CORBA -- RMI clients obtain a remote reference of an object. In the second case, the whole object (data + code) is transferred to the client application, thus its methods are performed in the same virtual machine as the client.

To figure out why RMI allows the pass-by-value of objects and CORBA didn't, some explanation is necessary. RMI was designed to exclusively work with Java; consequently, it can take advantage of all language features. Using pass-by-value of objects, an RMI server transfers the serialized bytestream of the required Java object to the client. The client application is written in Java as well, so it is able to locally rebuild the object.

Related Reading

Java RMI
By William Grosso

As you know, using CORBA it is even possible to develop client and server applications using different languages. Thus, a CORBA object may be written in C++ and accessed by Java client applications; consequently, the server can't transfer the Java bytestream of this object to the client, simply because there is no Java object. This is the main hindrance why the first versions of CORBA did not enable applications to transfer objects using the pass-by-value strategy.

The final purpose of this article is to simulate pass-by-value in CORBA, obviously in the case that both server and client are developed in Java, without using OBV and RMI-IIOP. I'm going to build a component which transfers the class bytecode from the server to the client application. To achieve this, first you have to figure out how CORBA works and in which way it can transfer an object by reference. I will show this by using an example. Afterwards, using the same example, I will implement an application simulating pass-by-value of objects and, consequently, the local method invocation.

To compile and execute the code presented in this article, you must use J2SE 1.4 with the new Portable Object Adapter (POA).

Remote Invocation

Suppose you would like to implement a remote stack using CORBA. Clients making a connection to such a distributed stack can invoke the pop and push methods in order to insert or take out an element from the stack. This is the IDL for the interface of the distributed stack object:

interface RemoteStack {
  void push(in short value);
  short pop();
};

You can compile the code below using the new idlj compiler included in J2SE 1.4. Therefore, you may implement the object like this:

import java.util.ArrayList;

// RemoteStack implementation
public class RemoteStackImpl extends RemoteStackPOA {

  private ArrayList _s = new ArrayList();

  public synchronized void push(short value) {
    System.out.println("Push: " + value);
    _s.add(new Short(value));
  }

  public synchronized short pop() {
    if (_s.size()==0) return -1;
    short value = ((Short)_s.get(_s.size()-1)).shortValue();
    _s.remove(_s.size()-1);
    System.out.println("Pop: " + value);
    return value;
  }
}

The RemoteStackImpl class uses an ArrayList to store the elements as short. The pop method returns -1 when the stack is empty; otherwise it returns the short value on the top of the stack and removes it from the ArrayList. Using this strategy, you can only use the stack with positive values, but it is enough for our purpose. It is also important to notice that both push and pop show in the console the value of the element. This means you can figure out whether the methods run on the server or on the client side. Actually, the java.util package already provides the Stack class; I used that data structure just as an example for developing a distributed object.

Now you can write a CORBA server that exposes the developed stack implementation.

import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;
import org.omg.CosNaming.NamingContextPackage.*;

public class RemoteStackServer {

  public static void main(String args[]) throws Exception {

    // Create and initialize the ORB
    ORB orb = ORB.init(args, null);

    // Create the RemoteStack implementation
    RemoteStackImpl impl = new RemoteStackImpl();

    // Activate the POAManager
    POA rootpoa =
      POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
    rootpoa.the_POAManager().activate();

    // Get object reference from the servant
    org.omg.CORBA.Object ref = rootpoa.servant_to_reference(impl);
    RemoteStack href = RemoteStackHelper.narrow(ref);

    // Using NameService
    org.omg.CORBA.Object objRef =
      orb.resolve_initial_references("NameService");
    NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

    // Bind the "REMOTE_STACK" Object Reference in Naming
    String name = "REMOTE_STACK";
    NameComponent path[] = ncRef.to_name(name);
    ncRef.rebind(path, href);

    // Server Ready
    System.out.println("REMOTE STACK SERVER READY.");
    orb.run();

  }
}

As you may notice, the RemoteStackServer performs the following operation:

  • Initializes the ORB.
  • Creates a RemoteStackImpl instance.
  • Activates the POA Manager.
  • Registers the RemoteStackImpl instance to the Name Service with the name REMOTE_STACK.
  • Exposes the object.

Here is a sample of a client application making a connection to the remote stack server.

import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;

public class RemoteStackClient {

  public static void main(String args[]) throws Exception {

    // Create and initialize the ORB
    ORB orb = ORB.init(args, null);

    // Using NameService
    org.omg.CORBA.Object objRef =
      orb.resolve_initial_references("NameService");
    NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

    // Resolve the Object Reference in Naming
    String name = "REMOTE_STACK";
    RemoteStack remoteStack = 
      RemoteStackHelper.narrow(ncRef.resolve_str(name));

    // Push (remote invocation);
    remoteStack.push((short)5);

    // Pop (remote invocation);
    short val = remoteStack.pop();
  }
} 

The code attempts a connection to the distributed object named REMOTE_STACK. Then it invokes the push method, passing 5 as a parameter. Eventually, it invokes the pop method and you will see in the server console the following message, proof the distrubuted object works on the server side:

Push: 5
Pop: 5

In fact, the CORBA Name Service returns a reference to the associated implementation of the RemoteStack object. This also means that when more clients invoke the push method on this object, the elements will be inserted on the same distributed object. The push and pop methods work on a single object living on the remote server. In the previous example, you expect the result of pop to be 5, because this is the last value the push method inserted into the stack. This isn't always true. In fact, if, after the push invocation, and before the pop, another client invokes push(18), the shown value will be 18. The point is clear: there is a single stack object, named REMOTE_STACK -- and all CORBA clients get a reference to that object; therefore, the execution of the push and pop methods will be always remote.

Pages: 1, 2, 3

Next Pagearrow