Java CORBA

This talk summarizes material from:

1 History

1997 RMI introduced in JDK 1.1. Initially, RMI was positioned as a natural outgrowth of Remote Procedure Calls (RPC), strictly for enabling calls to be made between Java objects in different virtual machines, and even on different physical machines.
1998 JDK 1.2 introduced Java IDL which includes an ORB, IIOP support, and idltojava.
1999 RMI over IIOP extension to Java introduced for JDK 1.1.6 and 1.2. This enabled remote objects written in the Java programming language to be accessible from any language via IIOP.
2000 J2SE introduced idlj which is written in Java and replaced idltojava
2001 J2SE v.1.4 includes support for the Portable Object Adapter, Portable Interceptors, Interoperable Naming Service, GIOP 1.2, and Dynamic Anys

2 Development Steps

  1. Define the remote interface using IDL.
  2. Compile it using idlj.
  3. Implement the server.
  4. Implement the client.
  5. Run them: name service, server, client.

3 Hello.idl

We start with a simple HelloWorld interface:
//Hello.idl
module HelloApp
{
  interface Hello
  {
    string sayHello();
    oneway void shutdown();
  };
};

4 idlj Generated Files

4.1 Hello.java

package HelloApp;


/**
* HelloApp/Hello.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 11:13:24 AM EST
*/

public interface Hello extends HelloOperations,
  org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity 
{
} // interface Hello

4.2 HelloOperations.java

package HelloApp;


/**
* HelloApp/HelloOperations.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 11:13:24 AM EST
*/

public interface HelloOperations 
{
  String sayHello ();
  void shutdown ();
} // interface HelloOperations

4.3 _HelloStub.java

package HelloApp;


/**
* HelloApp/_HelloStub.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 11:13:23 AM EST
*/

public class _HelloStub extends org.omg.CORBA.portable.ObjectImpl
  implements HelloApp.Hello
{

  public String sayHello ()
  {
    org.omg.CORBA.portable.InputStream $in = null;
    try {
       org.omg.CORBA.portable.OutputStream $out = _request ("sayHello", true);
       $in = _invoke ($out);
       String $result = $in.read_string ();
       return $result;
    } catch (org.omg.CORBA.portable.ApplicationException $ex) {
       $in = $ex.getInputStream ();
       String _id = $ex.getId ();
       throw new org.omg.CORBA.MARSHAL (_id);
    } catch (org.omg.CORBA.portable.RemarshalException $rm) {
       return sayHello ();
    } finally {
        _releaseReply ($in);
    }
  } // sayHello

  public void shutdown ()
  {
    org.omg.CORBA.portable.InputStream $in = null;
    try {
       org.omg.CORBA.portable.OutputStream $out = _request ("shutdown", false);
       $in = _invoke ($out);
    } catch (org.omg.CORBA.portable.ApplicationException $ex) {
       $in = $ex.getInputStream ();
       String _id = $ex.getId ();
       throw new org.omg.CORBA.MARSHAL (_id);
    } catch (org.omg.CORBA.portable.RemarshalException $rm) {
       shutdown ();
    } finally {
        _releaseReply ($in);
    }
  } // shutdown

  // Type-specific CORBA::Object operations
  private static String[] __ids = {
    "IDL:HelloApp/Hello:1.0"};

  public String[] _ids ()
  {
    return (String[])__ids.clone ();
  }

  private void readObject (java.io.ObjectInputStream s) throws java.io.IOException
  {
     String str = s.readUTF ();
     String[] args = null;
     java.util.Properties props = null;
     org.omg.CORBA.Object obj =
       org.omg.CORBA.ORB.init (args, props).string_to_object (str);
     org.omg.CORBA.portable.Delegate delegate =
       ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
     _set_delegate (delegate);
  }

  private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException
  {
     String[] args = null;
     java.util.Properties props = null;
     String str = org.omg.CORBA.ORB.init (args, props).object_to_string (this);
     s.writeUTF (str);
  }
} // class _HelloStub

4.4 HelloPOA.java

package HelloApp;


/**
* HelloApp/HelloPOA.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 11:13:23 AM EST
*/

