You are on page 1of 53

Java IDL Tutorial and Guide

Java IDL Tutorial and Guide

1. Getting Started with JavaTM IDL

Java TM IDL is a technology for distributed objects--that is, objects interacting on different
platforms across a network. Java IDL is similar to RMI (Remote Method Invocation), which
supports distributed objects written entirely in the Java programming language. However, Java
IDL enables objects to interact regardless of whether they're written in the Java programming
language or another language such as C, C++, COBOL, or others.

This is possible because Java IDL is based on the Common Object Request Brokerage Architecture
(CORBA), an industry-standard distributed object model. A key feature of CORBA is IDL, a
language-neutral Interface Definition Language. Each language that supports CORBA has its own
IDL mapping--and as its name implies, Java IDL supports the mapping for Java.

To support interaction between objects in separate programs, Java IDL provides an Object Request
Broker, or ORB. The ORB is a class library that enables low-level communication between Java
IDL applications and other CORBA-compliant applications.

This tutorial teaches the basic tasks in building a CORBA distributed application using Java IDL.
You will build the classic "Hello World" program as a distributed application, with both applet and
application clients. The Hello World program has a single operation that returns a string to be
printed.

Any relationship between distributed objects has two sides: the client and the server. The server
provides a remote interface, and the client calls a remote interface. These relationships are
common to most distributed object standards, including RMI and CORBA. Note that in this
context, the terms client and server define object-level rather than application-level interaction--
any application could be a server for some objects and a client of others. In fact, a single object
could be the client of an interface provided by a remote object and at the same time implement an
interface to be called remotely by other objects.

This figure shows how a one-method distributed object is shared between a CORBA client and
server to implement the classic "Hello World" application.

A one-method distributed object shared between a CORBA client and server.

On the client side, the application includes a reference for the remote object. The object reference
has a stub method, which is a stand-in for the method being called remotely. The stub is actually
wired into the ORB, so that calling it invokes the ORB's connection capabilities, which forwards
the invocation to the server.

On the server side, the ORB uses skeleton code to translate the remote invocation into a method
call on the local object. The skeleton translates the call and any parameters to their
implementation-specific format and calls the method being invoked. When the method returns, the
skeleton code transforms results or errors, and sends them back to the client via the ORBs.

Between the ORBs, communication proceeds by means of a shared protocol, IIOP--the Internet
Inter-ORB Protocol. IIOP, which is based on the standard TCP/IP internet protocol, defines how

-1-
Java IDL Tutorial and Guide

CORBA-compliant ORBs pass information back and forth. Like CORBA and IDL, the IIOP
standard is defined by OMG, the Object Management Group.

The Java IDL Development Process and the Hello World Tutorial

This tutorial teaches the basic tasks in building a CORBA distributed application using Java IDL.
You will build the classic Hello World program as a distributed application, with both applet and
application clients. The Hello World program has a single operation that returns a string to be
printed.

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. The following
steps provide a general guide to designing and developing a distributed object application with
Java IDL. Links to the relevant steps of the tutorial will guide you through creating this sample
application.

1. Define the remote interface

You define the interface for the remote object using the OMG's interface definition
langauge. You use IDL instead of the Java language because the idlj compiler
automatically maps from IDL, generating all Java language stub and skeleton source files,
along with the infrastructure code for connecting to the ORB. Also, by using IDL, you make
it possible for developers to implement clients and servers in any other CORBA-compliant
language.

Note that if you're implementing a client for an existing CORBA service, or a server for an
existing client, you would get the IDL interfaces from the implementer--such as a service
provider or vendor. You would then run the idlj compiler over those interfaces and follow
these steps.

Writing the IDL file in this tutorial walks you through these steps for the simple "Hello
World" example.

2. Compile the remote interface

When you run the idlj compiler over your interface definition file, it generates the Java
version of the interface, as well as the class code files for the stubs and skeletons that
enable your applications to hook into the ORB.

Mapping Hello.idl to Java in this tutorial walks you through these steps for the simple
"Hello World" example.

3. Implement the server

Once you run the idlj compiler, you can use the skeletons it generates to put together your
server application. In addition to implementing the methods of the remote interface, your
server code includes a mechanism to start the ORB and wait for invocation from a remote
client.

Developing the Hello World Server walks you through writing a simple server for the
"Hello World" application.

4. Implement the client

Similarly, you use the stubs generated by the idlj compiler as the basis of your client
application. The client code builds on the stubs to start its ORB, look up the server using

-2-
Java IDL Tutorial and Guide

the name service provided with Java IDL, obtain a reference for the remote object, and call
its method.

Developing a Client Application walks you through writing a simple client application
and Developing a Client Applet walks you through writing a client applet that performs
the same functions as the client application.

5. Start the applications

Once you implement a server and a client, you can start the name service, then start the
server, then run the client.

Compiling and Running the Hello World Application walks you through compiling
and running the server and client program that together make up the "Hello World"
application.

Using Stringified Object References walks you through making an object reference when there
is no naming service.

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

For More Information

Although concepts are explained as they are introduced in the tutorial, you will find more
information in the Concepts section. New terms are linked to their definitions throughout the
tutorial.

The Object Management Group no longer maintains this site, but the CORBA for Beginnners page
contains links to web pages that provide introductory CORBA information.

2. Writing the Interface Definition Language (IDL) file

Note: All command and troubleshooting instructions apply to Java 2 SDK v1.3.0 and its version of
idlj only.

Before you start working with Java IDL, you need to install version 1.3 of the Java 2 SDK. J2SDK
v1.3.0 provides the Application Programming Interface (API) and Object Request Broker (ORB)
needed to enable CORBA-based distributed object interaction, as well as the idlj compiler. 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.

This section teaches you how to write a simple IDL interface definition and how to translate the
IDL interface to Java. It also describes the purpose of each file generated by the idlj compiler.

These topics are included in this section:

1. Writing Hello.idl
2. Understanding the IDL file
3. Mapping Hello.idl to Java
4. Understanding the idlj Compiler Output

-3-
Java IDL Tutorial and Guide

Writing Hello.idl

To create the Hello.idl file,

1. Create a new directory, named Hello, for this application.


2. Start your favorite text editor and create a file named Hello.idl in this directory.
3. In your file, enter the code for the interface definition:

module HelloApp
{
interface Hello
{
string sayHello();
};
};

4. Save the file.

Understanding the IDL file

OMG IDL is a purely declarative language designed for specifying programming-language-


independent operational interfaces for distributed applications. OMG specifies a mapping from
IDL to several different programming languages, including C, C++, Smalltalk, COBOL, Ada, and
Java. When mapped, each statement in OMG IDL is translated to a corresponding statement in
the programming language of choice. You can use the tool idlj to map an IDL interface to Java and
implement the client class. When you map the same IDL to C++ and implement the server in that
language, the Java client and C++ server interoperate through the ORB as though they were
written in the same language.

The IDL for Hello World is extremely simple; its single interface has a single operation. You need
perform only three steps:

1. Declare the CORBA IDL module


2. Declare the interface
3. Declare the operations

Declaring the CORBA IDL Module

A CORBA module is a namespace that acts as a container for related interfaces and declarations.
It corresponds closely to a Java package. Each module statement in an IDL file is mapped to a
Java package statement.

The module statement looks like this:

module HelloApp
{
// Subsequent lines of code here.
};

When you compile the IDL, the module statement will generate a package statement in the Java
code.

Declaring the Interface

Like Java interfaces, CORBA interfaces declare the API contract an object has with other objects.
Each interface statement in the IDL maps to a Java interface statement when mapped.

-4-
Java IDL Tutorial and Guide

In your Hello.idl file, the interface statement looks like this:

module HelloApp
{
interface Hello // These
{ // are the
// interface
}; // statement.
};

When you compile the IDL, this statement will generate an interface statement in the Java code.
Your client and server classes will implement the Hello interface in different ways.

Declaring the Operations

CORBA operations are the behavior that servers promise to perform on behalf of clients that
invoke them. Each operation statement in the IDL generates a corresponding method statement in
the generated Java interface.

In your Hello.idl file, the operation statement looks like this:

module HelloApp
{
interface Hello
{
string sayHello(); // This line is the operation statement.
};
};

Our little Hello World application has only a single operation, so Hello.idl is now complete.

3. Mapping Hello.idl to Java

The tool idlj reads OMG IDL files and creates the required Java files. The idlj compiler defaults to
generating only the client-side bindings. If you need both client-side bindings and server-side
skeletons (as you do for our Hello World program), you must use the -fall option when running the
idlj compiler. For more information on the IDL-to-Java compiler options, follow the link.

1. Go to a command line prompt.


2. Change to the directory containing your Hello.idl file.
3. Enter the compiler command:

idlj -fall Hello.idl

If you list the contents of the directory, you will see that a directory called HelloApp has been
created and that it contains six files. Open Hello.java in your text editor. Hello.java is the
signature interface and is used as the signature type in method declarations when interfaces of the
specified type are used in other interfaces. It looks like this:

package HelloApp;

/**
* HelloApp/Hello.java
* Generated by the IDL-to-Java compiler (portable), version "3.0"
* from Hello.idl
*/

-5-
Java IDL Tutorial and Guide

