HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Common Object Request Broker Architecture and Java are among the newest emerging technologies revolving around IP and Internet applications. The CORBA specification defines an industry-wide standard infrastructure that simplifies the integration of software systems using object-oriented techniques. CORBA separates architecture and implementation from interface specification, allowing clients and servers to be implemented in any language, on any platform.

Java is an excellent, network-savvy, object-oriented language that's well suited for implementing CORBA components. Java's object-oriented paradigm separates an object's interface from its implementation, as does CORBA. Its machine independence and wide availability allows CORBA objects to execute on any platform running a Java Virtual Machine. Today JVMs are available on many systems, from mainframes to microprocessors. This combination of CORBA and Java creates an optimal environment for implementing real-time Web-based applications requiring no client software except a browser.

CORBA Overview
CORBA's Interface Definition Language, used to define object interfaces, is where the separation between interface specification and implementation occurs. IDL is a strongly typed, declarative-only language resembling C++. IDL doesn't define object implementations, only object interfaces. An IDL compiler translates the IDL into a set of stubs and skeletons implemented in a target language such as Java. These stubs and skeletons are a set of Java interfaces and classes from which object implementations and complete applications are built.

Following is an example of IDL for the object called MyObject, which has one method called getTimeStamp.

module MyPackage {
   interface MyObject {
    string getTimeStamp();
   };
};

Running this IDL through an IDL-to-Java compiler generates the Java classes and interfaces containing stubs and skeletons in a Java package called MyPackage.

CORBA's Object Request Broker (ORB) locates objects, manages connections and communications between stubs and skeletons, and invokes object methods on behalf of the client. The stubs and skeletons perform various functions such as marshaling data and operations. The client invokes methods on remote objects via the stub interface. In turn, the server receives client requests through the skeleton. Stubs and skeletons can be implemented statically or dynamically.

The Dynamic Invocation Interface is an approach that permits clients to discover information about objects at runtime that may not exist at compile time. CORBA's Interface Repository can be queried to discover, at runtime, a remote object reference, its methods and method parameters. DII provides a greater level of flexibility than static IDL stubs. The latter, however, are simpler and offer better performance. The Dynamic Skeleton Interface is the skeleton equivalent of DII. DSI provides a runtime binding to an object that may not be known at compile time. DSI allows the server to determine a requested method's signature and implement that method at runtime. An object receiving a request doesn't know if the client request originated from a DII or a static IDL stub. Similarly, the client doesn't know if the object implementation fulfilling the request uses an IDL skeleton or DSI.

Implementing CORBA Applications
Two implementation approaches exist for building on these stubs and skeletons, the IS-A approach and the HAS-A approach. The IS-A, or ImplBase approach, builds on the stubs and skeletons using inheritance. The HAS-A, or Tie approach, builds on the stubs and skeletons using delegation. In the Tie approach the object implementation must implement the IDL interfaces. Since Java doesn't support multiple inheritance, a class using the ImplBase approach is limited to inheriting only from the stub and skeleton classes.

If the object implementation must inherit from any class other than the ImplBase class, the Tie approach must be used.

  • Java implementation of MyObject using the ImplBase approach:

    class MyObjectImp extends _MyObjectImplBase {
       public String getTimeStamp() { //
       method body }
    }

  • Java implementation of MyObject using the Tie approach:

    class MyObjectTie implements _MyObjectOperations {
       public String getTimeStamp() { //
       method body }
    }

Objects are made available through a server process that's registered with the ORB. Note that registering a server with an ORB is vendor specific. The server initializes the ORB, instantiates the CORBA objects and passes control to the ORB to handle incoming requests.
  • Server implemented in Java using ImplBase approach:

    org.omg.CORBA.ORB orb =
    org.omg.CROBA.ORB.init(args,null); //initialize the ORB

    // instantiate the CORBA object
    MyObject ObjectRef = new MyObjectImpl();

    orb.connect(ObjectRef); // pass control to the ORB

  • Server implemented in Java using Tie approach:

    org.omg.CORBA.ORB orb =
    org.omg.CROBA.ORB.init(args,null);
    //initialize the ORB

    MyObject ObjectRef =
    new _tie_MyObject(new MyObjectTie());

    orb.connect(ObjectRef); //pass control to the ORB

