# Java IDL: The "Hello World" Example

## Using the POA, a persistent server, and a persistent naming service

This document is a high-level overview of how to create a complete CORBA (Common Object Request Broker Architecture) application using IDL (Interface Definiton Language) to define interfaces and the Java IDL compiler to generate stubs and skeletons. For more information on the development process, and a more detailed tutorial on creating a CORBA application using IDL, link to Getting Started with Java IDL: The Hello World Tutorial. You can also create CORBA applications by defining the interfaces in the Java programming language. For more information and a tutorial on this development process, link to Java RMI-IIOP documentation.

For more information on transient vs. persistent servers, please refer to the document Developing Servers.

This document contains:

- The IDL for a simple "Hello World" program
- A persistent server that creates an object and publishes it with the naming service using the default server-side implementation (POA)
- A servant that implements each of the IDL interfaces
- An application client that knows the object's name, retrieves a reference for it from the naming service, and invokes the object
- Instructions for compiling and running the example

## Defining the Interface (`PersistentHello.idl`)

The first step to creating a CORBA application is to specify all of your objects and their interfaces using the OMG's Interface Definition Language (IDL). IDL has a syntax similar to C++ and can be used to define modules, interfaces, data structures, and more. 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.

The following code is written in the OMG IDL, and describes a CORBA object whose `sayHello()` operation returns a string and whose `shutdown()` method shuts down the ORB. To learn more about OMG IDL Syntax and Semantics, link to the OMG Web site, and read Chapter 3 of the CORBA Specification.

PersistentHello.idl

    module Persistent {
        interface Hello {
            string sayHello( );
            oneway void shutdown();
        };
    };

NOTE: When writing code in OMG IDL, do not use an interface name as the name of a module. Doing so runs the risk of getting inconsistent results when compiling with tools from different vendors, thereby jeopardizing the code's portability. For example, code containing the same names could be compiled with the IDL to Java compiler from Sun Microsystems and get one result. The same code compiled with another vendor's IDL to Java compiler could produce a different result.

To complete the application, you simply provide the server (`PersistentServer.java`), servant (`PersistentHelloServant.java`), and client (`PersistentClient.java`) implementations.

## Implementing the Server (`PersistentServer.java`)

The example server, `PersistentServer`, has the server's `main()` method, which:

- Creates and initializes an ORB instance
- Creates a servant
- Gets a reference to the root POA
- Creates the policy that makes the server persistent
- Creates a persistent POA by passing in the persistent policy
- Activates the persistent POA's `POAManager`
- Associates the servant with the persistent POA
- Gets a CORBA object reference for the root naming context in which to register the new CORBA object
- Narrows the object reference to a naming context
- Registers the new object in the naming context under the name "PersistentServerTutorial"
- Waits for invocations of the new object from the client

This example provides an example of a persistent object server. For an example of the "Hello World" program with a transient object server, see Hello World with a Transient Server. For more discussion of CORBA servers, see Developing Servers.