public interface Hello extends HelloOperations, org.omg.CORBA.Object,


org.omg.CORBA.portable.IDLEntity
{
} // interface Hello

With an interface this simple, it is easy to see how the IDL statements map to the generated Java
statements.

IDL Statement Java Statement

module HelloApp package HelloApp;

interface Hello public interface Hello

The single surprising item is the extends statement. All CORBA objects are derived from
org.omg.CORBA.Object to ensure required CORBA functionality. The required code is generated
by idlj; you do not need to do any mapping yourself.

In previous versions of the idlj compiler (known as idltojava), the operations defined on the IDL
interface would exist in this file as well. Starting with J2SDK v1.3.0, the IDL-to-Java mapping
puts all of the operations defined on the IDL interface in the operations interface,
HelloOperations.java. The operations interface is used in the server-side mapping and as a
mechanism for providing optimized calls for co-located clients and servers. For Hello.idl, this file
looks like this:

package HelloApp;

/**
* HelloApp/HelloOperations.java
* Generated by the IDL-to-Java compiler (portable), version "3.0"
* from Hello.idl
*/

public interface HelloOperations


{
String sayHello ();
} // interface HelloOperations

Because there is only one operation defined in this interface, it is easy to see how the IDL
statements map to the generated Java statements.

IDL Statement Java Statement

string sayHello(); String sayHello();

Understanding the idlj Compiler Output

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 Hello.idl, with the -fall command line option, are:

_HelloImplBase.java

-6-
Java IDL Tutorial and Guide

This abstract class is the server skeleton, providing basic CORBA functionality for the
server. It implements the Hello.java interface. The server class HelloServant extends
_HelloImplBase.
_HelloStub.java
This class is the client stub, providing CORBA functionality for the client. It implements
the Hello.java interface.
Hello.java
This signature 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 IDLEntity, and is used as the signature type in method declarations when
interfaces of the specified type are used in other interfaces.
HelloHelper.java
This final class provides auxiliary functionality, notably the narrow() method required to
cast CORBA object references to their proper types.
HelloHolder.java
This final class holds a public instance member of type Hello. It provides operations for
out and inout arguments, which CORBA allows, but which do not map easily to Java's
semantics.
HelloOperations.java
This operations interface contains the single method sayHello(). The IDL-to-Java
mapping puts all of the operations defined on the IDL interface into this file. The
operations interface is used in the server-side mapping and as a mechanism for providing
optimized calls for co-located clients and servers.

When you write the IDL interface, you do all the programming required to generate all these files
for your distributed application. The next steps are to implement the client and server classes. In
the steps that follow, you will create HelloClient.java and HelloApplet.java client classes and the
HelloServer.java class.

Troubleshooting

• Error Message: "idlj" not found

If you try to run idlj on the file Hello.idl and the system cannot find idlj, it is most likely not
in your path. Make certain that the location of idlj (the J2SDK v.1.3 .bin directory) is in
your path, and try again.

For More Information

• Mapping IDL to Java: Overview

Provides the basics on mapping IDL constructs to the corresponding Java statements.

• Chapter 3 of the OMG CORBA/IIOP specification

Provides the complete specification for OMG Interface Definition Language. At this writing,
the specification can be downloaded from
http://www.omg.org/technology/documents/new_formal/corba.htm.

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

-7-
Java IDL Tutorial and Guide

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

-8-
Java IDL Tutorial and Guide

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

-9-
Java IDL Tutorial and Guide

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.

-10-
Java IDL Tutorial and Guide

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.

-11-
Java IDL Tutorial and Guide

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.

-12-
Java IDL Tutorial and Guide

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

5. Developing a Client Application

This topic introduces the basics of writing a CORBA client application. To create a CORBA client
applet, follow the link. Included in this lesson are:

1. Creating HelloClient.java
2. Understanding HelloClient.java
3. Compiling HelloClient.java

To see a completed version of HelloClient.java, follow the link.

Creating HelloClient.java

To create HelloClient.java,

1. Start your text editor and create a file named HelloClient.java in your main project
directory, Hello.
2. Enter the following code for HelloClient.java in the text file. The following section,
Understanding HelloClient.java, explains each line of code in some detail.

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


import org.omg.CosNaming.*; // HelloClient will use the naming service.
import org.omg.CORBA.*; // All CORBA applications need these
classes.

public class HelloClient