public abstract class HelloPOA extends org.omg.PortableServer.Servant
 implements HelloApp.HelloOperations, org.omg.CORBA.portable.InvokeHandler
{

  // Constructors

  private static java.util.Hashtable _methods = new java.util.Hashtable ();
  static
  {
    _methods.put ("sayHello", new java.lang.Integer (0));
    _methods.put ("shutdown", new java.lang.Integer (1));
  }

  public org.omg.CORBA.portable.OutputStream _invoke (String $method,
                                org.omg.CORBA.portable.InputStream in,
                                org.omg.CORBA.portable.ResponseHandler $rh)
  {
    org.omg.CORBA.portable.OutputStream out = null;
    java.lang.Integer __method = (java.lang.Integer)_methods.get ($method);
    if (__method == null)
      throw new org.omg.CORBA.BAD_OPERATION
        (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);

    switch (__method.intValue ())
    {
       case 0:  // HelloApp/Hello/sayHello
       {
         String $result = null;
         $result = this.sayHello ();
         out = $rh.createReply();
         out.write_string ($result);
         break;
       }

       case 1:  // HelloApp/Hello/shutdown
       {
         this.shutdown ();
         out = $rh.createReply();
         break;
       }

       default:
         throw new org.omg.CORBA.BAD_OPERATION
           (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
    }

    return out;
  } // _invoke

  // Type-specific CORBA::Object operations
  private static String[] __ids = {
    "IDL:HelloApp/Hello:1.0"};

  public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId)
  {
    return (String[])__ids.clone ();
  }

  public Hello _this() 
  {
    return HelloHelper.narrow(
    super._this_object());
  }

  public Hello _this(org.omg.CORBA.ORB orb) 
  {
    return HelloHelper.narrow(
    super._this_object(orb));
  }


} // class HelloPOA

4.5 HelloHelper.java

package HelloApp;


/**
* HelloApp/HelloHelper.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 11:13:23 AM EST
*/

abstract public class HelloHelper
{
  private static String  _id = "IDL:HelloApp/Hello:1.0";

  public static void insert (org.omg.CORBA.Any a, HelloApp.Hello that)
  {
    org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
    a.type (type ());
    write (out, that);
    a.read_value (out.create_input_stream (), type ());
  }

  public static HelloApp.Hello extract (org.omg.CORBA.Any a)
  {
    return read (a.create_input_stream ());
  }

  private static org.omg.CORBA.TypeCode __typeCode = null;
  synchronized public static org.omg.CORBA.TypeCode type ()
  {
    if (__typeCode == null)
    {
      __typeCode = org.omg.CORBA.ORB.init().create_interface_tc
        (HelloApp.HelloHelper.id (), "Hello");
    }
    return __typeCode;
  }

  public static String id ()
  {
    return _id;
  }

  public static HelloApp.Hello read(org.omg.CORBA.portable.InputStream istream)
  {
    return narrow (istream.read_Object (_HelloStub.class));
  }

  public static void write (org.omg.CORBA.portable.OutputStream ostream,
                            HelloApp.Hello value)
  {
    ostream.write_Object ((org.omg.CORBA.Object) value);
  }

  public static HelloApp.Hello narrow (org.omg.CORBA.Object obj)
  {
    if (obj == null)
      return null;
    else if (obj instanceof HelloApp.Hello)
      return (HelloApp.Hello)obj;
    else if (!obj._is_a (id ()))
      throw new org.omg.CORBA.BAD_PARAM ();
    else
    {
      org.omg.CORBA.portable.Delegate delegate =
        ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
      HelloApp._HelloStub stub = new HelloApp._HelloStub ();
      stub._set_delegate(delegate);
      return stub;
    }
  }

}

4.6 HelloHolder.java

package HelloApp;

/**
* HelloApp/HelloHolder.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 11:13:23 AM EST
*/

public final class HelloHolder
  implements org.omg.CORBA.portable.Streamable
{
  public HelloApp.Hello value = null;

  public HelloHolder ()
  {
  }

  public HelloHolder (HelloApp.Hello initialValue)
  {
    value = initialValue;
  }

  public void _read (org.omg.CORBA.portable.InputStream i)
  {
    value = HelloApp.HelloHelper.read (i);
  }

  public void _write (org.omg.CORBA.portable.OutputStream o)
  {
    HelloApp.HelloHelper.write (o, value);
  }

  public org.omg.CORBA.TypeCode _type ()
  {
    return HelloApp.HelloHelper.type ();
  }

}

