# Getting Started with Java IDL: Developing the Hello World Server

The example server consists of two classes, the servant and the server. The servant, `HelloServant`, is the implementation of the `Hello` IDL interface; each `Hello` instance is implemented by a `HelloServant` instance. The servant is a subclass of `_HelloImplBase`, which is generated by the `idlj` compiler from the example IDL. The servant contains one method for each IDL operation, in this example, just the `sayHello()` method. 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 server and the stubs.

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

- Creates an ORB instance
- Creates a servant instance (the implementation of one CORBA `Hello` object) and tells the ORB about it
- Gets a CORBA object reference for a naming context in which to register the new CORBA object
- Registers the new object in the naming context under the name "Hello"
- Waits for invocations of the new object

This lesson introduces the basics of writing a CORBA transient server. The steps in this topic cover:

1. Creating HelloServer.java
2. Understanding HelloServer.java
3. Compiling the Hello World Server

To see the complete version of HelloServer.java, follow the link.

## Creating HelloServer.java

To create `HelloServer.java`,

1. Start your text editor and create a file named `HelloServer.java` in your main project directory, `Hello`.

2. Enter the following code for `HelloServer.java` in the text file. The following section, Understanding HelloServer.java, explains each line of code in some detail.

       // The package containing our stubs.
       import HelloApp.*;

       // HelloServer will use the naming service.
       import org.omg.CosNaming.*;

       // The package containing special exceptions thrown by the name service.
       import org.omg.CosNaming.NamingContextPackage.*;

       // All CORBA applications need these classes.
       import org.omg.CORBA.*;

       public class HelloServer
       {
         public static void main(String args[])
         {
           try{

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

             // Create the servant and register it with the ORB
             HelloServant helloRef = new HelloServant();
             orb.connect(helloRef);

             // Get the root naming context
             org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
             NamingContext ncRef = NamingContextHelper.narrow(objRef);

             // Bind the object reference in naming
             // Make sure there are no spaces between ""
             NameComponent nc = new NameComponent("Hello", "");
             NameComponent path[] = {nc};
             ncRef.rebind(path, helloRef);

             // Wait for invocations from clients
             java.lang.Object sync = new java.lang.Object();
             synchronized(sync){
               sync.wait();
             }

           } catch(Exception e) {
               System.err.println("ERROR: " + e);
               e.printStackTrace(System.out);
             }
         }
       }

       class HelloServant extends _HelloImplBase
       {
         public String sayHello()
         {
           return "\nHello world!!\n";

         }
       }

3. Save and close `HelloServer.java`.

## Understanding HelloServer.java

This section explains each line of `HelloServer.java`, describing what the code does, as well as why it is needed for this application.

### Performing Basic Setup

The structure of a CORBA server program is the same as most Java applications: You import required library packages, declare the server class, define a `main()` method, and handle exceptions.

#### Importing Required Packages

First, we import the packages required for the server class:

    // The package containing our stubs.
    import HelloApp.*;

    // HelloServer will use the naming service.
    import org.omg.CosNaming.*;

    // The package containing special exceptions thrown by the name service.
    import org.omg.CosNaming.NamingContextPackage.*;

    // All CORBA applications need these classes.
    import org.omg.CORBA.*;

#### Declaring the Server Class

The next step is to declare the server class:

    public class HelloServer
    {
      // The main() method goes here.
    }

#### Defining the main() Method

Every Java application needs a `main` method. It is declared within the scope of the `HelloServer` class:

      public static void main(String args[])
      {
        // The try-catch block goes here.
      }

#### Handling CORBA System Exceptions

Because all CORBA programs can throw CORBA system exceptions at runtime, all of the `main()` functionality is placed within a try-catch block. CORBA programs throw runtime exceptions whenever trouble occurs during any of the processes (marshaling, unmarshaling, upcall) involved in invocation. The exception handler simply prints the exception and its stack trace to standard output so you can see what kind of thing has gone wrong.

The try-catch block is set up inside `main()`, as shown:

        try{

          // The rest of the HelloServer code goes here.

        } catch(Exception e) {
            System.err.println("ERROR: " + e);
            e.printStackTrace(System.out);
          }

### Creating an ORB Object

Just like in the client application, a CORBA server also needs a local ORB object. Every server instantiates an ORB and registers its servant objects so that the ORB can find the server when it receives an invocation for it.

The ORB variable is declared and initialized inside the try-catch block.

          ORB orb = ORB.init(args, null);

The call to the ORB's `init()` method passes in the server's command line arguments, allowing you to set certain properties at runtime.

### Managing the Servant Object