PersistentServer.java

    // PersistentServer.java
    // Copyright and License
    import java.util.Properties;
    import org.omg.CORBA.Object;
    import org.omg.CORBA.ORB;
    import org.omg.CosNaming.NameComponent;
    import org.omg.CosNaming.NamingContextExt;
    import org.omg.CosNaming.NamingContextExtHelper;
    import org.omg.CORBA.Policy;
    import org.omg.PortableServer.POA;
    import org.omg.PortableServer.*;
    import org.omg.PortableServer.Servant;

    public class PersistentServer {

        public static void main( String args[] ) {
            Properties properties = System.getProperties();
            properties.put( "org.omg.CORBA.ORBInitialHost",
                "localhost" );
            properties.put( "org.omg.CORBA.ORBInitialPort",
                "1050" );

            try {
                // Step 1: Instantiate the ORB
                ORB orb = ORB.init(args, properties);

                // Step 2: Instantiate the servant
                PersistentHelloServant servant = new PersistentHelloServant(orb);

                // Step 3 : Create a POA with Persistent Policy
                // *******************
                // Step 3-1: Get the rootPOA
                POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
                // Step 3-2: Create the Persistent Policy
                Policy[] persistentPolicy = new Policy[1];
                persistentPolicy[0] = rootPOA.create_lifespan_policy(
                    LifespanPolicyValue.PERSISTENT);
                // Step 3-3: Create a POA by passing the Persistent Policy
                POA persistentPOA = rootPOA.create_POA("childPOA", null,
                    persistentPolicy );
                // Step 3-4: Activate PersistentPOA's POAManager, Without this
                // All calls to Persistent Server will hang because POAManager
                // will be in the 'HOLD' state.
                persistentPOA.the_POAManager().activate( );
                // ***********************

                // Step 4: Associate the servant with PersistentPOA
                persistentPOA.activate_object( servant );

                // Step 5: Resolve RootNaming context and bind a name for the
                // servant.
                // NOTE: If the Server is persistent in nature then using Persistent
                // Name Service is a good choice. Even if ORBD is restarted the Name
                // Bindings will be intact. To use Persistent Name Service use
                // 'NameService' as the key for resolve_initial_references() when
                // ORBD is running.
                org.omg.CORBA.Object obj = orb.resolve_initial_references(
                    "NameService" );
                NamingContextExt rootContext = NamingContextExtHelper.narrow( obj );

                NameComponent[] nc = rootContext.to_name(
                    "PersistentServerTutorial" );
                rootContext.rebind( nc, persistentPOA.servant_to_reference(
                    servant ) );

                // Step 6: We are ready to receive client requests
                orb.run();
            } catch ( Exception e ) {
                System.err.println( "Exception in Persistent Server Startup " + e );
            }
        }
    }

## Implementing the Servant (`PersistentHelloServant.java`)

The example servant, `PersistentHelloServant`, is the implementation of the `Hello` IDL interface; each `Hello` instance is implemented by a `PersistentHelloServant` 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.

PersistentHelloServant.java

    // PersistentHelloServant.java
    // Copyright and License
    import org.omg.CORBA.ORB;

    public class PersistentHelloServant extends Persistent.HelloPOA {
        private ORB orb;

        public PersistentHelloServant( ORB orb ) {
            this.orb = orb;
        }

        /**
         *  sayHello() method implementation returns a simple message.
         */
        public String sayHello( ) {
            return "Hello From Persistent Server...";
        }

        /**
         *  shutdown() method shuts down the Persistent Server.
         *  See NOTE below.
         */
        public void shutdown( ) {
            orb.shutdown( false );
        }
    }

Note: For convenience of presentation in this example, the `shutdown()` method is included as part of the servant. This has been done in order to demonstrate the persistence of the server in this example. This is not a recommended programming convention for the following reasons:

- If the `orb.shutdown()` method is called with parameter `true` (meaning "wait for completion") within the implementation of a remote method, the ORB will hang in a deadlock. Other threads can invoke `orb.shutdown()` without deadlock.
- If you have multiple servants associated with the ORB, using the `shutdown(false)` method by one of them will make all of them unavailable.
- The `orb.shutdown(false)` method should be called as part of the SERVER code under more controlled circumstances.

## Implementing the Client Application (`PersistentClient.java`)

The example application client that follows:

- Creates and initializes an ORB.
- Resolves the `PersistentHelloServant` by using the Interoperable Naming Service's (INS) `corbaname url`. The URL locates the Naming Service running on host localhost and listening on port 1050. When located, it resolves "PersistentServerTutorial" from that Naming Service.
- Invokes the object's `sayHello()` and `shutdown()` operations and prints the result. In this example, the client calls the `sayHello()` method every 3 seconds, then shuts down the server. The next call from the client will restart the server (because of the persistent lifespan of the server).