5 Developing the Server

We must now write a HelloImpl which extends HelloPOA and actually implements the interface, as well as write a server which:

5.1 HelloServer.java

// HelloServer.java
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;

import java.util.Properties;

class HelloImpl extends HelloPOA {
  private ORB orb;

  public void setORB(ORB orb_val) {
    orb = orb_val; 
  }
    
  // implement sayHello() method
  public String sayHello() {
    return "\nHello world !!\n";
  }
    
  // implement shutdown() method
  public void shutdown() {
    orb.shutdown(false);
  }
}


public class HelloServer {

  public static void main(String args[]) {
    try{
      // create and initialize the ORB
      ORB orb = ORB.init(args, null);

      // get reference to rootpoa & activate the POAManager
      POA rootpoa = POAHelper.narrow
        (orb.resolve_initial_references("RootPOA"));
      rootpoa.the_POAManager().activate();

      // create servant and register it with the ORB
      HelloImpl helloImpl = new HelloImpl();
      helloImpl.setORB(orb); 

      // get object reference from the servant
      org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl);
      Hello href = HelloHelper.narrow(ref);
    
      // get the root naming context
      //The string "NameService" is defined for all CORBA ORBs.
      org.omg.CORBA.Object objRef =
          orb.resolve_initial_references("NameService");

      //objRef is a generic object reference. We must narrow it down
      // to the interface we need.
      // Use NamingContextExt which is part of the Interoperable
      // Naming Service (INS) specification.
      NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

      // bind the Object Reference with the Naming Service.
      String name = "Hello";
      NameComponent path[] = ncRef.to_name( name );
      //pas the name to the Naming Service, binding the href to the string
      // "Hello"
      ncRef.rebind(path, href);

      System.out.println("HelloServer ready and waiting ...");

      // wait for invocations from clients
      orb.run();
    } 
  
      catch (Exception e) {
        System.err.println("ERROR: " + e);
        e.printStackTrace(System.out);
      }
    
      System.out.println("HelloServer Exiting ...");
  
  }
}

5.2 Server Implementation Models

5.3 HelloServer.java (tie server)

// Copyright and License import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;

import java.util.Properties;

class HelloImpl extends HelloPOA{
  private ORB orb;

  public void setORB(ORB orb_val){
    orb = orb_val;
  }
  
  public String sayHello(){
    return "\nHello world !!\n";
  }
  
  public void shutdown(){
    orb.shutdown(false);
  }
}

public class HelloServer{