Clients initialize the ORB and obtain an object reference to the server by calling the bind method. Using this object reference, requests to the server can be made as if the object resided in the client's address space.

  • Client implemented in Java:

    org.omg.CORBA.ORB.init(this,null);

    // bind to server
    MyObject ObjRef =
    MyObjectHelper.bind(":MyServer","hostname");

    // executes method getTimeStamp on server
    String TheTime = ObjRef.getTimeStamp();

CORBA Callback Methods
Applications, such as real-time stock updates, inventory management and network surveillance, require clients to react in real time to changes or updates that occur in the server. Callbacks are a technique that makes it possible for the server to execute methods on the client as changes occur in the server.

Callbacks are a well-defined, easy-to-implement, effective technique for developing real-time, Web-based clients. When using callbacks, the client/server relationship is reversed. Clients wanting to receive real-time data register with the server by passing a client object reference to the server (see Figure 1). A proxy for the client's object is created in the server. This proxy serves as a handle to the client that the server uses to invoke methods on the client. Servers wishing to use callbacks with many clients need to store the client object references as a data structure, such as Java's Vector class.

Figure 1
Figure 1:

By default, when executing CORBA methods, callers block until the called method returns. When using callbacks, a deadlock situation can occur since clients may invoke server methods from within the callback method. To avoid this possible situation, callback methods should be qualified with the IDL keyword oneway. Calling objects don't block - instead, they continue immediately after invoking oneway methods. Using these methods, servers don't wait until a method completes and may continue to accept method invocations. For this reason oneway methods must have a return type of void and should not throw an exception.

The following IDL defines the interfaces for the objects MyCallback and MyObject. Clients register with a server by invoking MyObject's registerCallback and remove themselves from the server's client list by invoking MyObject's removeCallback. MyCallback declares the callback method receiveTimeStamp, which the server invokes to update the client's timestamp.

module MyPackage {
interface MyCallback {
   oneway void receiveTimeStamp(in
string servertime);
};

interface MyObject {
   string getTimeStamp();
   void registerCallback(in MyCallback obj);
   void removeCallback(in MyCallback obj);
};
};

The client initializes the ORB, binds to the server and registers by executing registerCallback with an argument of this (an instance of MyCallback).

The server uses the MyCallback object reference as a proxy to the client.

class MyClient extends _MyCallbackImplBase {
public MyClient(){
   org.omg.CORBA.ORB.init(this,null);
   MyObject ObjRef =
   MyObjectHelper.bind(":MyServer","hostname");
   ObjRef.registerCallback(this);
}
public void receiveTimeStamp(String serverTime) {
   // method body
   }
}

The server's registerCallback method receives an instance of MyCallback and stores it in its instance variable client. The doCallback method executes receiveTimeStamp on the client by making reference to the client instance variable. The server may execute doCallback whenever it wants to update the timestamp on the client.

class MyObjectImp extends _MyObjectImplBase {
MyCallback client;
public String getTimeStamp() {
   // method body
}
public void registerCallback(MyCallback obj) {
   client = obj;
}
public void removeCallback(MyCallback obj) {
   // method body
}
public void doCallback(){
   // define method what will execute
on client
   client.receiveTimeStamp("10:10 AM");
}
}

Understanding Network Traffic Generated by CORBA
One key element to understanding performance in a CORBA system is the network traffic generated by method calls. Developers need to understand when they're using object references versus object instances. CORBA objects always reside on the server and are accessed by the client through methods defined in the IDL. Prior to CORBA 3.0, only object references could be passed between servers and clients. CORBA copies by value nonobjects such as Java primitive data types. An object's attributes are retrieved from the server by using an object's accessor (get) method. Each invocation of an accessor method generates network traffic. The amount of network traffic generated depends on the amount of data retrieved and the number of accessor methods invoked. If a client needs to make frequent reference to object attributes that don't change often, network traffic can be kept to a minimum by making a local copy of the attributes on the client. Callbacks shouldn't be used to update the client-side data.

The IDL compiler generates a pair of Java methods for IDL variables tagged with the attribute keyword. Each IDL attribute generates accessor and mutator (set) methods. The accessor method returns the value contained in the class variable. The mutator method is used to modify the value of the class variable. Only the accessor method is generated for IDL attributes marked as read-only. Method parameters may be marked with the IDL keyword in, out or inout. Parameters marked in are passed only from the client to the server and are viewed as immutable to the called method. The inout keyword is used to declare parameters modified by the server. Parameters marked inout are passed from the client to the server and from the server back to the client. The out keyword declares parameters returned to the client from the server. Since Java doesn't support passing out and inout parameters by reference, the IDL compiler generates a Java Holder class, which is instantiated to simulate passing parameters by reference. The best performance is achieved by using parameters marked with the in keyword.

