CORBA & Java IDL                  Peter Komisar

references:
1) 'Developer's Handbook' Heller-Roberts ,2) ' Introducing Java IDL' ,The Java Tutorial,
3) jdk1.2.2 at /docs/guide/idl/mapping/jidlMapping.html,
4)'A Quick Tour Of the CORBA Security Service by David Chizmadia
5) ' Advanced Java' Clifford J. Berg



 

The problem CORBA was Designed to To Solve

'The Java Developer's Handbook' by Heller & Robert's describe a problem
scenario that many major companies found themselves in. CORBA was invented
to provide a solution to this problem. The story basically goes like this. By the mid
seventies many companies had mainframes they used for various business support
chores such as creating graphics to generate artwork used for branding and
advertisment. The mainframe would also be used for doing trend analysis and
keeping track of inventory. At the early 80s relatively cheap PCs became available
and started to proliferate in the companies various departments. The engineering
department might have acquired Unix based workstations while the art department
might have collected Apple computers. The business divisions would be adding IBM
PCs to the office. When networking became a possibility, the idea of the company
connecting all the disparate computers into a grand inter-communicating system
became very alluring. What the firms found though was the many different machines
had not been conceived or designed with intercommunication in mind. Making many
machines, with programs written in different programming languages, resting on
different operating systems and hardware communicate with each other turned out
to be a very difficult and expensive proposition.
 

The Object Management Group, OMG

This is the problem the Object Management Group was formed to address.
Initially the OMG was just a group of engineers. As time went on OMG grew
to a large consortium with over 800 member companies. The Object Management
Group came up with CORBA, the Common Object Request Broker Architecture
that allowed different types of computer platforms to intercommunicate. Besides
CORBA, the OMG are also the official custodians for other world standards.
They now oversee UML, the Unified Modeling Language, which is platform and
language neutral, object-oriented visual modeling language. They also overlook
the ODMG, which stands for Object Data Standard. ODMG provides an object-
oriented way to manage databases.
 

What is CORBA?

CORBA is descibed as a distributed objects framework became it is an object-
oriented distributed computing architecture. CORBA allows programs that are
written in different computer languages running on different operating systems and
hardware to communicate each other using a language neutral interface language
called IDL or Interface Definition Language. CORBA uses a ORBs or Object
Request Brokers to broker method invocations between objects running on
different machines. The secret to making the system work is that the individual
ORBs take care of translating the platform specific aspects of requests and
responses into the language neutral layer of CORBA. The OMG only maintains
the CORBA specification. It leaves commercial implementation of the standard
to ORB vendors. You can see a list of companies that have developed CORBA
solutions at www. corba.org . More famous producer's are Borland who make
Visibroker and IONA that make Orbix.

Why Use CORBA?

So why go through all the trouble? One of the key benefits of CORBA beyond
allowing heterogeneous platform communicate is it allows the migration of legacy
code and data, worth billions of dollars, into a network-centric model. This enables
the investment in legacy code to continue being used along side newer more unified
information systems.
 

Corba and Java

Java integrates support for CORBA into it's standard development kit distributions.
Some of it's components are light weight and intended primarily for a reference for
development. For instance, Java's ORBs do not use persistence or permanent
storage to back up it's data. More robust commercial ORBs provide persistence
for CORBA objects.  The Java Enterprise Edition (J2EE) was designed to provide
network solutions written in Java. The applications that are used to host Enterprise
JavaBeans are called Containers. These containers are often designed to run over
the CORBA architecture.
 

CORBA Architecture

The OMG call the  framework of applications that work together to form a
CORBA system the OMA or Object Management Architecture. There are
a core set of these elements that every CORBA implementation will include.
First there is the ORB. Each station will have an ORB or Object Request Broker.
The ORB handles communications between the client and the CORBA system.
The ORB serves the same role for the server as it does for the client. A CORBA
system will have a COS or Common  Object Service. The COS is also called
CORBAServices. Every CORBA system implementation is also predicated on
the use of IDL or Interface Definition Language. Each CORBA implementation
will supply an IDL compiler that translates interfaces written in IDL into the native
language being used by a client or server to write their distributed applications.
The final aspect that is described as part of the system is the CORBAFacilities.
CORBAFacilities is also called Common Frameworks. This part of the system
is not widely supported to date CORBAFacilities can be viewed as an optional
part of a CORBA implementation even though it is part of the specification.