PersistentClient.java

    // Copyright and License

    import java.util.Properties;
    import org.omg.CORBA.ORB;
    import org.omg.CORBA.OBJ_ADAPTER;
    import org.omg.CosNaming.NamingContext;
    import org.omg.CosNaming.NamingContextHelper;
    import org.omg.CosNaming.NameComponent;
    import org.omg.PortableServer.POA;

    import Persistent.HelloHelper;
    import Persistent.Hello;

    public class PersistentClient {

        public static void main(String args[]) {

            try {
                // Step 1: Instantiate the ORB
                ORB orb = ORB.init(args, null);

                // Step 2: Resolve the PersistentHelloServant by using INS's
                // corbaname url. The URL locates the NameService running on
                // localhost and listening on 1050 and resolve
                // 'PersistentServerTutorial' from that NameService
                org.omg.CORBA.Object obj = orb.string_to_object(
                    "corbaname::localhost:1050#PersistentServerTutorial");

                Hello hello = HelloHelper.narrow( obj );

                // Step 3: Call the sayHello() method every 60 seconds and shutdown
                // the server. Next call from the client will restart the server,
                // because it is persistent in nature.
                while( true ) {
                    System.out.println( "Calling Persistent Server.." );
                    String helloFromServer = hello.sayHello();
                    System.out.println("Message From Persistent Server: " +
                        helloFromServer );
                    System.out.println( "Shutting down Persistent Server.." );
                    hello.shutdown( );
                    Thread.sleep( 60000 );
                }
            } catch ( Exception e ) {
                System.err.println( "Exception in PersistentClient.java..." + e );
                e.printStackTrace( );
            }
        }
    }

## Building and Running Hello World

Despite its simple design, the Hello World program lets you learn and experiment with all the tasks required to develop almost any CORBA program that uses static invocation.

This example requires a naming service, which is a CORBA service that allows CORBA objects to be named by means of binding a name to an object reference. The name binding may be stored in the naming service, and a client may supply the name to obtain the desired object reference. This example uses orbd, which contains a Persistent Naming Service and a Server Manager.

When running this example, remember that, when using Solaris software, you must become root to start a process on a port under 1024. For this reason, we recommend that you use a port number greater than or equal to 1024. The following instructions assume you can set the `-ORBInitialPort` option to use port 1050 for the Java IDL Object Request Broker Daemon, `orbd`. You can substitute a different port if necessary.

To run this client-server application on your development machine:

1. Create or download the IDL and Java files for this example.
2. Change to the directory that contains the file `PersistentHello.idl`.