A server is a process that instantiates one or more servant objects. The servant implements the interface generated by `idlj` and actually performs the work of the operations on that interface. Our `HelloServer` needs a `HelloServant`.

#### Instantiating the Servant Object

We instantiate the servant object inside the try-catch block, just below the call to `init()`, as shown:

          HelloServant helloRef = new HelloServant();

The section of code describing the servant class will be explained in a later step.

The next step is to connect the servant to the ORB, so that the ORB can recognize invocations on it and pass them along to the correct servant:

          orb.connect(helloRef);

#### Defining the Servant Class

At the end of `HelloServer.java`, outside the `HelloServer` class, we define the class for the servant object.

    class HelloServant extends _HelloImplBase
    {
      // The sayHello() method goes here.
    }

The servant is a subclass of `_HelloImplBase` so that it inherits the general CORBA functionality generated for it by the compiler.

Next, we declare the required `sayHello()` method:

      public String sayHello()
      {
        // The method implementation goes here.
      }

The `sayHello()` implementation looks like this:

        return "\nHello world!!\n";

### Working with COS Naming

The `HelloServer` works with the naming service to make the servant object's operations available to clients. The server needs an object reference to the name service, so that it can register itself and ensure that invocations on the Hello interface are routed to its servant object.

#### Obtaining the Initial Naming Context

In the try-catch block, below instantiation of the servant, we call `orb.resolve_initial_references()` to get an object reference to the name server:

          org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");

The string "NameService" is defined for all CORBA ORBs. When you pass in that string, the ORB returns a naming context object that is an object reference for the name service.

#### Narrowing the Object Reference

As with all CORBA object references, `objRef` is a generic CORBA object. To use it as a `NamingContext object`, you must narrow it to its proper type. The call to `narrow()` is just below the previous statement:

          NamingContext ncRef = NamingContextHelper.narrow(objRef);

Here you see the use of an `idlj`-generated helper class, similar in function to `HelloHelper`. The `ncRef` object is now an `org.omg.CosNaming.NamingContext` and you can use it to access the naming service and register the server, as shown in the next topic.

#### Registering the Servant with the Name Server

Just below the call to `narrow()`, we create a new `NameComponent` member:

          NameComponent nc = new NameComponent("Hello", "");

This statement sets the `id` field of `nc` to "Hello" and the `kind` component to the empty string. Make sure there are no spaces between the "".

Because the path to the `Hello` has a single element, we create the single-element array that `NamingContext.resolve` requires for its work:

          NameComponent path[] = {nc};

Finally, we pass `path` and the servant object to the naming service, binding the servant object to the "Hello" id:

          ncRef.rebind(path, helloRef);

Now, when the client calls `resolve("Hello")` on the initial naming context, the naming service returns an object reference to the `Hello` servant.

### Waiting for Invocation

The previous sections describe the code that makes the server ready; the next section explains the code that enables it to simply wait around for a client to request its service. The following code, which is at the end of (but within) the try-catch block, shows how to accomplish this.

          java.lang.Object sync = new java.lang.Object();
          synchronized(sync){
            sync.wait();
          }

This form of `Object.wait()` requires `HelloServer` to remain alive (though quiescent) until an invocation comes from the ORB. Because of its placement in `main()`, after an invocation completes and `sayHello()` returns, the server will wait again.

## Compiling the Hello World Server

Now we will compile the `HelloServer.java` so that we can correct any error before continuing with this tutorial.

Windows users note that you should substitute backslashes (\) for the slashes (/) in all paths in this document.

To compile `HelloServer.java`,

1. Change to the `Hello` directory.

2. Run the Java compiler on `HelloServer.java`:

       javac HelloServer.java HelloApp/*.java

3. Correct any errors in your file and recompile if necessary. (You can copy the file from HelloServer.java, if you have trouble finding your typographical errors).

4. The files `HelloServer.class` and `HelloServant.class` are generated in the `Hello` directory.

### Running the Hello World Server

The next section describes Running the Hello World Application.

## For More Information

Exceptions: System Exceptions
  Explains how CORBA system exceptions work and provides details on the minor codes of Java IDL's system exceptions
Developing Servers
  Covers topics of interest to CORBA server programmers
Naming Service
  Covers the COS Naming Service in greater detail

Previous:Developing a Client Application or Developing a Client Applet
Next: Running the Hello World Application
Tutorial home | `HelloServer.java`

Home

Copyright © 1996, 1997 Sun Microsystems, Inc., 2550 Garcia Ave., Mtn. View, CA. 94043-1100 USA., All rights reserved.