Table Summarizing the Principle Components of a Corba System
 
 ORB  An Object Request Broker implementation
 COS   A Common Object Services a.k.a CORBAServices
 IDL   The Interface Definition Language & compiler 
 CORBAFacilities  a.k.a. Common Frameworks  // optional 

The ORB      // The Object Request Broker

The ORB is the Object Request Broker. The orb takes messages from the client, translates
them into CORBA's language neutral protocol, and transmits the message to the target ORB
that is representing the server which will respond to the request message. The ORB on the
server translates the language-neutral message back into the native language of the server
and the server provides a response to the request. The response, in like fashion is returned
back into the CORBA system and is returned to the client.

Practically speaking the messages are method calls, passing arguments and receiving return
values. The ORB  takes care of translating this information into a language neutral form and
then transmitting the information over the wires of the network.

The ORB is sometimes also describes as an object bus because it provides a pathway for
objects to travel between different address spaces. Each machine that represents a node
on CORBA network will be represented by an ORB whether client or server. While a
client would be represented by it's ORB the server on the other side of a network would
have it's own ORB object, acting as a receiver that translates messages from clients into a
dialect it understands. If you can imagine a phone system that allows people speaking in
different languages to make very simple quantitative info exchanges  ( i.e Donnez moi deux
pommes .... 2 apples sent  ) you have the basic notion of what the CORBA system does.
Each ORB used is familiar with the native language of the machine  it is being hosted on so
takes care of translating in and out of language-neutral 'Corbese'  to the language that is
being used on the machine. It is in the sense that the ORB 'brokers' between different
languages, platforms, and hardware that it get's it's name Object Request Broker. Beyond
the basic responsibilities of handling the network connections and the message parameters
the ORB is also responsible for concurrency, the synchronizing of simultaneous request that
might come from multiple clients.
 

 Figure 1 The basic exchange between a client and server over the Corba System

CLIENT  <->  ORB      <- object bus->       ORB  <->  SERVER
 

 COS    // Common Object Services

The Common Object Services define a number of services that CORBA specifies. They
include the different aspects that are important to any computer system. They are unique
in that describe services that are uniquely designed to operate in the distributed architecture
that is CORBA. These services provide the mechanisms for the distributed application to
locate services, respond to events, maintain security and provide transactional processing
against databases. Other services include time services, and ways to store stateful objects
in long term memory.

Our first objective will be to get a basic system running and to this end we will just be
using the Naming service that is provided with the java distribution. The different CORBA
services are listed in the tables below.

Common Object Services
Common Object Services assist the ORB providing  The15 services are:

 The principal four services
 
 Naming Service  -provides a hierarchial naming directory for CORBA objects
  enabling clients to request a reference to an object by name
 Event Service  -allows an EventObject to be sent to receiver(s) 
 -objects can request 'to listen' to specific event 
  channels. The service notifies listeners of an event 
  on that channel. (events are stored until passed)
 Security Service  -provides method authentication, authorizes object 
 accesses and secures communications
 Transaction Service  -controls database access with transaction 'commit' & 'rollback'

The remaining eleven
 
 5)   Persistent Object Service  6)   Concurrency Control Service 
 7)   Life Cycle Service   8)   Relationship Service 
 9)   Externalization Service  10)  Query Service 
11)  Licencing Service  12)  Property Service 
13)  Time Service  14)  Object Trader Service 
15)  Object Collections Service .

IDL

IDL or Interface Definition Language is a language-neutral grammer. IDL is said to be
compiled but it is really translated via some language specific tool, into a native language's
interfaces. IDL compilers are available for C, C++, Java, SmallTalk, COBOL and Ada.
The CORBA interface definitions (ORB, COS & Common Frameworks) are all written
in IDL language constructs.
 

IIOP  // Internet Inter-ORB Protocol