  public static void main(String args[]){
    try{
      // create and initialize the ORB
      ORB orb = ORB.init(args, null);

      // Get reference to rootpoa & activate the POAManager
      POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
      rootpoa.the_POAManager().activate();

      // create servant and register it with the ORB
      HelloImpl helloImpl = new HelloImpl();
      helloImpl.setORB(orb); 

,---- //different stuff
|       // create a tie, with servant being the delegate.
|       HelloPOATie tie = new HelloPOATie(helloImpl, rootpoa);
| 
|       // obtain the objectRef for the tie
|       // this step also implicitly activates the 
|       // the object
|       Hello href = tie._this(orb);
|       // get the root naming context
|       org.omg.CORBA.Object objRef =
|         orb.resolve_initial_references("NameService");
`----
      
      // Use NamingContextExt which is part of the Interoperable
      // Naming Service specification.
      NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

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

      System.out.println("HelloServer ready and waiting ...");

      // wait for invocations from clients
      orb.run();
      } 
      
    catch (Exception e){
      System.err.println("ERROR: " + e);
      e.printStackTrace(System.out);
    }
    
    System.out.println("HelloServer Exiting ...");
  
  }
}
 

5.4 HelloPOATie.java

package HelloApp;


/**
* HelloApp/HelloPOATie.java .
* Generated by the IDL-to-Java compiler (portable), version "3.1"
* from Hello.idl
* Thursday, March 21, 2002 4:54:32 PM EST
*/

public class HelloPOATie extends HelloPOA
{

  // Constructors

  public HelloPOATie ( HelloApp.HelloOperations delegate ) {
      this._impl = delegate;
  }
  public HelloPOATie ( HelloApp.HelloOperations delegate ,
                       org.omg.PortableServer.POA poa ) {
      this._impl = delegate;
      this._poa      = poa;
  }
  public HelloApp.HelloOperations _delegate() {
      return this._impl;
  }
  public void _delegate (HelloApp.HelloOperations delegate ) {
      this._impl = delegate;
  }
  public org.omg.PortableServer.POA _default_POA() {
      if(_poa != null) {
          return _poa;
      }
      else {
          return super._default_POA();
      }
  }
  public String sayHello ()
  {
    return _impl.sayHello();
  } // sayHello

  public void shutdown ()
  {
    _impl.shutdown();
  } // shutdown

  private HelloApp.HelloOperations _impl;
  private org.omg.PortableServer.POA _poa;

} // class HelloPOATie

6 HelloClient.java

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

public class HelloClient
{
  //Notice that this is of type Hello
  static Hello helloImpl;

  public static void main(String args[])
    {
      try{
        //A client needs its own ORB to perform all
        // marshalling and IIOP work.
        // create and initialize the ORB
        ORB orb = ORB.init(args, null);
        
        // get the root naming context
        org.omg.CORBA.Object objRef = 
          orb.resolve_initial_references("NameService");
        // Use NamingContextExt instead of NamingContext. This is 
        // part of the Interoperable naming Service.  
        NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
        
        // resolve the Object Reference in Naming
        String name = "Hello";
        //The inner call gets the reference and the outer one narrows it
        // to the proper type.
        helloImpl = HelloHelper.narrow(ncRef.resolve_str(name));
        
        System.out.println("Obtained a handle on server object: " + helloImpl);

        //Invobe a method on the object. magic happens.
        System.out.println(helloImpl.sayHello());
        helloImpl.shutdown();
        
      } catch (Exception e) {
        System.out.println("ERROR : " + e) ;
        e.printStackTrace(System.out);
      }
    }
}

7 Running It

  1. Start the orbd with orbd -ORBInitialPort 1050 -ORBInitialHost localhost &
  2. Start server with java HelloServer -ORBInitialPort 1050 -ORBInitialHost localhost &
  3. Run the client application with java HelloClient -ORBInitialPort 1050 -ORBInitialHost localhost
  4. The client should print "Hello World!".

8 Making Stringified References

9 Running HelloWorld on Two Machines

10 RMI-IIOP

  1. Make sure all constant definitions in remote interfaces are of primitive types or String and evaluated at compile time.
  2. Don't use Java names that conflict with IDL mangled names generated by the Java to IDL mapping rules.
  3. Don't inherit the same method name into a remote interface more than once from different base remote interfaces.
  4. Be careful when using names that differ only in case. The use of a type name and a variable of that type whose name differs from the type name only in case is supported. Most other combinations of names that differ only in case are not supported.
  5. Don't depend on runtime sharing of object references to be preserved exactly when transmitting object references across IIOP. Runtime sharing of other objects is preserved correctly.
  6. Don't use the following features of RMI:
    • RMISocketFactory
    • UnicastRemoteObject
    • Unreferenced
    • The Distributed Garbage Collection (DGC) interfaces

10.1 Using RMI-IIOP

URLs

  1. CORBA Technology and the Java 2 Platform, http://java.sun.com/j2se/1.4/docs/guide/corba/index.html
  2. Java IDL Documentation, http://java.sun.com/j2se/1.4/docs/guide/idl/index.html
  3. Getting Started with Java IDL, http://java.sun.com/j2se/1.4/docs/guide/idl/GShome.html
  4. RMI, CORBA, and Distributed Objects, http://www-105.ibm.com/developerworks/education.nsf/java-onlinecourse-bytitle/92336034DA5B81FB85256758000A3D1B?OpenDocument
  5. Java RMI, http://www.amazon.com/exec/obidos/ASIN/1565924525/multiagentcom/
  6. RMI-IIOP Programmer's Guide, http://java.sun.com/j2se/1.4/docs/guide/rmi-iiop/rmi_iiop_pg.html

This talk available at http://jmvidal.cse.sc.edu/talks/javacorba/
Copyright © 2009 José M. Vidal . All rights reserved.

25 March 2002, 03:08PM