{
public static void main(String args[])
{

-13-
Java IDL Tutorial and Guide

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");
NamingContext ncRef = NamingContextHelper.narrow(objRef);

// Resolve the object reference in naming


// make sure there are no spaces between ""
NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

// Call the Hello server object and print results


String Hello = helloRef.sayHello();
System.out.println(Hello);

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

3. Save and close HelloClient.java.

Understanding HelloClient.java

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

Performing Basic Setup

The basic shell of a CORBA client is the same as many Java applications: You import required
library packages, declare the application class, define a main method, and handle exceptions.

Importing Required Packages

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

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


import org.omg.CosNaming.*; // HelloClient will use the naming service.
import org.omg.CORBA.*; // All CORBA applications need these classes.

Declaring the Client Class

The next step is to declare the client class:

public class HelloClient


{
// The main() method goes here.
}

-14-
Java IDL Tutorial and Guide

Defining a main() Method

Every Java application needs a main() method. It is declared within the scope of the HelloClient
class, as follows:

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 system exceptions
whenever trouble occurs during any of the processes (marshaling, unmarshaling, upcall) involved
in invocation.

Our exception handler simply prints the name of 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(),

try{

// Add the rest of the HelloClient code here.

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

Creating an ORB Object

A CORBA client needs a local ORB object to perform all of its marshaling and IIOP work. Every
client instantiates an org.omg.CORBA.ORB object and initializes it by passing to the object certain
information about itself.

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 your application's command line arguments,
allowing you to set certain properties at runtime.

Finding the Hello Server

Now that the application has an ORB, it can ask the ORB to locate the actual service it needs, in
this case the Hello server. There are a number of ways for a CORBA client to get an initial object
reference; our client application will use the COS Naming Service specified by OMG and provided
with Java IDL. See Using Stringified Object References for information on how to get an initial
object reference when there is no naming service available.

-15-
Java IDL Tutorial and Guide

Obtaining the Initial Naming Context

The first step in using the naming service is to get the initial naming context. In the try-catch
block, below your ORB initialization, you 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 the initial naming context, an object reference to 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.

NamingContext ncRef = NamingContextHelper.narrow(objRef);

Here we 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 find other services. You will do that in the next step.

Finding a Service in Naming

Names can have different structures depending upon the implementation of the naming service.
Consequently, CORBA name servers handle complex names by way of NameComponent objects.
Each NameComponent holds a single part, or element, of the name. An array of NameComponent
objects can hold a fully specified path to an object on any computer file or disk system.

To find the Hello server, you first need a NameComponent to hold an identifying string for the Hello
server.

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

This statement sets the id field of nc to "Hello" and the kind field to an empty string. Be sure this
is an empty string, do not enter a space between "".

Because the path to the Hello object has just one element, we have created a single-element array
out of nc. The NamingContext.resolve() method requires this array for its work:

NameComponent path[] = {nc};

Finally, we pass path to the naming service's resolve() method to get an object reference to the
Hello server and narrow it to a Hello object:

Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

Here you see the HelloHelper helper class at work. The resolve() method returns a generic
CORBA object as you saw above when locating the name service itself. Therefore, you immediately
narrow it to a Hello object, which is the object reference you need to perform the rest of your work.

-16-
Java IDL Tutorial and Guide

Invoking the sayHello() Operation

CORBA invocations look like a method call on a local object. The complications of marshaling
parameters to the wire, routing them to the server-side ORB, unmarshaling, and placing the upcall
to the server method are completely transparent to the client programmer. Because so much is
done for you by generated code, invocation is really the easiest part of CORBA programming.

String Hello = helloRef.sayHello();

Finally, we print the results of the invocation to standard output:

System.out.println(Hello);

Compiling HelloClient.java

Now we will compile HelloClient.java so that we can correct any errors before continuing with
this tutorial.

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

To compile HelloClient.java,

1. Change to the Hello directory.


2. Run the Java compiler on HelloClient.java:

javac HelloClient.java HelloApp/*.java

3. Correct any errors in your file and recompile if necessary. (You can copy the file from
HelloClient.java if you have trouble finding your typographical errors).
4. The HelloClient.class is generated to the Hello directory.

Running the Client Application

We need to create and compile the Hello server before we can successfully run the Hello client
application. Running the Hello World application is covered in Running the Hello World
Application.

For More Information

Developing Clients
Covers topics of interest to CORBA client programmers
Exceptions: System Exceptions
Explains how CORBA system exceptions work and provides details on the minor codes of
Java IDL's system exceptions
Initialization: System Properties
Explains what properties can be passed to the ORB at initialization
Naming Service
Covers the COS Naming Service in greater detail

6. Developing a Client Applet

This topic introduces the basics of writing a CORBA client applet. An applet is a Java program to
be included in HTML pages and executed in Java-enabled browsers. Developing a CORBA client
applet is very similar to developing a CORBA client application, except that in the applet the code

-17-
Java IDL Tutorial and Guide

appears in the init() method rather than in the main() method. You can run the applet from the
Applet Viewer or from a Web browser that is compatible with J2SE v1.3. The steps in this lesson
are:

1. Creating the Applet


2. Understanding the Applet
3. Compiling and Running the Hello World Applet

To see a completed version of HelloApplet.java, follow the link.

Creating the Applet

To create HelloApplet.java,

1. Create a file named HelloApplet.java in the main project directory, Hello, using your
favorite text editor.
2. Enter the following code for HelloApplet.java in the text file. The following section,
Understanding the Applet, explains each line of code in some detail.

// The package containing our stubs.


import HelloApp.*;

// HelloClient 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.*;

// Needed for the applet.


import java.awt.Graphics;

public class HelloApplet extends java.applet.Applet


{
public void init()
{
try{

// Create and initialize the ORB


// The applet 'this' is passed to make parameters from the tag
// available to initialize the ORB
ORB orb = ORB.init(this, null);

// Get the root naming context


org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);

// Resolve the object reference in naming


NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

// Call the Hello server object and print the results


message = helloRef.sayHello();

} catch(Exception e) {

-18-
Java IDL Tutorial and Guide

System.out.println("HelloApplet exception: " + e);


e.printStackTrace(System.out);
}
}
String message = " ";

public void paint(Graphics g)


{
g.drawString(message, 25, 50);
}

3. Save and close HelloApplet.java.

Understanding the Applet

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

Performing Basic Setup

The basic shell of a CORBA client applet is the same as most applets: You import required library
packages, declare the applet class, define an init() method, and handle exceptions.

Importing Required Packages

The first step to creating the basic shell of the applet is to import the packages required for the
client class:

// The package containing our stubs.


import HelloApp.*;

// HelloClient 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.*;

// Needed for the applet.


import java.awt.Graphics;

Declaring the Applet Class

Next, we declare the applet class:

public class HelloApplet extends java.applet.Applet


{
// The init() method goes here.
}

Declaring the init() method

Every Java application needs a main method of some type. In an applet, the init method is used
instead of the main method. The code you write under the init method overrides the Applet's

-19-
Java IDL Tutorial and Guide

default method so that it can respond to major events. In this case, the code will describe how the
applet should be initialized each time it is loaded or reloaded. Typically, an applet will also include
start, stop, and destroy methods.

public void init()


{
// The try-catch block goes here.
}

Handling CORBA System Exceptions

Because all CORBA programs can throw CORBA system exceptions at runtime, all of the init()
functionality is placed within a try-catch block. CORBA programs throw system exceptions
whenever trouble occurs during any of the processes (marshaling, unmarshaling, upcall) involved
in invocation.

The exception handler prints the name of the exception and its stack trace to standard output (the
Java console) so you can see what has gone wrong.

A try-catch block is set up inside init():

try{

// The rest of the HelloApplet code goes here.

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

Creating an ORB Object

A CORBA client needs a local ORB object to perform all of its marshaling and IIOP work. Every
client instantiates an org.omg.CORBA.ORB object and initializes it by passing certain information
about itself to the ORB.

You declare and initialize an ORB variable inside the try-catch block:

Properties props = new Properties();


props.put("org.omg.CORBA.ORBInitialPort", "1050");
ORB orb = ORB.init(this, props);

The call to the ORB's init() method passes in the applet, allowing you to set certain properties at
runtime. Here we have set the ORBInitialPort property to 1050 so that it connects properly to the
HelloServer.

Finding the Hello Server

Now that the applet has an ORB, it can ask the ORB to locate the actual service it needs, in this
case the Hello server. There are a number of ways for a CORBA client to get an initial object
reference; your client applet will use the COS Naming Service specified by OMG and provided with
Java IDL.

-20-
Java IDL Tutorial and Guide

Obtaining the Initial Naming Context

The first step in using the naming service is to get the initial naming context. In the try-catch
block, below your ORB initialization, you call orb.resolve_initial_references() to get an
object reference to the name service:

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 to 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 added 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 find other services.

Finding a Service in Naming

Names can have different structures depending upon the implementation of the naming service.
Consequently, CORBA name servers handle complex names by way of NameComponent objects.
Each NameComponent holds a single part, or element, of the object's full name. An array of
NameComponent objects can hold a fully-qualified path to an object on any computer file or disk
system.

To find the Hello server, you first need a NameComponent to hold an identifying string for it. This
code is found directly below the call to narrow().

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

This statement sets the id field of nc to "Hello" and the kind field to the empty string. To make
sure it's an empty string, make sure there are no spaces between the quotation marks.

Because the path to the Hello object has just one element, create a single-element array out of nc.
The NamingContext.resolve() method requires this array for its work:

NameComponent path[] = {nc};

The NameComponent array is passed to the naming service's resolve() method to get an object
reference to the Hello server and narrow it to a Hello object:

Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

Here you see the HelloHelper class at work. The resolve() method returns a generic CORBA
object as you saw above when locating the name service itself. Therefore, you immediately narrow
it to a Hello object, which is the object reference you need to perform the rest of your work.

-21-
Java IDL Tutorial and Guide

Invoking the sayHello() Operation

CORBA invocations look like a method call on a local object. The complications of marshaling
parameters to the wire, routing them to the server-side ORB, unmarshaling, and placing the upcall
to the server method are completely transparent to the client programmer. Because so much is
done for you by the generated code, invocation is really the easiest part of CORBA programming.

message = helloRef.sayHello();

Finally, print the results of the invocation. This code is placed outside your init() method, but
within the HelloApplet class:

String message = " ";

public void paint(Graphics g)


{
g.drawString(message, 25, 50);
}

Compiling and Running the Hello World Applet

To run the Hello World applet, you first need to compile the applet file and generate the Applet
subclass, then call the subclass within an HTML file using an <APPLET> tag.

Compiling the Client Applet

1. Open a DOS prompt or terminal window. Change to the directory where the
HelloApplet.java file resides.
2. Run the Java compiler on HelloApplet.java:
3. javac HelloApplet.java
4. Correct any errors in your file and recompile if necessary. (You can copy the file from
HelloApplet.java if you have trouble finding your typographical errors).

The generated file HelloApplet.class can be found in your project directory.

Setting Up the HTML File

Once you've written an applet, you need to add it to an HTML page so that you can try it out. You
do this by adding an <APPLET> tag to the basic HTML shell. When you have completed this step,
you can run your applet using the Applet Viewer or from a J2SE v1.3-enabled Web browser.

This section describes how to create the basic HTML file and add the APPLET tag to it.

1. Create a file named Tutorial.html using your favorite text editor in your project
directory, Hello.
2. Enter the following HTML code to Tutorial.html, or paste it from Tutorial.html:

<HTML>
<!--Copyright 2000, Sun Microsystems, Inc. -->
<HEAD>
<TITLE>Getting Started with Java IDL: Running HelloApplet</TITLE>
<X-SAS-WINDOW TOP=42 BOTTOM=477 LEFT=4 RIGHT=534>
</HEAD>
<BODY BGCOLOR="#FFFFFF">

<H1 ALIGN=CENTER>Running the Hello World Applet</H1>

-22-
Java IDL Tutorial and Guide

<HR>

<P>If all goes well, the applet appears below:

<P>
<APPLET CODE=HelloApplet.class
CODEBASE='enter_the_path_to_your_project_directory_here'
WIDTH=500
HEIGHT=300>
<PARAM name="org.omg.CORBA.ORBInitialHost"
value=enter_server_machine_name>
<PARAM name="org.omg.CORBA.ORBInitialPort" value=1050>
</APPLET>

</BODY>
</HTML>

3. Save the file and exit the editor.

The simplest form of the APPLET tag tells the browser to load the applet whose Applet subclass is
name HelloApplet.class. When a Java-enabled browser encounters an <APPLET> tage, it
reserves a display area of the specified WIDTH and HEIGHT, loads the bytecode for the specifiec
Applet subclass, creates an instance of the subclass, and then calls the instances init method.

This applet includes PARAM tags, which let you customize the applet's configuration with
parameters. In the first PARAM tag, the value for ORBInitialHost is the name of the machine
where the CORBA name server runs. In this example, this will most likely be your local machine
name. In the second PARAM tag, the value of ORBInitialPort is the one you are using to run the
name server. This value was defined as 1050 earlier in this tutorial.

By default, a browser looks for an applet's class files in the same directory as the HTML file that
has the <APPLET> tag. We could use the CODEBASE attribute to tell the browser in which directory
the the applet's files are located. If the applet's files and the HTML file are in the same directory,
as they may be in this example, you can eliminate this attribute.

Running the Applet

Now that you have the applet code and the HTML file that loads the applet, you are ready to run
your applet. For information on how to do this, link to Running the Hello World Applet.

Troubleshooting

If you are having trouble running the applet inside your Java-enabled Web browser, make sure
you have the JavaTM 2 Runtime Environment, Standard Edition, version 1.3.0, which includes the
JavaTM Plug-in 1.3. This can be downloaded from http://java.sun.com/products/plugi n/index.html.
Instructions for plugging it into your Web browser are available there as well.

On of the error messages indicative of this situation is security violation: method


verification error.

For More Information

Developing Clients
Covers topics of interest to CORBA client programmers
Exceptions: System Exceptions

-23-
Java IDL Tutorial and Guide

Explains how CORBA system exceptions work and provides details on the minor codes of
Java IDL's system exceptions
Initialization: System Properties
Explains what properties can be passed to the ORB at initialization
Naming Service
Covers the COS Naming Service in greater detail

7. Running the Hello World Application

This topic walks you through running the server and client program that together make up the
"Hello World" application or applet.

Running the Hello World Application

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. To run this
client-server application on your development machine:

1. Start the Java IDL Name Server. To do this from a UNIX command shell, enter:

tnameserv -ORBInitialPort 1050&

From an MS-DOS system prompt (Windows), enter:

start tnameserv -ORBInitialPort 1050

In this example, port 1050 has been chosen for the naming service. You can change this to a
different value if port 1050 is occupied on your system. If the nameserverport is not
specified, port 900 will be chosen by default. 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.

2. From a second prompt or shell, start the Hello server:

On Unix:

java HelloServer -ORBInitialPort 1050&

On Windows:

start java HelloServer -ORBInitialPort 1050

You can leave out -ORBInitialPort nameserverport if the name server is running on the
default port.

If the Hello server is running on a different host (machine) than the naming service, you
would need to specify where the naming service is running when you start the server. To do
this, you would use the -ORBInitialHost nameserverhost argument.

3. From a third prompt or shell, run the Hello application client:

java HelloClient -ORBInitialPort 1050

You can leave out -ORBInitialPort nameserverport if the name server is running on the
default port.

-24-
Java IDL Tutorial and Guide

If the Hello client is running on a different host (machine) than the naming service, you
would need to specify where the naming service is running when you start the client. To do
this, you would use the -ORBInitialHost nameserverhost argument.

4. The client prints the string from the server to the command line:

Hello world!!

The name server and the Hello World server, like many CORBA servers, run until you explicitly
stop them. To avoid having many servers running, kill the server processes after the client
application returns successfully.

Running the Hello World Applet

You can run the applet from either a Java-enabled Web browser (with JRE 1.3) or from the Applet
Viewer. In either case, you must run the Name Server and the HelloServer prior to invoking the
applet. To run the applet,

1. From an MS-DOS system prompt (Windows) or command shell (UNIX), start the Java IDL
name server:

On Unix:

tnameserv -ORBInitialPort 1050&

On Windows:

start tnameserv -ORBInitialPort 1050

In this example, the nameserverport, which is the port on which you want the name server
to run, is set to 1050. If you do not specify this, port 900 will be chosen by default. Also note
that 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.

2. Start the Hello server:

On Unix:

java HelloServer -ORBInitialPort 1050 &

On Windows:

start java HelloServer -ORBInitialPort 1050

In this example, the ORBInitialPort, which is the port on which you want the name
server to run, is set to 1050. If you do not specify this, port 900 will be chosen by default.
Also note that 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.

3. Run the applet.

To run the applet from the appletviewer,

1. Change to the applet directory, Hello.

-25-
Java IDL Tutorial and Guide

2. Start the appletviewer and browse Tutorial.html by typing:

<path_to_appletviewer_executable>appletviewer Tutorial.html

Hello world!! prints to the appletviewer frame.

To run the applet from a Web browser, make sure you have the Java 2 Runtime
Environment, Standard Edition, version 1.3.0, which includes the Java Plugin 1.3,
and the latest version of your browser, preferably Netscape 6, then:

3. Open the Web browser.


4. Open the file Tutorial.html.

Hello world!! prints in the browser frame.

If the applet does not run in the Web browser, make sure you have the Java 2 Runtime
Environment, Standard Edition, version 1.3.0, which includes the Java Plugin 1.3. This plugin is
needed to run the applet and may not be present in older Web browsers.

The name server and the Hello World server, like many CORBA servers, run until you explicitly
stop them. To avoid having many servers running, kill the server processes after the client
application returns successfully.

Troubleshooting

Security violation: method verification error

Make sure you have the Java 2 Runtime Environment, Standard Edition, version 1.3.0, which
includes the Java Plugin 1.3. This plugin is needed to run the applet and may not be present in
older Web browsers. It can be downloaded from http://java.sun.com/products/plugin/index.html.

Specifying ORB Initial Port

The default ORB Initial Port is port 900. If you prefer, you can omit the port specifications if you
start the name server on port 900. Using Solaris software, you must become root to start a process
on a port under 1024. Remember to exit from root access before continuing with the tutorial if you
choose this port for your name server.

8. Using Stringified Object References

To invoke an operation on a CORBA object, a client application needs a reference to the object. You
can get such references in a number of ways, such as calling
ORB.resolve_initial_references() or using another CORBA object (like the name service). In
previous sections of this tutorial, you used both of these methods to get an initial object reference.

Often, however, there is no naming service available in the distributed environment. In that
situation, CORBA clients use a stringified object reference to find their first object.

In this lesson, you will learn how to create a stringified object reference as a part of the server
startup, and how the client gets that reference and destringifies it for use as a real object
reference.

The steps in this lesson are:

1. Making a Stringified Object Reference

-26-
Java IDL Tutorial and Guide

2. Getting a Stringified Object Reference


3. Destringifying the Object Reference
4. Compiling and Running a Stringified Hello World

To see completed versions of the source code, follow the links to HelloServer.java and
HelloClient.java.

Making a Stringified Object Reference

For a stringified object reference to be available to the client, the server must create it and store it
somewhere that the client can access. Your reference will be written to disk in the form of a text
file.

1. Create a new directory at the same level as the Hello directory named HelloString. Copy
Hello.idl to this directory.
2. Copy HelloServer.java from the Hello directory to the HelloString directory. Name it
HelloServerString.java, and make the following changes in this file.
3. Because the new server will write a file to disk, you need to add an import statement. Add
the following:

import java.io.*; // needed for output to the file system.

4. The new server won't use the naming service, so you don't need the CosNaming packages.
Delete these lines from the code:

import org.omg.CosNaming.*; // not needed for stringified version


import org.omg.CosNaming.NamingContextPackage.*; // remove from code

5. Delete the code that gets the initial naming context and resolves the reference to a Hello
object:

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


NameComponent nc = new NameComponent("Hello", " ");
NameComponent path[] = {nc};
ncRef.rebind(path, helloRef);

6. Call the ORB's object_to_string() method and pass it the reference to the servant
object. This returns the object reference in a string form that can be saved in a file on disk.

String ior = orb.object_to_string(helloRef);

7. Build the path to the file that will be stored, using system properties to determine the path
structure and syntax.

String filename = System.getProperty("user.home")+


System.getProperty("file.separator")+"HelloIOR";

8. Use standard Java operations to write the stringified ior to disk:

FileOutputStream fos = new FileOutputStream(filename);


PrintStream ps = new PrintStream(fos);
ps.print(ior);

-27-
Java IDL Tutorial and Guide

ps.close();

9. Save and close HelloServerString.java.

When HelloServerString runs, instead of calling the ORB and registering the servant object
with naming, it creates the text file HelloIOR containing a stringified reference to the servant. The
file is stored in your home directory.

Getting a Stringified Object Reference

Note to Windows users: You should substitute backslashes (\) for the slashes (/) in all paths in this
document.

1. Copy HelloClient.java from the Hello directory to the HelloString directory. Name it
HelloClientString.java, and make the following changes in this file.
2. Because the new client will read a file from the disk, you need to change the import
statements. Add the following:

import java.io.*; // needed for input from the file system.

3. The new client won't use the naming service, so you don't need the CosNaming package.
Delete this line from the code:

import org.omg.CosNaming;* // not needed for stringified version

4. Delete the code that gets the initial naming context and registers the servant with the
naming service:

// Get the root naming context


org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);

// Resolve the object reference in naming


NameComponent nc = new NameComponent("Hello", " ");
NameComponent path[] = {nc};
Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

5. Use standard Java operations to read the file that has the object reference. Note that client
and server programs must know the name of the file and where it is stored.

String filename = System.getProperty("user.home")+


System.getProperty("file.separator")+"HelloIOR";
FileInputStream fis = new FileInputStream(filename);
DataInputStream dis = new DataInputStream(fis);
String ior = dis.readLine();

The HelloClientString application now has a String object containing the stringified object
reference.

Destringifying the Object Reference

To destringify the object reference in ior, call the standard ORB method:

org.omg.CORBA.Object obj = orb.string_to_object(ior);

Finally, narrow the CORBA object to its proper type, so that the client can invoke on it:

-28-
Java IDL Tutorial and Guide

Hello helloRef = HelloHelper.narrow(obj);


The rest of the client code stays the same. Save and close HelloClientString.java.

Compiling and Running a Stringified Hello World

Compiling and running the new version of Hello World requires most of the same steps as for the
naming service version.

Compiling Hello World

1. Change to the HelloString directory.


2. Compile the IDL file. Enter the compiler command:

idlj -fall Hello.idl

3. Run the Java compiler on your source code:

javac *.java

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

HelloServerString.class, HelloServantString.class, and HelloClientString.class are


generated to the HelloString directory.

Running Hello World

To be certain that you are running your own server, check that all Hello server and name server
processes have been stopped. Stop them if they are running.

1. From an MS-DOS system prompt (Windows) or command shell (UNIX), start the Hello
server with the stringified object reference:

java HelloServerString -ORBInitialPort 1050 &

2. From another prompt or shell, run the Hello application client with the stringified object
reference:

java HelloClientString -ORBInitialPort 1050 &

3. The client prints the string from the server to the command line:

Hello world!!

For More Information

Initialization: Obtaining Initial Object References


Explains the various ways of getting an initial object reference

9. The "Hello World" Example on 2 machines

To enable the Hello World Tutorial to run on two machines, follow the steps as directed in the
tutorial, with the following changes. This tutorial was written for the Java (tm) 2 Platform,
Standard Edition (J2Se(tm)), version 1.3. In this example, the client, stubs, and skeletons are

-29-
Java IDL Tutorial and Guide

located on the client machine, and the server and name server are located on the server machine.
This scenario can be changed to meet your needs and is provided simply as an introduction to one
way this can be accomplished.

1. Create and compile the Hello.idl file on the client machine as indicated in the tutorial:

idlj -fall Hello.idl

2. Create HelloClient.java on the client machine. Compile the .java files, including the stubs
and skeletons (which are in the directory HelloApp):

javac *.java HelloApp/*.java

3. Create HelloServer.java on the server machine. Compile the .java files:

javac *.java

4. Start the Java IDL name server on the server machine. To do this on Unix:

tnameserv -ORBInitialPort 1050&

To do this on Windows:

start tnameserv -ORBInitialPort 1050

Note that the name server will run on port 1050 if you enter the command as listed. If you
want a different nameserverport, replace 1050 with the correct port number.

5. On the server machine, start the Hello server, as follows:

java HelloServer -ORBInitialPort 1050

If you used a different nameserverport, replace 1050 with the correct port number.

6. On the client machine, run the Hello application client. From a DOS prompt or shell, type:

java HelloClient -ORBInitialHost namerserverhost -ORBInitialPort 1050

Note that nameserverhost is the host on which the IDL name server is running. In this
case, it is the server machine.

If you used a different nameserverport, replace 1050 with the correct port number.

7. Kill or stop the server process when finished.

10. Hello World with Persistent State

This document has not been updated for J2SE 1.3

Java IDL only supports transient objects - if an object's server process halts and restarts, the object
reference becomes invalid. However, Example 2 illustrates how a transient object can store its
state and re-initialize itself from this state each time the server is restarted.

The Example 2 server hosts a Hello object that stores a string in a file. You provide the string as a
command line argument to the client program. The server Hello object "remembers" the string and

-30-
Java IDL Tutorial and Guide

returns it to the client the next time that the client is run, even if the server has been stopped and
restarted.

Example 2 is identical to Example 1 except for the persistence enhancements. This page only
discusses the code neccessary to these enhancements.

This page contains:

• The IDL for the persistent "Hello World" program


• A transient server that creates an object, registers it in a naming context, and saves its
state in a file.
• An application client.

Instructions for compiling and running the example are provided.

Interface Definition (Hello.idl)

module HelloApp
{

interface Hello
{
exception cantWriteFile{};
exception cantReadFile{};

string sayHello(in string message)


raises (cantWriteFile);

string lastMessage()
raises (cantReadFile);
};
};

• Because the Hello object reads from and writes to a file, you will need to throw Java language
exceptions. (See Implementing the Server below). The Hello interface must define and raise
exceptions in order to generate the appropriate skeleton definitions.

• The sayHello method has been modified to take a string argument, which will be stored in a file
at runtime. A lastMessage method has been added to return this stored string to the client.

• The IDL compiler generates a directory HelloApp/HelloPackage that contains the following
exception class files:
cantReadFile.java
cantReadFileHelper.java
cantReadFileHolder.java
cantWriteFile.java
cantWriteFileHelper.java
cantWriteFileHolder.java

Use of these classes is illustrated in the implementation below.

Implementing the Server (HelloServer.java)

// Copyright and License

import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

-31-
Java IDL Tutorial and Guide

import java.io.*;

class HelloServant extends _HelloImplBase


{
public String sayHello(String msg)
throws HelloApp.HelloPackage.cantWriteFile
{
try {
synchronized(this) {
File helloFile = new File("helloStorage.txt");
FileOutputStream fos = new FileOutputStream(helloFile);
byte[] buf = new byte[msg.length()];
msg.getBytes(0, msg.length(), buf, 0);
fos.write(buf);
fos.close();
}
} catch(Exception e) {
throw new HelloApp.HelloPackage.cantWriteFile();
}
return "\nHello world !!\n";
}

public String lastMessage()


throws HelloApp.HelloPackage.cantReadFile
{
try {
synchronized(this) {
File helloFile = new File("helloStorage.txt");
FileInputStream fis = new FileInputStream(helloFile);
byte[] buf = new byte[1000];
int n = fis.read(buf);
String lastmsg = new String(buf);
fis.close();
return lastmsg;
}
} catch(Exception e) {
throw new HelloApp.HelloPackage.cantReadFile();
}
}
}

public class HelloServer {

public static void main(String args[])


{
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);

// create 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


NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
ncRef.rebind(path, helloRef);

-32-
Java IDL Tutorial and Guide

// 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);
}
}
}

• The sayHello and lastMessage method implementations throw the exceptions defined in the
IDL file. These methods must throw file IO exceptions or the Java language compiler issues
warnings and errors.

• The HelloServant object receives ansychronous and possibly simultaneous method requests at
runtime. Therefore, you should enclose all file IO code in a synchronized clause.

• No changes are required to HelloServer.main.

Implementing the Client (HelloClient.java)

// Copyright and License

import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.io.*;

public class HelloClient


{
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");
NamingContext ncRef = NamingContextHelper.narrow(objRef);

// resolve the Object Reference in Naming


NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

// call the Hello server object and print results

String oldhello = helloRef.lastMessage();


System.out.println(oldhello);
String hello = helloRef.sayHello(args[0]);
System.out.println(hello);

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

-33-
Java IDL Tutorial and Guide

• This client retrieves the stored message via lastMessage and stores the new message via an
argument to sayHello.

Building and Running Hello World

The following instructions assume you can use port 1050 for the Java IDL name server. Substitute
a different port if necessary. Note that for ports below 1024, you need root access on UNIX
machines, and administrator privileges on Windows95 and NT. Note also that the instructions use
a slash (/) for path names. Windows95 and NT users should subtitute a backslash (\).

• Create source files as shown above.

• Run idlj on the IDL file to create stubs and skeletons:

idltojava -fall Hello.idl

• Compile the .java files, including the stubs and skeletons:

javac *.java HelloApp/*.java

• Make sure the name server is running:

tnameserv -ORBInitialPort 1050&

• Start the Hello server:

java HelloServer -ORBInitialPort 1050

• Run the Hello application client from a different shell than the server:

java HelloClient "remember this message" -ORBInitialPort 1050

11. Hello World with Callback Object

Client programs often react to changes or updates that occur in a server. For example, a client
graph or spreadsheet program might need to be updated with each stock price update on a stock
market server. The client has two options in this scenario: (1) periodically ask for the stock price
via a method request on the stock server or (2) ask to be notified by the server whenever a price
change occurs. The second option is referred to as a "callback".

Example 3 illustrates how a client program can pass a callback object to a server. The server then
issues a method request on the callback object and thereby notifies the client.

Example 3 is identical to Example 1 except for the callback enhancements. This page only
discusses the code necessary to these enhancements.

This page contains:

• The IDL for a "Hello world" program with a callback.


• A server implementation that callsback to a client.
• A client that sends a callback object reference to a server.

Instructions for compiling and running the example are provided.

-34-
Java IDL Tutorial and Guide

Interface Definition (Hello.idl)

module HelloApp
{
interface HelloCallback
{
void callback(in string message);
};

interface Hello
{
string sayHello(in HelloCallback objRef, in string message);
};
};

• A HelloCallback is defined, which the client will implement.

• The sayHello method is modified to take an object reference argument and string argument.
The object reference argument provides a means for the client to pass a callback object to the
server, which the server can invoke. The string argument is the string that the server will send
back to the client.

Implementing the Server (HelloServer.java)

// Copyright and License

import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

class HelloServant extends _HelloImplBase


{
public String sayHello(HelloCallback callobj, String msg)
{
callobj.callback(msg);
return "\nHello world !!\n";
}
}

public class HelloServer {

public static void main(String args[])


{
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);

// create 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


NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};

-35-
Java IDL Tutorial and Guide

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);
}
}
}

• The sayHello method implementation has been modified to invoke the callback object that it
receives.

Implementing the Client (HelloClient.java)

// Copyright and License

import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;

class HelloCallbackServant extends _HelloCallbackImplBase


{
public void callback(String notification)
{
System.out.println(notification);
}
}

public class HelloClient


{
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");
NamingContext ncRef = NamingContextHelper.narrow(objRef);

// resolve the Object Reference in Naming


NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

HelloCallbackServant helloCallbackRef = new HelloCallbackServant();


orb.connect(helloCallbackRef);

// call the Hello server object and print results


String hello = helloRef.sayHello(helloCallbackRef,"\ntest..\n");
System.out.println(hello);

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

-36-
Java IDL Tutorial and Guide

}
}
}

• The client implements the HelloCallbackServant object.

• The HelloClient.main instantiates the callback object and passes it to the server. The client
must also register the callback object with the ORB.

Building and Running Hello World

The following instructions assume you can use port 1050 for the Java IDL name server. Substitute
a different port if necessary. Note that for ports below 1024, you need root access on UNIX
machines, and administrator privileges on Windows95 and NT. Note also that the instructions use
a slash (/) for path names. Windows95 and NT users should subtitute a backslash (\).

• Create the source code files as shown above.

• Run idlj on the IDL file to create stubs and skeletons:

idlj -fall Hello.idl

• Compile the .java files, including the stubs and skeletons:

javac *.java HelloApp/*.java

• Make sure the name server is running:

tnameserv -ORBInitialPort 1050&

• Start the Hello server:

java HelloServer -ORBInitialPort 1050

• Run the Hello application client from a different shell than the server:

java HelloClient -ORBInitialPort 1050

12. Hello World with Implementation Inheritance

Ordinarily, servant classes must inherit from the ImplBase class generated by the idlj compiler.
This is inadequate for servant classes that need to inherit functionality from another Java class.
The Java programming language allows a class only one superclass and the generated ImplBase
class occupies this position.

Example 4 illustrates how a servant class can inherit (an implementation) from any Java class. In
this example, the HelloServant class inherits its entire implementation from another Java class
HelloBasic. At runtime, method requests for HelloServant are delegated to another idlj-
generated class.

Example 4 is identical to Example 1 except for implementation inheritance enhancements. This


page only discusses the code necessary for these enhancements.

This section contains:

-37-
Java IDL Tutorial and Guide

• The IDL for a simple "Hello World" program


• A server implementation that delegates method requests for HelloServant to another
Java class.
• A client program.

Instructions for compiling and running the example are provided.

Interface Definition (Hello.idl)

module HelloApp
{
interface Hello
{
string sayHello();
};
};

Compile the IDL interface with the command:

idlj -fall Hello.idl

The files generated by this command are discussed in the basic tutorial.

Then use the compiler again to generate the Tie bindings:

idlj -fallTIE Hello.idl


The second command generates an additional file in a HelloApp subdirectory:
Hello_Tie.java
This class acts as the skeleton, receiving invocations from the ORB and delegating them to
the servant that actually does the work.

Implementing the Server (HelloServer.java)

// Copyright and License

import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;

class HelloBasic
{
public String sayHello()
{
return "\nHello world !!\n";
}
}

class HelloServant extends HelloBasic implements HelloOperations


{
}

public class HelloServer {

public static void main(String args[])


{
try{
// create and initialize the ORB

-38-
Java IDL Tutorial and Guide

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

// create servant and register it with the ORB


HelloServant servant = new HelloServant();
Hello helloRef = new Hello_Tie(servant);
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


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);
}
}
}

Implementing the Client (HelloClient.java)

// Copyright and License

import HelloApp.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;

public class HelloClient


{
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");
NamingContext ncRef = NamingContextHelper.narrow(objRef);

// resolve the Object Reference in Naming


NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
Hello helloRef = HelloHelper.narrow(ncRef.resolve(path));

// call the Hello server object and print results


String hello = helloRef.sayHello();
System.out.println(hello);

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

-39-
Java IDL Tutorial and Guide

e.printStackTrace(System.out);
}
}
}

Building and Running Hello World

The following instructions assume you can use port 1050 for the Java IDL name server. Substitute
a different port if necessary. Note that for ports below 1024, you need root access on UNIX
machines, and administrator privileges on Windows95 and NT. Note also that the instructions use
a slash (/) for path names. Windows95 and NT users should subtitute a backslash (\).

• Create source code files as shown above.

• Run idlj on the IDL file to create stubs and skeletons:

idlj -fall Hello.idl

Then run the idlj compiler again to generate the Tie classes:

idlj -fallTIE Hello.idl

• Compile the .java files, including the stubs and skeletons:

javac *.java HelloApp/*.java

• Make sure the name server is running:

tnameserv -ORBInitialPort 1050&

• Start the Hello server:

java HelloServer -ORBInitialPort 1050

• Run the Hello application client from a different shell than the server:

java HelloClient -ORBInitialPort 1050

13. Exceptions

CORBA has two types of exceptions: standard system exceptions which are fully specified by the
OMG and user exceptions which are defined by the individual application programmer. CORBA
exceptions are a little different from Java exception objects, but those differences are largely
handled in the mapping from IDL to Java.

Topics in this section include:

• Differences Between CORBA and Java Exceptions


• System Exceptions
o System Exception Structure
o Minor Codes
o Completion Status
• User Exceptions
• Minor Code Meanings

-40-
Java IDL Tutorial and Guide

Differences Between CORBA and Java Exceptions

To specify an exception in IDL, the interface designer uses the raises keyword. This is similar to
the throws specification in Java. When you use the exception keyword in IDL you create a user-
defined exception. The standard system exceptions need not (and cannot) be specified this way.

System Exceptions

CORBA defines a set of standard system exceptions, which are generally raised by the ORB
libraries to signal systemic error conditions like:

• Server-side system exceptions, such as resource exhaustion or activation failure.


• Communication system exceptions, for example, losing contact with the object, host down,
or cannot talk to ORB daemon (orbd).
• Client-side system exceptions, such as invalid operand type or anything that occurs before
a request is sent or after the result comes back.

All IDL operations can throw system exceptions when invoked. The interface designer need not
specify anything to enable operations in the interface to throw system exceptions -- the capability
is automatic.

This makes sense because no matter how trivial an operation's implementation is, the potential of
an operation invocation coming from a client that is in another process, and perhaps (likely) on
another machine, means that a whole range of errors is possible.

Therefore, a CORBA client should always catch CORBA system exceptions. Moreover, developers
cannot rely on the Java compiler to notify them of a system exception they should catch, because
CORBA system exceptions are descendants of java.lang.RuntimeException.

System Exception Structure

All CORBA system exceptions have the same structure:

exception <SystemExceptionName> { // descriptive of error


unsigned long minor; // more detail about error
CompletionStatus completed; // yes, no, maybe
}

System exceptions are subtypes of java.lang.RuntimeException through


org.omg.CORBA.SystemException:

java.lang.Exception
|
+--java.lang.RuntimeException
|
+--org.omg.CORBA.SystemException
|
+--BAD_PARAM
|
+--//etc.

Minor Codes

All CORBA system exceptions have a minor code field, a number that provides additional
information about the nature of the failure that caused the exception. Minor code meanings are not

-41-
Java IDL Tutorial and Guide

specified by the OMG; each ORB vendor specifies appropriate minor codes for that
implementation. For the meaning of minor codes thrown by the Java ORB, see Minor code
meanings .

Completion Status

All CORBA system exceptions have a completion status field, indicating the status of the operation
that threw the exception. The completion codes are:

COMPLETED_YES
The object implementation has completed processing prior to the exception being raised.
COMPLETED_NO
The object implementation was not invoked prior to the exception being raised.
COMPLETED_MAYBE
The status of the invocation is unknown.

User Exceptions

CORBA user exceptions are subtypes of java.lang.Exception through


org.omg.CORBA.UserException:

java.lang.Exception
|
+--org.omg.CORBA.UserException
|
+-- Stocks.BadSymbol
|
+--//etc.

Each user-defined exception specified in IDL results in a generated Java exception class. These
exceptions are entirely defined and implemented by the programmer

Minor Code Meanings

System exceptions all have a field minor that allows CORBA vendors to provide additional
information about the cause of the exception. For a list of standard OMG minor code exceptions
(OMGVMCID), refer to the OMG document at http://cgi.omg.org/docs/omg/02-06-01.txt. If you
encounter a Sun minor code exception, email us for more information at javaidl@eng.sun.com.

14. Initialization

Before a Java program can use CORBA objects, it must initialize itself as follows:

• Create an ORB object.


• Obtain one or more initial object references, typically at least a naming context.

Topics in this section include:

• Creating an ORB Object


o Creating an ORB for an Application
o Creating an ORB for an Applet
o Arguments to ORB.init()
o System Properties
• Obtaining Initial Object References
o Stringified Object References
o Getting References from an ORB

-42-
Java IDL Tutorial and Guide

Creating an ORB Object

Before it can create or invoke a CORBA object, an applet or application must first create an ORB
object. Doing so introduces the applet or application to the ORB and obtains access to important
operations that are defined on the ORB object.

Applets and applications create ORB instances slightly differently, because their parameters,
which must be passed in the ORB.init() call, are arranged differently.

Creating an ORB for an Application

This fragment shows how an application might create an ORB:

import org.omg.CORBA.ORB;

public static void main(String args[])


{
try{
ORB orb = ORB.init(args, null);
// code continues

Creating an ORB for an Applet

An applet creates an ORB like this:

import org.omg.CORBA.ORB;

public void init() {


try {
ORB orb = ORB.init(this, null);
// code continues

Some web browsers have an ORB built directly into them. This can cause problems if that ORB is
not perfectly compliant. In this case, special steps must be taken to initialize the Java IDL ORB
specifically. For example, because of missing classes in the installed ORB in Netscape
Communicator 4.01, an applet displayed in that browser must contain code similar to the following
in its init() method:

import java.util.Properties;
import org.omg.CORBA.*;

public class MyApplet extends java.applet.Applet {


public void init()
{
// Instantiate the Java IDL ORB, passing in this applet
// so that the ORB can retrieve the applet properties.
Properties props = new Properties();
props.put("org.omg.CORBA.ORBClass", "com.sun.CORBA.iiop.ORB");
ORB orb = ORB.init(this, props);
...
}
}

Arguments to ORB.init()

For both applications and applets, the arguments for the initialization method are:

-43-
Java IDL Tutorial and Guide

args or this
Provides the ORB access to the application's arguments or applet's parameters.
null
A java.util.Properties object.

The init() operation uses these parameters, as well as the system properties, to obtain
information it needs to configure the ORB. It searches for ORB configuration properties in the
following places and order:

1. The application or applet parameters (first argument)


2. A java.util.Properties object (second argument), if one has been supplied
3. The java.util.Properties object returned by System.getProperties()

The first value found for a particular property is the value the init() operation uses. If a
configuration property cannot be found in any of these places, the init() operation assumes an
implementation-specific value for it. For maximum portability among ORB implementations,
applets and applications should explicitly specify configuration property values that affect their
operation, rather than relying on the assumptions of the ORB they happen to be running in.

System Properties

With respect to the system Properties object, note that Sun's Java virtual machine* adds -D
command line arguments to it. Other Java virtual machines may or may not do the same.

Currently, the following configuration properties are defined for all ORB implementations:

org.omg.CORBA.ORBClass
The name of a Java class that implements the org.omg.CORBA.ORB interface. Applets and
applications do not need to supply this property unless they must have a particular ORB
implementation. The value for the Java IDL ORB is com.sun.CORBA.iiop.ORB.
org.omg.CORBA.ORBSingletonClass
The name of a Java class that implements the org.omg.CORBA.ORB interface. This is the
object returned by a call to orb.init() with no arguments. It is used primarily to create
typecode instances than can be shared across untrusted code (such as unsigned applets) in
a secured environment.

In addition to the standard properties listed above, Java IDL also supports the following
properties:

org.omg.CORBA.ORBInitialHost
The host name of a machine running a server or daemon that provides initial bootstrap
services, such as a name service. The default value for this property is localhost for
applications. For applets it is the applet host, equivalent to getCodeBase().getHost().
org.omg.CORBA.ORBInitialPort
The port the initial naming service listens to. The default value is 900.

Note: When specifying a property as a command-line argument to a Java IDL application, omit
the org.omg.CORBA. portion of the property name. For example, a command line that starts an
application looks like this:
-ORBInitialPort 800

Applet parameters should specify the full property names. The conventions for applications differ
from applets so as not to expose language-specific details in command-line invocations.

-44-
Java IDL Tutorial and Guide

Obtaining Initial Object References

To invoke a CORBA object, an applet or application must have a reference for it. There are three
ways to get a reference for a CORBA object:

• From a string that was specially created from an object reference


• From another object, such as a naming context
• From the ORB operation resolve_initial_references()

Stringified Object References

The first technique, converting a stringified reference to an actual object reference, is ORB-
implementation independent. No matter what Java ORB an applet or application runs on, it can
convert a stringified object reference. However, it is up to the applet or application developer to:

• Ensure that the object referred to is in fact accessible from where the applet or application
is running.
• Obtain the stringified reference, perhaps from a file or a parameter.

The following fragment shows how a server converts a CORBA object reference to a string:

org.omg.CORBA.ORB orb = // get an ORB object


org.omg.CORBA.Object obj = // create the object reference
String str = orb.object_to_string(obj);
// make the string available to the client

This code fragment shows how a client converts the stringified object reference back to an object:

org.omg.CORBA.ORB orb = // get an ORB object


String stringifiedref = // read string
org.omg.CORBA.Object obj = orb.string_to_object(stringifiedref);

Getting References from an ORB

If you don't use a stringified reference to get an initial CORBA object, you use the ORB itself to
produce an initial object reference. However, doing so may make your applet or application ORB-
dependent, because, although the CORBA specification defines the interface for getting initial
object references, it doesn't yet provide enough information for ORB vendors to implement it in a
standard way. Applet and application developers should therefore be cautious when using this
operation until the standard is more tightly specified. To guarantee ORB-implementation-
independence, use the stringified object reference technique instead.

The ORB interface defines an operation called resolve_initial_references() that is intended


for bootstrapping object references into a newly started application or applet. The operation takes
a string argument that names one of a few recognized objects; it returns a CORBA Object, which
must be narrowed to the type the applet or application knows it to be. Two string values are
presently defined:

NameService
Passing this value returns a reference to a root naming context which, after narrowing, can
be used to look up references for objects whose names are known to the applet or
application (assuming those objects are registered by those names in the root or
subordinate naming contexts).
InterfaceRepository
This value returns a reference to an interface repository, a CORBA object that contains
interface definitions. The current release of Java IDL does not include an implementation

-45-
Java IDL Tutorial and Guide

of the interface repository. If you are using another server-side orb, you can still use
"InterfaceRepository" as the argument to resolve_initial_references().

The Java IDL implementation of resolve_initial_references() requires an already-running


naming service whose host and port are identified by the ORBInitialHost and ORBInitialPort
properties described previously, or by their default values. See Naming Service for details on
starting the Java IDL name server.

*As used on this web site, the terms "Java Virtual Machine" or "JVM" mean a virtual machine
for the Java platform.

15. Naming Service

Topics in this section include:

• Java IDL Naming Service


• Starting the Java IDL Naming Service
• Stopping the Java IDL Naming Service
• Sample Client: Adding Objects to the Namespace
• Sample Client: Browsing the Namespace

Java IDL Naming Service

The CORBA COS (Common Object Services) Naming Service provides a tree-like directory for
object references much like a filesystem provides a directory structure for files. The Naming
Service provided with Java IDL is a simple implementation of the COS Naming Service
specification.

Object references are stored in the namespace by name and each object reference-name pair is
called a name binding. Name bindings may be organized under naming contexts. Naming contexts
are themselves name bindings and serve the same organizational function as a file system
subdirectory. All bindings are stored under the initial naming context. The initial naming context
is the only persistent binding in the namespace; the rest of the namespace is lost if the Java IDL
naming service process halts and restarts.

For an applet or application to use COS naming, its ORB must know the port of a host running a
naming service or have access to a stringified initial naming context for that naming service. The
naming service can either be the Java IDL naming service or another COS-compliant naming
service.

Starting the Java IDL Naming Service

You must start the Java IDL naming service before an application or applet that uses its naming
service. Installation of the Java IDL product creates a script (Solaris: tnameserv) or executable file
(Windows NT: tnameserv.exe) that starts the Java IDL naming service. Start the naming service
so it runs in the background.

If you do not specify otherwise, the Java IDL naming service listens on port 900 for the bootstrap
protocol used to implement the ORB resolve_initial_references() and
list_initial_references() methods, as follows:

tnameserv -ORBInitialPort nameserverport

If you do not specify the name server port, port 900 is used by default. When running Solaris
software, you must become root to start a process on a port under 1024. For this reason, we

-46-
Java IDL Tutorial and Guide

recommend that you use a port number greater than or equal to 1024. To specify a different port,
for example, 1050, from a UNIX command shell, enter:

tnameserv -ORBInitialPort 1050

From an MS-DOS system prompt (Windows), enter:

start tnameserv -ORBInitialPort nameserverport

Clients of the name server must be made aware of the new port number. Do this by setting the
org.omg.CORBA.ORBInitialPort property to the new port number when creating the ORB object.

The -J option

This command-line option is available for use with tnameserve.


-Joption
Pass option to the Java virtual machine, where option is one of the options described on the
reference page for the java application launcher. For example, -J-Xms48m sets the startup
memory to 48 megabytes. It is a common convention for -J to pass options to the underlying
virtual machine.

Stopping the Java IDL Naming Service

To stop the Java IDL naming service, use the relevant operating system command, such as kill.
Note that names registered with the Java IDL naming service disappear when the service is
terminated.

Sample Client: Adding Objects to the Namespace

The following sample program illustrates how to add names to the namespace. It is a self-
contained Naming Service client that creates the following simple tree.

In this example, plans is an object reference and Personal is a naming context that contains two
object references: calendar and schedule.

import java.util.Properties;
import org.omg.CORBA.*;
import org.omg.CosNaming.*;

public class NameClient


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

-47-
Java IDL Tutorial and Guide

In the above section, Starting the Java IDL Naming Service, the nameserver was started on port
1050. The following code ensures that the client program is aware of this port number.

Properties props = new Properties();


props.put("org.omg.CORBA.ORBInitialPort", "1050");
ORB orb = ORB.init(args, props);

This code obtains the initial naming context and assigns it to ctx. The second line copies ctx into a
dummy object reference objref that we'll attach to various names and add into the namespace.

NamingContext ctx =
NamingContextHelper.narrow(orb.resolve_initial_references(
"NameService"));
NamingContext objref = ctx;

This code creates a name "plans" of type "text" and binds it to our dummy object reference. "plans"
is then added under the initial naming context using rebind. The rebind method allows us to run
this program over and over again without getting the exceptions we'd get from using bind.

NameComponent nc1 = new NameComponent("plans", "text");


NameComponent[] name1 = {nc1};
ctx.rebind(name1, objref);
System.out.println("plans rebind sucessful!");

This code creates a naming context called "Personal" of type "directory". The resulting object
reference, ctx2, is bound to the name and added under the initial naming context.

NameComponent nc2 = new NameComponent("Personal", "directory");


NameComponent[] name2 = {nc2};
NamingContext ctx2 = ctx.bind_new_context(name2);
System.out.println("new naming context added..");

The remainder of the code binds the dummy object reference using the names "schedule" and
"calendar" under the "Personal" naming context (ctx2).

NameComponent nc3 = new NameComponent("schedule", "text");


NameComponent[] name3 = {nc3};
ctx2.rebind(name3, objref);
System.out.println("schedule rebind sucessful!");

NameComponent nc4 = new NameComponent("calender", "text");


NameComponent[] name4 = {nc4};
ctx2.rebind(name4, objref);
System.out.println("calender rebind sucessful!");

} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}

Sample Client: Browsing the Namespace

The following sample program illustrates how to browse the namespace.

import java.util.Properties;
import org.omg.CORBA.*;
import org.omg.CosNaming.*;

public class NameClientList

-48-
Java IDL Tutorial and Guide

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

In the above section, Starting the Java IDL Naming Service, the nameserver was started on port
1050. The following code ensures that the client program is aware of this port number.

Properties props = new Properties();


props.put("org.omg.CORBA.ORBInitialPort", "1050");
ORB orb = ORB.init(args, props);

The following code obtains the intial naming context.


NamingContext nc =
NamingContextHelper.narrow(orb.resolve_initial_references(
"NameService"));

The list method lists the bindings in the naming context. In this case, up to 1000 bindings from
the initial naming context will be returned in the BindingListHolder; any remaining bindings are
returned in the BindingIteratorHolder.

BindingListHolder bl = new BindingListHolder();


BindingIteratorHolder blIt= new BindingIteratorHolder();
nc.list(1000, bl, blIt);

This code gets the array of bindings out of the returned BindingListHolder. If there are no
bindings, the program ends.
Binding bindings[] = bl.value;
if (bindings.length == 0) return;

The remainder of the code loops through the bindings and prints the names out.
for (int i=0; i < bindings.length; i++) {

// get the object reference for each binding


org.omg.CORBA.Object obj = nc.resolve(bindings[i].binding_name);
String objStr = orb.object_to_string(obj);
int lastIx = bindings[i].binding_name.length-1;

// check to see if this is a naming context


if (bindings[i].binding_type == BindingType.ncontext) {
System.out.println( "Context: " +
bindings[i].binding_name[lastIx].id);
} else {
System.out.println("Object: " +
bindings[i].binding_name[lastIx].id);
}
}

} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}

16. The Dynamic Skeleton Interface (DSI)

The Dynamic Skeleton Interface (DSI) allows servers to serve a servant object without prior
(compile time) knowledge of the object's interface. Insead of using skeleton code compiled from the
IDL interface definition, the server constructs an operation invocation dynamically.

-49-
Java IDL Tutorial and Guide

Why Use DSI?

DSI can be used to bridge CORBA with non-CORBA environments. Such a bridge would allow
CORBA clients to invoke methods on CORBA objects that are implemented as, for example, COM
services.

The dynamic servant is implemented to convert the CORBA client request to a format understood
by the COM server. You must write all the code to perform this work. Contrast this with a typical
static object invocation. The server has access to the compiled skeletons for the interface being
invoked. These skeletons are generated by compiling the IDL interface definitions with the idlj
compiler. When the ORB receives a request, it uses the skeleton code to build operation arguments
on the server side and to send back any result.

Dynamic Servant Implementation Example

Consider the following interface:

module HelloApp
{
interface Hello
{
string printHelloArgs(in string arg1, in short arg2);
};
};

The following code is a shell implementation of a dynamic servant for the above interface. It is a
shell because only the basic compilable infrastructure for parsing method requests is provided. You
would need to insert code to implement a bridge.

// Copyright and License

import HelloApp.*;

import java.util.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import java.io.*;
import org.omg.CORBA.*;

// servant must extend DynamicImplementation


class HelloServant extends DynamicImplementation
{

// store the repository ID for the implemented interface

-50-
Java IDL Tutorial and Guide

static String[] myIDs = {"IDL:JavaIDL/DSIExample:1.0"};


ORB orb;

// create a reference to the ORB


HelloServant(ORB orb) {
this.orb = orb;
}
// must implement invoke() for handling requests
public void invoke(ServerRequest request) {
try {
System.out.println("DSI: invoke called, op = "+request.op_name());

// create an NVList to hold the parameters


NVList nvlist = orb.create_list(0);

// need an if statement like this for each method name


if (request.op_name().equals("printHelloArgs") == true) {

// need an Any for each argument


Any any1 = orb.create_any();
any1.insert_string("");
nvlist.add_value("arg1", any1, ARG_IN.value);

Any any2 = orb.create_any();


any2.insert_string("");
nvlist.add_value("arg2", any2, ARG_IN.value);

// pass the NVList to the request to get values


request.params(nvlist);

System.err.println("Argument 1: In value: " +


nvlist.item(0).value().extract_string());

System.err.println("Argument 2: In value: " +


nvlist.item(1).value().extract_short());

TypeCode result_tc = orb.get_primitive_tc(TCKind.tk_void);


Any result_any = orb.create_any();
result_any.type(result_tc);

request.result(result_any);
}
}
catch (Exception ex) {
ex.printStackTrace();
System.out.println("DSIExample: Exception thrown: " + ex);
}
}

// implement an _ids method to return repository ID of interface


public String[] _ids() {
return myIDs;
}

// HelloServer implemented in the usual fashion


public class HelloServer {

public static void main(String args[])


{
try{
// create and initialize the ORB
ORB orb = ORB.init(args, null);

// create servant and register it with the ORB

-51-
Java IDL Tutorial and Guide

HelloServant helloRef = new HelloServant(orb);


orb.connect(helloRef);

OutputStream f = new
FileOutputStream(System.getProperty("user.home") +
System.getProperty("file.separator") + "DSI.ior");
DataOutputStream out = new DataOutputStream(f);
String ior = orb.object_to_string(helloRef);
out.writeBytes(ior);
out.close();

System.out.println("IOR is "+ ior);

// 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);
}
}
}

17. IDL to Java Language Mapping

This release of the JavaTM 2 Platform, Standard Edition, v.1.3, includes idlj, a compiler that reads
an Object Management Group (OMG) Interface Definition Language (IDL) file and translates it, or
maps it, to a Java interface. The idlj compiler also creates stub, skeleton, helper, holder, and
other files as necessary. These .java files are generated from the IDL file according to the
mapping specified in the OMG document (pdf format) OMG IDL to Java Language Mapping
Specification, formal, 99-07-53. The postscript version of this specification can be found at
http://www.omg.org/technology/documents/formal/omg_idl_to_java_language_mapping.htm.
Formal specification 99-07-53 of the IDL to Java language mapping is aligned with CORBA version
2.3. For a basic summary of the IDL to Java mapping, see IDL to Java Language Mapping
Overview below.

Some topics from the OMG IDL to Java Language Mapping specification that are not easily
summarized are:

• Section 1.19, Mapping Pseudo-Objects to Java


• Section 1.20, Server-Side Mapping
• Section 1.21, Java ORB Portability Interfaces

IDL to Java Language Mapping Overview

CORBA objects are defined in OMG IDL (Object Management Group Interface Definition
Language). J2SE v1.3 includes idlj, the IDL-to-Java compiler that maps the IDL-defined
interfaces to Java classes and interfaces.

This overview shows the correspondence between OMG IDL constructs and Java constructs. Note
that OMG IDL, as its name implies, defines interfaces. Like Java interfaces, IDL interfaces
contain no implementations for their operations (methods in Java). In other words, IDL interfaces
define only the signature for an operation (the name of the operation, the data type of its return
value, the data types of the parameters that it takes, and any exceptions that it raises). The
implementations for these operations need to be supplied in Java classes written by a Java
programmer.

-52-
Java IDL Tutorial and Guide

The following table lists the main constructs of IDL and the corresponding constructs in Java.

IDL Construct Java Construct

module package

signature interface and an operations interface, helper class,


interface (non-abstract)
holder class

interface (abstract) signature interface, helper class, holder class

constant (not within an


public interface
interface)

boolean boolean

char, wchar char

octet byte

string, wstring java.lang.String

short, unsigned short short

long, unsigned long int

long long, unsigned long long long

float float

double double

fixed java.math.BigDecimal

enum, struct, union class

sequence, array array

exception class

readonly attribute accessor method

readwrite attribute accessor and modifer methods

operation method

Note: When a CORBA operation takes a type that corresponds to a Java object type (a String, for
example), it is illegal to pass a Java null as the parameter value. Instead, pass an empty version of
the designated object type (for example, an empty String or an empty array). A Java null can be
passed as a parameter only when the type of the parameter is a CORBA object reference or value
type, in which case the null is interpreted as a nil CORBA object reference.

-53-

You might also like