The IIOP is short for Internet Inter-ORB Protocol. IIOP is as TCP/IP implementation
of General Inter-ORB Protocol ( GIOP ) The GIOP specification defines how ORBs
communicate with each other. The GIOP specification describes how messages are
to be sent, how bytes are ordered and how parameters are handled during remote
method calls.

IIOP compatibility is required for CORBA 2.0 compliance. Heller & Robert's in the
'Java Developer's Handbook' point out that the standardization that CORBA 2 has
brought to ORBs has greatly strengthened CORBA's position in the world of network
computing. This is because CORBA 2.0 compliant, ORBs provided by different
vendors are now by definition interoperable.
 
 
 BOA and POA   //  reference


 "An Adapter converts the interface of a class into another interface clients expect" 
                                                                                          Design Patterns, E. Gamma et al.

 Corba supports the idea of an Object Adapter. Object Adapters create server objects 
 and return the object's reference. Corba specified one Basic Object Adapter (BOA). It 
 was deprecated in favor of the Portable Object Adapter (POA). The POA specification 
 makes it possible to move server-side code from one vendor implementation to another. 
 You can think of a POA as a plug-in component that provides most of the functionality 
 of an ORB. Current references say POA implementations are still pending. Aug / 2000
.
 

CORBA Transactions

In simplest terms, the Server provides a remote interface and the client calls it. The CORBA
client holds a reference for the remote corba object. This reference has a stub method which
stands in for the method being called remotely. The stub connects to the ORB which handles
connecting and forwarding the invocation to the server. The ORB in the process converts the
native environment message into Corba's language neutral format.

On the server, the ORB restores the language neutral message to what is native on the server
machine and calls the skeleton code to convert the remote invocation into a call on the
implementation object. After the calls have been processed, the skeleton takes care of return-
ing these values to the ORB. The ORB once again retranslates the return values to language-
neutral, GIOP format. The IIOP layer packages the GIOP message into a TCP compliant
package and sends it back to the client.
 
 
Corba Operation in More Detail


 This is a quote  from part of "A Quick Tour Of the CORBA Security Service" 
 by David Chizmadia, OMG Security SIG Co-Chair. View this article  at 
 http://www.omg.org/news/corbasec.htm


"Conceptually, the interface stub routine calls on the ORB to transform the language-specific 
  operation call into a language, operating system, and hardware independent GIOP (Generic 
  Inter-ORB Protocol) Request. The GIOP defines a Common Data Representation (CDR) for 
  all of the basic IDL types and seven basic request formats that cover all of the kinds of 
  interactions between the client and object implementation, as well as an Interoperable 
 Object Reference (IOR) that allows the Object Implementation to publish information that 
 allows clients' ORBs to find and forward requests to it. The GIOP Request is then passed 
 to a network transport processing layer,"..." the Internet Inter-ORB Protocol (IIOP). The 
 transport processing layer transforms the GIOP object location information into the transport-
 specific address (TCP host and port for IIOP) of the Object Implementation and creates a 
 transport Message containing the GIOP Request. 
 The client-side ORB sends the Message to the ORB on which the Object Implementation runs. 
 The receiving ORB's transport processing layer extracts the GIOP Requestfrom the Message 
 and forwards it to the GIOP processing layer, which transforms the Request into the specific 
 language, operating system, and hardware dependent format required by the Object 
 Implementation. The Object Implementation code  is then invoked as an upcall from the 
 interface skeleton routine generated by the IDL compiler. After the Object Implementation 
 completes its processing, it returns control to the skeleton routine, which sends the result 
 back to the client stub, which returns the result to the client program. "
 . 



This image has been extracted from 'IDL', 'The Java Tutorial',Campione-Walraith
and can be viewed at http://java.sun.com/docs/books/tutorial/idl/intro/corba.html

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



More detailed description of a Client Object Interaction in CORBA
 
  THE CLIENT       THE   OBJECT IMPLEMENTATION
 native call on stub          ( native call   layer )  makes calls on object
 calls the ORB where   (stub skeleton   layer )  Skeleton takes native
 call info
 GIOP processes 
 native to neutral 
        ( Conversion  layer )   GIOP processes
 neutral to native 
 GIOP request.              (Generic Inter  Orb Protocol)  GIOP request
 TCP packaged    message(request)  < --   (Internet Inter-  Orb Protocol)    -->  TCP packaged
 message(request)

