The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: IDL
Lesson: The Hello Client-Server Example

## Developing the Hello World Server

> This lesson introduces the basics of writing a CORBA transient server. Here's the complete version of ``HelloServer.java``.

### 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 remember to handle any exceptions.

> ### Importing Required Packages

> Start your text editor and save a new file titled `HelloServer.java`. Next, import the packages required for the client 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

> Declare the server class:

> >     public class HelloServer {
> >         // Add the main method here in the next step.
> >     }

> ### Defining the main Method

> Declare a standard `main` method:

> >     public static void main(String args[]) {
> >         // Add the try-catch block here in the next step.
> >     }

> ### Handling CORBA System Exceptions

> Because all CORBA programs can throw CORBA system exceptions at runtime, you will place all of the `main` functionality 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.

> Inside `main`, set up a `try-catch` block:

> >     try {
> >         // Add the rest of the HelloServer code here.
> >     } catch(Exception e) {
> >         System.err.println("ERROR: " + e);
> >         e.printStackTrace(System.out);
> >     }

> ### Creating an ORB Object

> Just like a client, 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.

> Inside `HelloServer.java`'s `try-catch` block, declare and initialize an ORB variable:

> >     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 `idltojava` and actually performs the work of the operations on that interface. Our `HelloServer` needs a `HelloServant`.

> ### Instantiating the Servant Object

> Inside the `try-catch` block, just below the call to `init`, instantiate the servant object:

> >     HelloServant helloRef = new HelloServant();

> This servant class isn't defined yet; you will do that in a later step. Next, 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, define the class for the servant object.
> 1. Declare the servant class:

>    >     class HelloServant extends _HelloImplBase {
>    >         // Add the sayHello method here in the next step.
>    >     }

> 2. The servant is a subclass of `_HelloImplBase` so that it inherits the general CORBA functionality generated for it by the compiler.
> 3. Declare the required `sayHello` method:

>    >     public String sayHello() {
>    >         // Add the method implementation here in the next step.
>    >     }

> 4. Write the `sayHello` implementation:

>    >     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, 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. Add the call to `narrow` just below the previous statement:

> >     NamingContext ncRef = NamingContextHelper.narrow(objRef);

> Here you see the use of an `idltojava` -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. You will do that in the next step.

> ### Registering the Servant with the Name Server

> 1. Just below the call to `narrow`, create a new `NameComponent` member:

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

> 2. This statement sets the `id` field of `nc`, the new `NameComponent`, to "Hello" and the `kind` component to the empty string. Because the path to the `Hello` has a single element, create the single-element array that `NamingContext.resolve` requires for its work:

>    >     NameComponent path[] = {nc};

> 3. Finally, 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 server is ready; it simply needs to wait around for a client to request its service. To achieve that, enter the following code at the end of (but within) the `try-catch` block:

> >     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.

| Start of Tutorial > Start of Trail > Start of Lesson | Search