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, see 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, see Java RMI-IIOP documentation.

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

This document contains:

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, read Chapter 3 of the CORBA 2.3.1 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 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:

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:

Implementing the Client Application (PersistentClient.java)

The example application client that follows:

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 (Solaris, Linux, or Mac OS X or Windows), 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, see the man page for idlj (Solaris, Linux, or Mac OS X or Windows).

    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 Anys. 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 one of the following:

    • Solaris, Linux, or Mac OS X operating system:

      orbd -ORBInitialPort 1050 -serverPollingTime 200&
      
    • Windows operating system:

      start orbd  -ORBInitialPort 1050 -serverPollingTime 200&
      

    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 (Solaris, Linux, or Mac OS X or Windows), 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        (Solaris, Linux, or Mac OS X 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:

      Server Tool
    • 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 shell on Solaris, Linux, or Mac OS X, 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 Solaris, Linux, or Mac OS X 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 Solaris, Linux or Mac OS X operating systems, 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

Copyright © 1993, 2024, Oracle and/or its affiliates. All rights reserved.