Corba is similar in function to RMI but with the extra IDL layer to translate the
differences between languages, operating systems, and hardware. Because of the
similarities, little modification of the CORBA system was required to to support
RMI over IIOP.

What is missing in our discussion so far is any reference to the naming service. The
registration and looking up of the remote corba object is an activity separate from
the transaction being described in the models. The remote calls happen after the
connection between client and object have been made. The way the naming service
is used in Corba is more complicated than in RMI and will be evident when we
look at the code examples. As with RMI, the naming service will need to be started
running in it's own process. The following example shows the CORBA naming
service being started.

Example             tnameserv -ORBInitialPort 1050


IDL to Java Mapping

For details see in the jdk1.2.2 at /docs/guide/idl/mapping/jidlMapping.html


Interface Definition Language

The slight of hand that enables different languages to cross-communicate requires the
programmer to first write to the language neutral, Interface Definition Language (IDL).
Code is first descibed in the interfaces of IDL. This idl script is then run through the
idltojava compiler which translates the script into java classes and interfaces which
have the Corba architectural hooks built into them. The java programmer then fills in
the implementation details in the framework that the idltojava compiler has provided.
 

 IDL Constructs and Java equivalents

 primitives and String
 
 IDL   JAVA 
 float   float
 double   double
 long, unsigned long   int
 long long, unsigned long long   long
 short, unsigned short   short
 char, wchar   char
 boolean   boolean
 octet   byte
 string, wstring   java.lang.String
 The IDL boolean constants TRUE and FALSE are mapped to the corresponding
 Java boolean literals true and false.

 package, class, interface, method & constant
 
 module   package 
 enum, struct, union   class
 interface   interface, helper, holder, implementation, stub 
 constant   public static final
 exception   class 
 readonly attribute  method for accessing value of attribute 
 readwrite attribute  creates accessor and mutator methods
 operation  method   //operation isn't an IDL keyword

 Note from Mapping IDL to Java                   jdk1.2.2/docs/guide/idl/mapping/jidlMapping.html
 
 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, in which case the null is interpreted as a nil CORBA object reference.

 
Holder Classes  // from jdk1.2.2 /docs/guide/idl/mapping/jidlMapping.html


 IDL supports  out and inout parameter but Java only supports in parameters. Java works around 
 this by using "holder" classes to wrap the in and inout values.These classes are available for all 
 of the basic IDL datatypes in the org.omg.CORBA  package and are generated for all named user 
 defined types except those defined by typedefs. 
 For the basic IDL datatypes, the holder class name is the Java type name (with its initial letter 
 capitalized) to which the datatype is mapped with an appended Holder, e.g. IntHolder.
 Each holder class has a default constructor that sets the value field to the default value for the 
 type as defined by the Java language (i.e. false for boolean, 0 for numeric and char types, etc.)

 The holder classes are in the org.omg.CORBA package.



 Example of a Holder class from the CORBA package

 package org.omg.CORBA;

 final public class ShortHolder {
        public short value;
        public ShortHolder( ) {}           // default no-args, empty constructor
        public ShortHolder(short initial) {
            value = initial;
        }
 }



 Example of how Holder classes are used in place of an inout parameter

 interface InOutInterface{ 
   void InOutMethod ( inout double x );
   };
};
 // the above IDL interface generates the following

 public interface InOutInterface{
   public void inOutMethod ( DoubleHolder x );
  }
. . .
 DoubleHolder dh = new DoubleHolder( 11 );
 inOutInstance. inOutMethod ( dh );
 int returned= dh.value( );
 // Corba Holder classes look a lot like regular java Wrapper classes
.


An IDL file is a composition of several elements which together create a naming scope.
IDL does not support operation overloading or overriding but does support single and
multiple inheritence


The IDL module construct defines the enclosing scope of one or more IDL interfaces
and may contain other nested module constructs.  // ' module'  maps  to  java's 'package'

example       module  The_Company{
                               module     Inventory{
                                     interface Records{
                                                     . . .
                                     };
                                 };
                              };
  // the idltojava compiler would create the package, The_Company.Inventory


