For a detailed description of the code listed here, consult the introductory tutorial, Getting Started with Java IDL.
The following file, Hello.idl, is written in the OMG Interface Definition Language, and describes a CORBA object whose sayHello() operation returns a string and whose shutdown() method shuts down the ORB. OMG IDL is a purely declarative language designed for specifying programming-language-independent operational interfaces for distributed applications. The IDL can be mapped to a variety of programming languages. The IDL mapping for Java is summarized in IDL to Java Language Mapping Summary.
To learn more about OMG IDL Syntax and Semantics, link to the OMG Web site, and read Chapter 3 of the CORBA Specification.
Hello.idl
module HelloApp { interface Hello { string sayHello(); oneway void shutdown(); }; };
The idlj compiler uses the IDL-to-Java mapping to convert IDL interface definitions to corresponding Java interfaces, classes, and methods, which you can then use to implement your client and server code. The following files are generated when Hello.idl is compiled with the IDL-to-Java compiler, using the following command:
idlj -fall Hello.idl
The signature interface file, Hello.java extends org.omg.portable.IDLEntity, org.omg.CORBA.Object, and the operations interface, HelloOperations. The signature interface is used as the signature type in method declarations when interfaces of the specified type are used in other interfaces. From the client's point of view, an object reference for a CORBA Hello object implements this interface.
Note: The Stub implements the Hello interface, where it generates code for each method to marshall the arguments, invoke the method, and then unmarshall the arguments.
package HelloApp; /** * HelloApp/Hello.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public interface Hello extends HelloOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { } // interface Hello
The Java operations interface, HelloOperations.java, is used in the server-side mapping and as a mechanism for providing optimized calls for co-located clients and server. The server developer provides implementation for the methods indicated by the operations interface.
This interface contains the methods sayHello() and shutdown(). The IDL-to-Java mapping puts all of the operations defined on the IDL interface into this file, which is shared by both the stubs and skeletons.
Note: The server writer usually extends HelloPOA and provides implementation for the methods provided by the operations interface.
package HelloApp; /** * HelloApp/HelloOperations.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public interface HelloOperations { String sayHello (); void Shutdown (); } // interface HelloOperations
The Java class HelloHelper provides auxiliary functionality, notably the narrow() method required to cast CORBA object references to their proper types. The Helper class is responsible for reading and writing the data type to CORBA streams, and inserting and extracting the data type from Anys. The Holder class delegates to the methods in the Helper class for reading and writing.
package HelloApp; /** * HelloApp/HelloHelper.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ 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; } } }
The Java class called HelloHolder holds a public instance member of type Hello. Whenever the IDL type is an out or an inout parameter, the Holder class is used. It provides operations for org.omg.CORBA.portable.OutputStream and org.omg.CORBA.portable.InputStream arguments, which CORBA allows, but which do not map easily to Java's semantics. The Holder class delegates to the methods in the Helper class for reading and writing. It implements org.omg.CORBA.portable.Streamable.
package HelloApp; /** * HelloApp/HelloHolder.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ 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 (); } }
The Java class _HelloStub is the stub file for the client-side mapping. It extends org.omg.CORBA.portable.ObjectImpl and implements the Hello.java interface.
package HelloApp; /** * HelloApp/_HelloStub.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ 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
The Java class HelloImplPOA is the skeleton file for the server-side mapping, providing basic CORBA functionality for the server. It extends org.omg.PortableServer.Servant, and implements the InvokeHandler interface and the HelloOperations interface. The server class, HelloServant, extends HelloPOA.
package HelloApp; /** * HelloApp/HelloPOA.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ 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
To complete the application, the developer must write the client and server code.
The example server consists of two classes, the servant and the server. The servant, HelloImpl, is the implementation of the Hello IDL interface; each Hello instance is implemented by a HelloImpl instance. The servant is a subclass of HelloPOA, which is generated by the idlj compiler from the example IDL.
The servant contains one method for each IDL operation, in this example, the sayHello() and shutdown() methods. Servant methods are just like ordinary Java methods; the extra code to deal with the ORB, with marshaling arguments and results, and so on, is provided by the skeleton.
This example shows the code for a transient server. For a "Hello World" application with a persistent server, see Hello World with a Persistent Server.
The following code is written by the developer.
// HelloServer.java // 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; } // 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 // NameService invokes the name service org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); // Use NamingContextExt which is part of the Interoperable // Naming Service (INS) 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 ..."); } }
This example shows a Java client application. You could write a CORBA client as a servlet, a JSP, an applet, etc.
// Copyright and License import HelloApp.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; public class HelloClient { static Hello helloImpl; public static void main(String args[]) { try{ // 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"; helloImpl = HelloHelper.narrow(ncRef.resolve_str(name)); System.out.println("Obtained a handle on server object: " + helloImpl); System.out.println(helloImpl.sayHello()); helloImpl.shutdown(); } catch (Exception e) { System.out.println("ERROR : " + e) ; e.printStackTrace(System.out); } } }
For the details of compiling and running a Java CORBA application,
refer to Building and Running the Hello
World Application.