Developing Clients


Topics in this section include:

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

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:

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 idltojava 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:

Here's a simple example from the point of view of a client.

OMG IDL

Generated Java

module Example {
   interface Counter {
      boolean increment (in long arg);
   };
};
package Example;
public interface Counter 
   extends org.omg.CORBA.Object {
   public boolean increment (int arg);
}
 
public class CounterHelper {
   public static Counter narrow
      (org.omg.CORBA.Object obj);
   // ... 
} 
 
public final class CounterHolder {
   // ... 
}

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 reference to learn the identity of the object's servant.
  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.