IDL interface maps to several Java interfaces / files.

      1) A Java interface class with same name as the IDL interface identifier
      2) An implementation base class containing skeleton code for the server
      3) A stub class for the client
      4) A helper class for narrowing references returned from the Naming Service
      5) A holder class to contain an IDL type reference

examples  1) Records.java
                  2) RecordsImplBase.java
                  3) RecordsStub.java
                  4) RecordsHelper.java
                  5) RecordsHolder.java


IDL attribute
the  IDL keyword marking CORBA variable types

Attributes generate get/set (accessor/mutator) methods for the type declared

example   attribute float price;                 // the IDL attribute creates the following java methods
               float price( );
               void price(float arg);      // if attribute is marked read only then only accessor is created


IDL Operations
Operations compile to Java methods. There isn't an operation keyword.

Operations 1) must have a return type
                  2) may have zero or more arguments
                  3) in parameters map directly to java arguments
                  4) out and inout parameters map to the nameHolder class. Java doesn't support
                      types that can be mapped comparably to out or inout. The holder class serves
                      to mediate the differences.


IDL raises
IDL operations can be declared throwing exceptions with the IDL keyword  raises

example      interface Winds{
                 void prevailing_wind(in  boolean WEST){
                          raises (EastWindException);
                              };
                       };


IDL exception
Exceptions 1) must be declared before they are invoked
                  2) IDL exceptions don't map directly to Java Exceptions API rather they map to
                      java classes that are extensions of org.omg.CORBA.UserException class

example    exception StockException{
                   string reason;
                              };

            interface account{
                              void orderBooks( in Booklist books)
                          raises (StockException);
                              };


IDL struct
A container class used to pass a collection of data as a single object.
Maps to a Java class with public data members.

example    struct Book {
              string title;
              string author;
              string isbn_number;
              float price;
                        };


IDL typedef
The typedef construct allows defining new IDL types from existing ones.
The IDL compiler will set the type back to actual type before compiling.

example          typedef    string        Name;
                        typedef    long           Salary;
                        typedef    sequence  <long> ID;


IDL sequence
A single dimension array, bounded (where the maximum value is set) or unbounded.

example    typedef sequence < long, 10 > Orders;

An example of a bounded sequence of 10 IDL long numbers of type Orders
Exceeding bounds throws a MARSHAL systems exception
Every sequence created has it's own Java helper and holder class


IDL Arrays
The IDL array construct creates a single-dimension array similar to sequences

           const long length = 20;
           typedef string name[length];


IDL enum
IDL's enum creates an enumerated list which maps to a java final class with the same name

example        enum Teams { Yankees, Expos, BlueJays };
 


Getting the idltojava compiler

Once you have written your code in IDL it needs to be compiled through the idltojava compiler.
The jdk1.2 idltojava compiler is found at the following site.    // use for the practical example below

http://developer.java.sun.com/developer/earlyAccess/jdk12/idltojava.html

The newer  Version 1.3 of the Java 2 SDK, Standard Edition, includes a new version of Java
IDL. The new IDL-to-Java compiler, idlj, is included with the download of J2SE v.1.3. It has
a number of changes outlined at the following site.

http://java.sun.com/j2se/1.3/docs/guide/idl/jidlChanges.html

While spending time investigating IDL one should be aware that since the RMI-IIOP
specification has largely been ironed out, writing and compiling IDL can avoided!  You
now have the option to write to Corba directly over RMI. Essentially it comes down to
writing to RMI as usual with a few more restrictions.   See RMI_IIOP


IDL Development Steps

Heller-Robert's 10 steps to creating a CORBA Service
including examples from their 'Java Developer's Handbook',Heller-Roberts

 1.  Create an IDL file that represents the interfaces desired
 2.  Compile the IDL file using idltojava
 3.  Compile the generated classes using javac
 4.  Create an implementation class
 5.  Create the implementation server
 6.  Create the client application (or applet)
 7.  Compile the implementation, server and client code
 8.  Start the Naming Service application, tnameserv
 9.  Start the server (which registers with the Naming Service)
10. Start the client