3. Run the IDL-to-Java compiler, `idlj`, on the IDL file to create stubs and skeletons. This step assumes that you have included the path to the `java/bin` directory in your path.

         idlj  -fall -td . -verbose  PersistentHello.idl

   You must use the `-fall` option with the `idlj` compiler to generate both client and server-side bindings. This command line will generate the default server-side bindings, which assumes the POA Inheritance server-side model. For more information on the `idlj` options, link to IDL-to-Java compiler options.

   The `idlj` compiler generates a number of files. The actual number of files generated depends on the options selected when the IDL file is compiled. The generated files provide standard functionality, so you can ignore them until it is time to deploy and run your program. The files generated by the `idlj` compiler for `PersistentHello.idl`, with the `-fall` command line option, are:

   - `HelloPOA.java`

     This abstract class is the stream-based server skeleton, 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 `PersistentHelloServant` extends `HelloPOA`.

   - `_HelloStub.java`

     This class is the client stub, providing CORBA functionality for the client. It extends `org.omg.CORBA.portable.ObjectImpl` and implements the `Hello` interface.

   - `Hello.java`

     This interface contains the Java version of our IDL interface. The `Hello.java` interface extends `org.omg.CORBA.Object`, providing standard CORBA object functionality. It also extends the `HelloOperations` interface and `org.omg.CORBA.portable.IDLEntity`.

   - `HelloHelper.java`

     This class 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 `Any`s. The Holder class delegates to the methods in the Helper class for reading and writing.

   - `HelloHolder.java`

     This `final` class 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`.

   - `HelloOperations.java`

     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.

4. Compile the `.java` files, including the stubs and skeletons (which are in the directory `Persistent`). This step assumes the `java/bin` directory is included in your path.

          javac *.java Persistent/*.java

5. Start `orbd`.

   To start `orbd`, enter:

         orbd -ORBInitialPort 1050 -serverPollingTime 200&          (Unix operating system)

         start orbd  -ORBInitialPort 1050 -serverPollingTime 200&   (Windows operating system)

   Note that `1050` is the port on which you want the name server to run. The `-ORBInitialPort` argument is a required command-line argument. Note that when using Solaris software, you must become root to start a process on a port under 1024. For this reason, we recommend that you use a port number greater than or equal to 1024.

   The `-serverPollingTime 200` argument specifies how often ORBD checks for the health of persistent servers registered via `servertool`. The default value is 1,000 ms. We are setting this parameter to 200 ms in this example to enable more frequent monitoring of failures. In the event that a server failure is detected, the server will be restarted to its proper state.

6. Start the Hello server:

   To register a persistent server with the ORBD, the server must be started using servertool, which is a command-line interface for application programmers to register, unregister, startup, and shutdown a persistent server. When the `servertool` is started, you must specify the port and the host (if different) on which `orbd` is executing.

   To start the Hello server,

   - Start the `servertool` from the command line of another terminal window or command prompt as follows:

           servertool -ORBInitialPort 1050        (Unix operating system)

           start servertool -ORBInitialPort 1050  (Windows operating system)

     Make sure the name server (`orbd`) port is the same as in the previous step, for example, `-ORBInitialPort 1050`. The `servertool` must be started on the same port as the name server.

     The `servertool` command line interface appears:

   - Register the `PersistentServer` from the `servertool` prompt, as shown below. Type the information in one long string without returns.

           servertool  > register -server PersistentServer -applicationName s1
                         -classpath path_to_server_class_files

     The `servertool` registers the server, assigns it the name of "s1", and displays its server id.

7. Run the client application from the command line of another terminal window or command prompt:

         java -classpath . PersistentClient

   The terminal window or DOS prompt displays the following messages:

       Calling Persistent Server..
       Message From Persistent Server: Hello From Persistent Server...
       Shutting down Persistent Server..
       Calling Persistent Server..
       Message From Persistent Server: Hello From Persistent Server...
       Shutting down Persistent Server..

In this example, the client invokes the `sayHello()` method every minute and then kills the persistent server, which will be automatically restarted the next time the client invokes the `sayHello()` method.

When you have finished this tutorial, be sure to shut down or kill the name server (`orbd`). To do this from a DOS prompt, select the window that is running the server and enter `Ctrl+C` to shut it down. To do this from a Unix shell, type `pkill ordb` from a terminal window. The server will continue to wait for invocations until it is explicitly stopped.

Running the Hello World Application on Two Machines describes one way of distributing the simple application across two machines - a client and a server.

## Running the Example on Unix Using a Makefile

The following code provides an example of a Makefile that can be used to run this example. Change the location of `JAVA_HOME` to the location where you installed J2SE 5.0. Change the `CLASSPATH` variable to the directory where you have created the sample application. This example is for the Unix operating system, modify accordingly if using the Windows operating system.

    #Change to location of your Java SE installation.
    JAVA_HOME=/home/user_name/j2sdk1.5.0/

    CLASSPATH=.

    JAVAC=$(JAVA_HOME)/bin/javac
    JAVA=$(JAVA_HOME)/bin/java

    ORB_INITIAL_PORT=1050
    ORB_INITIAL_HOST=localhost
    ORB_ACTIVATION_PORT=1049

    #Change ClassPath based on where your PersistentServer is located.
    export CLASSPATH=<path to server class files>
    IDLJ :=$(JAVA_HOME)/bin/idlj

    ORB_PROPS=-Dorg.omg.CORBA.ORBInitialHost=$(ORB_INITIAL_HOST)
    -Dorg.omg.CORBA.ORBInitialPort=$(ORB_INITIAL_PORT)

    IDLJ_FLAGS=-fall -td . -verbose

    ORBD=${JAVA_HOME}/bin/orbd -ORBInitialPort ${ORB_INITIAL_PORT}
    -port ${ORB_ACTIVATION_PORT} -serverPollingTime 200
    -serverStartupDelay 1000

    SERVERTOOL=${JAVA_HOME}/bin/servertool

    all: clean build run

    build: stubs

    stubs:
    	$(IDLJ) $(IDLJ_FLAGS) PersistentHello.idl
    	$(JAVAC) *.java
    	$(JAVAC) Persistent/*.java

    runc:
    	$(JAVA) -classpath . PersistentClient

    runorbd:
    	$(ORBD)

    # Enter the following command in servertool to register server:
    # (without the # sign)
    # register -server PersistentServer -applicationName s1
    -classpath path_to_server_class_files

    servertool:
    	$(SERVERTOOL) -ORBInitialPort $(ORB_INITIAL_PORT)

    clean:
    	rm -rf Persistent
    	rm -rf *.class

To run the application using the Makefile, enter the following commands:

1. gnumake build
2. gnumake runorbd
3. gnumake runservertool
4. In `servertool`, enter the commands as shown above
5. gnumake runc

Java IDL Home