Following are IDL-defining attributes that create a Java interface containing accessor and mutator methods. These methods are generated for the name and gpa attributes. Since the ID attribute is read-only, only an accessor method is created.

interface Student {
   attribute string name;
   attribute float gpa;
   readonly attribute long id;
};
interface MyObject {
  Student getStudent(in long idNumber);
};

A developer implements the Student object by extending the IDL generated _StudentImplBase class. StudentImpl defines the attributes declared in the IDL as private instance variables, along with the accessor and mutator methods.

public class StudentImpl extends _StudentImplBase {
private String name;
private float gpa;
private int id;
public StudentImpl(String pname, int pid) {
   name = pname;
   id = pid;
}
public String name() {
   return name;
}
public void name(String value) {
   name = value;
}
public float gpa() {
   return gpa;
}
public void gpa(float value) {
  gpa = value; }
public int id() {
  return id;
}
}

The following client code demonstrates the use of object references. After binding to MyServer, the client obtains a reference to the Student object by invoking MyObject's getStudent method. The execution of the student.id, student.name and student.gpa methods generate network activity. Although invocations of these methods appear to operate on a local instance of class Student, they actually access the Student object that resides on the server (see Figure 2).

Figure 2
Figure 2:

org.omg.CORBA.ORB.init(args, null);
MyObject ObjectRef =
MyObjectHelper.bind(":MyServer", "hostname");

Student student = ObjectRef.getStudent(1234);
System.out.println("Student's id: " + student.id()
+ "Student's Name: " + student.name());
student.gpa(3.9);
System.out.println("Student's gpa: " + student.gpa());

Using CORBA in a Web Browser
Java-enabled Web browsers act as a common platform from which CORBA applets may be launched. An ORBlet downloaded to the Web browser permits the execution of CORBA-enabled applets. Browsers that are CORBA enabled, such as Netscape's Communicator, provide efficient use of CORBA in applets since the need to download an ORBlet is eliminated. Netscape's Communicator contains Inprise's Visigenics ORB. If an applet requires an ORB other than the one contained in the Web browser, the required ORBlet must be downloaded when the applet is downloaded. The HTML <param> tag's name and value attributes direct the Web browser to use the downloaded ORB.

The following HTML code downloads the CORBA-enabled applet Grid.class contained in the file Grid.jar. IONA's OrbixWeb ORB is downloaded in the file OrbixWeb301.jar. The HTML <aram> tags direct Netscape's Communicator to use IONA's ORB rather than Inprise's built-in ORB.

<HTML>
<BODY>
<APPLET CODE=Grid.class ARCHIVE=Grid.jar,
OrbixWeb301.jar CODEBASE=java_output>
<param name="org.omg.CORBA.ORBClass"
value="IE.Iona.OrbixWeb.CORBA.BOA">
<param name="org.omg.CORBA.ORBSingletonClass"
value="IE.Iona.OrbixWeb.CORBA.BOA">
</APPLET>
</BODY>
</HTML>

Typically, applets initialize the ORB and bind to the server in the applet's init method. Thereafter, applets may invoke server methods in response to user actions such as a button click. The server may run callback methods on the client anytime after the applet's init method completes. In this way clients receiving real-time updates from a server may be deployed requiring only a Java-enabled Web browser on the client.

Summary
CORBA's powerful concept of separating interface from implementation is well suited to Java. This concept allows software systems to communicate with each other without regard to the client's actual platform. Real-time distributed systems executing on a wide variety of clients can be developed using the techniques discussed here. These applications execute in the ubiquitous Java-enabled Web browser, reducing client-side administration.

Author Bios
Rolf Kamp is a senior technical staff member with AT&T's Operations Technology Center, working on network operation support systems. He is also an adjunct faculty member at Brookdale Community College.
He can be reached at [email protected]

Thomas Czernik is also a senior technical staff member with AT&T's Operations Technology Center, working on network operation support systems.
He can be reached at: [email protected]

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.