1. Creating the IDL File

       module Calculator{
              interface Functions{                                                      // idl interface is like  java's
               float square_root ( in float number );
               float power ( in float base, in float exponent);
               };
        };                                            // java doesn't require the semi-colons after the curly braces

The IDL file describes an IDL interface named Functions, enclosed in the running scope of a
module named Calculator, describing a single service (containing two operations).
 

2. Compiling the IDL File using the idltojava compiler           // similar to RMI compiler

       idltojava -fno-cpp calc.idl                                            // save IDL to a file suffixed .idl

where -fno-cpp option turns off C/C++ preproccessing    // translates  flag no preprocessor

//  the idltojava is written in native C++ (thus the preprocessor directives). The newer idlj is all java.

The compilation creates the following Java files and directories
 
 Calculator  The directory/package created by the module declaration 
 Functions  A Java interface declaring operations as methods
_FunctionsImplBase  An abstract class implementing 'Functions' providing the server a 
 skeleton class from which it can inherit Corba connectivity. The 
 server or an implementation object subclasses this skeleton and 
 implements it's methods
_FunctionsStub   Another class implementing the Functions interface, the stub is 
 extended by the client to access the interface methods
 FunctionsHolder  A utility class holding a reference to assist in 'out' and 'inout' 
 method argumentation not implemented in Java
 FunctionsHelper  Autility class providing auxillary functions i.e. the narrow( ) method 
 required to cast CORBA object refs to their proper types 

3. Compiling the Generated Classes

The IDL compiler produces Java source code files that next are run through the javac compiler

       javac Calculator\*.java
 
The interface Functions created by the idltojava compiler


package Calculator;
  public interface Functions extends org.omg.CORBA.Object{
     float square_root(float number);
     float power(float base,float exponent);
     }

4. Creating the Implementation Class

One of the classes created by the idltojava compiler is created as an abstract class extending org.omg.CORBA.DynamicImplementation and implementing the Functions interface.
As a result it only needs to be extended and Function's methods have to be implemented.

Heller-Roberts implemetation class

/* Note:Convenience by Design  The abstract, complicated and CORBA wise _FunctionsImplBase
     generated  by the idltojava compiler is provided for the Corba programmer to easily extend   */

package Calculator

public class FunctionsImpl  extends _FunctionsImplBase{

    public FunctionsImpl( ) {       // constructor not required but recommended
    }
                                                                                 // method implementation
   public float square_root(float number){
       return (float)Math.sqrt((double)number);
       }
    public float power(float base, float exponent){
       return (float)Math.pow((double)base,(double)exponent);
      }
   }


5. Creating the Server        // See finished client and servers in the example code provided

The server class registers the implementation object with the ORB and Naming Service and provides
the connection implementation class. It begins by initializing an ORB object, then creating a reference
to the the implementation class, FunctionsImpl. It also publishes a name to reference the object with
the Naming Service.
 

 6. Creating the Client

The client locates a reference to the Functions object using the Naming Service. After creating an ORB
instance, it requests an object reference matching that created through the NamingContext. This general
CORBA reference must be cast or narrowed to the appropriate reference type via the Helper class
narrow( ) method. The object is now a client side stub representing an implementation of the interface.
This instance can be used by the client to reference the desired method calls.
 

7. Compile the Implementation, Client and Server

                    javac FunctionsImpl.java  CalculatorServer.java  CalculatorClient.java
 

8. Start the Naming Service

tnameserv -ORBInitialPort 1050                               // naming service default port number is 900

Creates the IOR Interoperable Object Reference followed by the current port number
The naming service outputs a long string called the IOR (Interoperable Object Reference)
and the current port the naming service is on. The IOR describes location (host,name IP address
etc.) and the services the object provides and can be used to allow two ORB's to eliminate the
need for having the naming service locate the object.

9. Start the Server

                     java CalculatorServer -ORBInitialPort 1050

                  -starting the server reisters the implementation object with the Naming
                   Service by using port number (exampled here) or by using the IOR
                   published at Naming Service start up.
 

10. Start the Client

                     java  CalculatorClient -ORBInitialPort 1050

                   -if successful in locating the server and remotely referencing
                    the FunctionsImpl object's methods, the results from thesquare root
                    and power operations will be written to screen.