# Developing Clients

Topics in this section include:

- ORBs and Invocations
- Static Invocation
- Dynamic Invocation
- Initializing Applets

## ORBs and Invocations

For a client to invoke a CORBA object operation, both the client and the server (the object implementation) must use a CORBA software component called an ORB (object request broker). ORBs are the common denominators that bridge the differences in location, platform, and programming language that can separate a client and a server. ORBs can contact each other across the network, can create and interpret object references (CORBA object handles), and can marshal parameters into and out of the format used by IIOP. In addition to enabling client/server communication, ORBs provide other services, but they are not described here.

The two ways to invoke an operation on a CORBA object are:

- Static invocation, which is used most often and most resembles conventional Java programming, is type-checked by the compiler. But it can only be used for objects whose interface definitions exist when the invoking client is compiled.

- Dynamic invocation is more flexible because clients can invoke objects they discover at runtime. However, compile-time type-checking is impossible with dynamic invocation. Although it's possible to type-check parameters at runtime, doing so requires a CORBA Interface Repository, which the current release of Java IDL does not provide.

## Static Invocation

To make a static invocation on a CORBA object, a Java client needs an object reference to the servant that performs the operation. The object reference has two important functions:

- It uniquely identifies the servant, wherever it is located.

- It implements the client stub interface, making the reference a local proxy for the servant object.

Clients don't create object references but obtain them, typically from other objects such as factories or naming contexts.

OMG IDL is the language in which CORBA object interfaces are defined. For each OMG IDL module, the `idlj` compiler generates a Java package. For each interface `Foo` defined in an OMG IDL module, the generated package contains the following items of interest to the client programmer:

- A Java signature interface `Foo`, which extends `org.omg.portable.IDLEntity`, `org.omg.CORBA.Object`, and the operations interface. The signature interface is used as the signature type in method declarations when interfaces of the specified type are used in other interfaces. From the client's point of view, an object reference for a CORBA `Foo` object implements this interface.

  Note: The Stub implements the `Foo` interface, where it generates code for each method to marshall the arguments, invoke the method, and then unmarshall the arguments.

- A Java operations interface `FooOperations`, which is used in the server-side mapping and as a mechanism for providing optimized calls for co-located clients and server. The server developer provides implementation for the methods indicated by the operations interface.

- A Java class `FooHelper`, that defines auxiliary methods, notably `narrow()`, which is the CORBA counterpart of Java casting.

- A Java class called `FooHolder`, that holds a public `Foo` member. Holders are required for CORBA operations that take `out` or `inout` arguments, which, unlike CORBA `in` arguments, don't map directly to Java's pass-by-value semantics.

Here's a simple example from the point of view of a client. The full text of the generated files can be viewed from Sample Code for Example.idl.

OMG IDL | Generated Java
--- | ---
    module Example {
       interface Counter {
          boolean increment (in long arg);
       };
    };

    package Example;

    public interface Counter extends CounterOperations, org.omg.CORBA.Object,
       org.omg.CORBA.portable.IDLEntity
    {
    } // interface Counter

    package Example;

    public interface CounterOperations
    {
      boolean increment (int arg);
    } // interface CounterOperations

    package Example;

    abstract public class CounterHelper
    {
      private static String  _id = "IDL:Example/Counter:1.0";

      public static Example.Counter narrow (org.omg.CORBA.Object obj)
      {
       // ...
    }

    package Example;

    public final class CounterHolder implements
       org.omg.CORBA.portable.Streamable
    {
       // ...
    }

The following Java fragment shows the essentials of declaring and invoking an instance of this CORBA object:

>     import Example.*     // get the interface and helper

>     Counter anInstance = // acquire a reference

>     boolean aResult;
>     int anArg = 10;

>     aResult = anInstance.increment(anArg);

A stub adapts a client to its underlying ORB for a particular CORBA object type. The ORB knows how to marshal an argument, but not which arguments need marshaling for a particular method. The stub, being type-specific, knows which arguments need marshaling for each method. When a client invokes a stub method, the stub tells the client's ORB what to marshal, and then tells the ORB to invoke the CORBA object identified by the object reference. The client's ORB uses the object reference to determine which remote ORB should receive the invocation, passes the marshaled parameters over the network to that ORB, and waits for the result. (For those familiar with remote procedure calls, CORBA object invocation is similar.)

A skeleton is an object server's analog of the client's stub. Skeletons are also generated by IDL compilers. When an ORB receives an invocation for one of its objects, processing is as follows:

1. The ORB inspects the object key from the incoming message to learn the identity of the object's servant. Actually, the object reference contains the object key, and according to the IIOP protocol specified by the OMG, only the object key part of the object reference flows as part of the message.
2. The ORB then invokes the appropriate skeleton, which tells the ORB how to unmarshal the parameters.
3. The ORB invokes the servant implementation of the operation requested by the client.
4. The servant method returns a result to the skeleton.
5. The skeleton arranges marshaling with the server ORB.
6. The server ORB returns the result to the client ORB.
7. The client ORB returns the result to the stub.
8. The stub returns the result to the client.

To summarize, IIOP ORBs communicate CORBA object invocations across a network in a standardized form. All ORB operations are independent of the type of object being invoked and of the language in which the client and server are written. It's the job of the stub and the skeleton to match clients and servers to their ORBs for a particular type of CORBA object.

## Dynamic Invocation

CORBA dynamic invocation uses an object called a request to hold everything pertinent to an invocation: the object reference, the name of the operation, its parameters, and space for the result. The client builds a request object describing an operation, then calls the request's `invoke` method, which dispatches the request just as a stub would. When the invoke method returns, the result is available in the request object.

The key to dynamic invocation is the ability of requests to hold self-describing data. This facility enables a request object to represent any invocation of any operation, regardless of its parameters. Each self-describing data element has a special type known in OMG IDL as `Any`. An `Any` consists of a typecode (whose values are defined by OMG IDL) and a value; the typecode specifies the type of the value.

The following example shows the essentials of dynamic invocation. The CORBA object to be invoked has the following OMG IDL interface definition:

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

    public class CounterClient {
      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("Counter", "");
          NameComponent path[] = {nc};
          Counter counterRef = CounterHelper.narrow(ncRef.resolve(path));

          System.out.println("Object Ref: " + orb.object_to_string(counterRef));

          // Create a DII request and set the arguments and result
          org.omg.CORBA.Request r = counterRef._request("increment");
          r.set_return_type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_long));
          org.omg.CORBA.Any inc = r.add_in_arg();
          inc.insert_long(1); // increment by 1

          for (int i = 0; i < 10; i++) {
            // call the Hello server object and print results
    	r.invoke();
    	java.lang.Exception ex = r.env().exception();
            if (ex instanceof org.omg.CORBA.UnknownUserException) {
              org.omg.CORBA.UnknownUserException userEx =
    		  (org.omg.CORBA.UnknownUserException) ex;
            }

    	// extract the result
            int result;
    	result = r.return_value().extract_long();
    	System.out.println("Counter: " + result);
          }

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

## Initializing Applets

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

Clients | Servers | Exceptions | Initialization | Naming

Home | Fundamentals | Programming | References | Tutorial

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