|
The growing relevance of CORBA
and OMG in the Information Technology world has
made it an irresistible option to Software Developers.
Infact, CORBA is the only system solution that
supports all major languages and most major platforms.
Sun underestimated this when they avoided CORBA
altogether in their Java solution (More one this
in the first article). Well, they had better reasons
for doing so; they needed something simpler. It's
was by now a public concern that CORBA was a tough
solution, mainly due to the lack of platform support
and surprising to me may people complain about
the steep learning curve. Though I haven't said
this before, OMG IDL is something I would like
to see left out in the past but that would require
of platform support. The pros of COBRA strongly
favored it among the Software Developers community.
The large number of CORBA servers that are deployed
in the enterprise needed to be accommodated with
RMI clients and newly developed RMI servers needed
to be accommodated with the existing CORBA infrastructure.
Sun sure wanted something simple, they did consider
that learning IDL would mean going the extra mile
for most Java professionals. They wanted an Interface
Definition Language for Java. This was pretty
simple, they had interfaces in Java and more over,
a well architected JVM that accommodated easy
pass by value semantics (For more details of pass
by value semantics, refer to the previous article).
When RMI was introduced to the market Sun also
bought along with it ease of programming, and good
integration of ORB technologies to the JVM. I
do like RMI, after all the power of Jini and Java
Spaces, pretty advanced distributed technologies
have this technology as its ORB. The people at
Sun believed in making RMI the only solution for
their distributed Java needs and making Java the
defacto language for software development. This
would never happen and resulted in Sun's inclusion
of CORBA in their Java platform specification.
But this meant that Sun had to do away with RMI
altogether or augment RMI with the best known
CORBA features like Transactions, Security, Fault
Tolerance, Scalability and the sorts. They decided
on the later solution.
People from IBM and Sun decided to work out a
solution. They needed to integrate the RMI runtime
with CORBA and still keep RMI like programming
style. They came up with a simple solution, let
the interface to the programmer still be RMI,
and the messaging engine be IIOP. IIOP enables
interoperability between different vendors ORBs.
So, they decided to call it RMI over IIOP. However,
this needed some changes in the tools that are
to generate the middleware code - stubs and skeletons.
There were a lot of semantic differences between
RMI and CORBA distribution concepts. However,
the architectural pattern Broker along with the
concepts of an ORB, stub, skeleton and servants
is omnipresent in both the technologies. So, the
mapping was not simple on CORBA, it needed some
adjustments to IDL, some criticized for being
too close to Java, like the valuetypes with methods,
abstract valuetypes and abstract interfaces (read
the previous article). One feature of RMI that
CORBA lacked was pass by value semantics. RMI
achieved it with the Java Serialization mechanism.
With the inclusion of pass by value semantics
to CORBA, this lack was addressed. Distributed
garbage collection always was a contentious issue
and would result in some very sticky situation.
With RMI, you had true distributed garbage collection.
Meaning, if the clients stopped using a RMI object,
there was a corresponding decrease in the RMI
objects reference count. In the case of CORBA,
all objects are reference counted locally, meaning
if the client drops the reference count, only
the proxy reference count is reduced. As for the
server side, there exist two concepts, the CORBA
Object and the Servant. It's unto the Object Adapter
to maintain this existence, and to terminate this
association, and to remove the registered CORBA
object. However, this is hidden behind the RMI/IIOP
runtime.
One feature that I miss much is the casting operation.
In RMI, a simple cast with the () [cast] operator
would lead to the automatic download of the required
stub. With plain CORBA you will not only need
the stub code, but also need a CORBA cast operator.
Well, does CORBA have a cast operator? It does
have, but a very crude one. Remember, if a feature
is not available with an Object System, you can
achieve it with Objects. And this is exactly what
CORBA has. Remember the Helper class and the narrow
operation. It's just this feature that helps CORBA
remain independent of language features (a good
example reduced platform support for CORBA, which
cannot be helped). With the integration of RMI
and CORBA, well, you have the choice of downloading
the stub remotely with the help of the codebase
argument. This required of IIOP to be augmented
with code downloading semantics. As of now, CORBA
does not have any code downloading semantics.
A simple solution would be to have the codebase
attached to the IOR as a multicomponent profile
(TAG_JAVA_CODEBASE).
The picture below will show how RMI/IIOP works
from the architectural perspective. In the first
picture you can replace the CORBA server side
with an RMI server side seen in the second picture
(the vice versa is also true).
Lets now look at the Java to IDL mapping in detail.
To encourage convergence between the RMI and CORBA
programming communities, it is important to define
a solution that is both fully compatible with
the current RMI semantics and fully compatible
with OMG IDL, IIOP and CORBA Object Model. The
subset of Java that meets these goals is referred
to as RMI/IDL. A confirming RMI/IDL type is a
Java type whose values may be transmitted across
an RIM/IDL remote interface at run-time. A Java
data type is a confirming RMI/IDL type if it is:
 |
| |
 |
Lets now look at the Java to
IDL mapping in detail. To encourage convergence
between the RMI and CORBA programming communities,
it is important to define a solution that is both
fully compatible with the current RMI semantics
and fully compatible with OMG IDL, IIOP and CORBA
Object Model. The subset of Java that meets these
goals is referred to as RMI/IDL. A confirming
RMI/IDL type is a Java type whose values may be
transmitted across an RIM/IDL remote interface
at run-time. A Java data type is a confirming
RMI/IDL type if it is:
One of the Java primitive
types
These are: void, boolean, byte, char, short, int,
float, double, long.
A conforming Remote
Interface
A Java interface that can be invoked remotely
should inherit from the java.rmi.Remote interface
directly or indirectly and all its methods are
to throw the java.rmi.RemoteException or its superclass.
The arguments and the return type at runtime are
to represent conforming RMI/IDL types. One interesting
fact is that you can have method overloading.
However, if the interface inherits from several
interfaces, you cannot have conflicting names
between the interfaces. You can also declare constants
in the interfaces.
A conforming value
type
An RMI/IDL value type represents a class whose
values can be moved between systems. So rather
than transmitting a reference between systems,
the actual state of the object is transmitted
between systems. This requires that the receiving
system have an analogous class that can be used
to hold the received value. A conforming RMI/IDL
valuetype is a Java class that implements the
java.io.Serializable or java.io.Externalizable
interface and must not directly or indirectly
implement the java.rmi.Remote interface. Methods
and field names should not cause any collisions
when mapped to IDL. A java.lang.String is also
a conforming RMI/IDL valuetype but is mapped to
an IDL string.
An Array of conforming
RMI/IDL types
Arrays of conforming RMI/IDL types are also conforming
RMI/IDL types.
A conforming exception
type
An RMI/IDL exception type is a checked exception
class and meets the RMI/IDL valuetype requirements.
A conforming CORBA
Object Reference type
A conforming CORBA object reference type is either
a Java interface org.omg.CORBA.Object or a Java
interface that extends org.omg.CORBA.Object directly
or indirectly and conforms to the rules specified
in the Java Language Mapping.
A conforming IDL Entity
type
A Java class is a conforming IDL entity type if
it extends ormg.omg.CORBA.portable.IDLEntity and
conforms to the rules specified in the Java Language
Mapping and is not an OMG IDL user exception.
We start off the mapping of Java to IDL with naming
conventions, then proceed to the primitive datatypes
and end up with complex constructs. I would avoid
some of the intricacies for the sake of brevity.
Naming Conventions
Packages are mapped directly to OMG IDL modules.
Inner classes are mapped by appending two underscores
after the outer class name followed by the inner
class name. All overloaded methods are mangled
with their respective arguments. This is a simple
name-mangling scheme. For example the four overloaded
Java methods:
void
hello();
void hello( int x );
void hello( int z[] );
void hello( Object o );
Are mapped to the following OMG IDL methods:
Void
hello__();
Void hello__long( in long x
);
Void hello__org_omg_boxedRMI_seq1_long(
in
::org::omg::boxedRMI::seq1_long
x );
Void hello__java_lang_Object(
in
::java::lang::_Object o );
Note
that any name clashes with built in Java names
are avoided by prepending an underscore in front
of the conflicting name as seen by the mapping
of java.lang.Object.
Primitive Datatypes
The mappings for the Java void, boolean, short,
int, long, float and double types are straight
forward as they have exact OMG IDL analogues.
The 8 bit Java type byte is mapped to an 8 bit
unsigned OMG IDL type octet. The mapping is bit-for-bit
so that Java byte value "-1" is transmitted as
GIOP octet "0xFF". Thus when using this mapping,
we will preserve full value and sign information
when using RMI/IDL between a Java client and a
Java server over GIOP. A 16 bit Java Unicode char
is mapped to an OMG IDL wchar type.
 |
| |
RMI/IDL
Remote Interfaces
An RMI/IDL remote interface is mapped into an
OMG IDL interface with the corresponding name
in the OMG IDL module corresponding to the Java
interface's package name. However, the java.rmi.Remote
interface is mapped to an IDL Object (CORBA::Object),
the base of all IDL interfaces.
//IDL
module java {
module
rmi {
typedef
Object Remote;
};
};
All methods of the form get and set
are mapped to attributes and methods of the form
get is mapped to a readonly attribute. Boolean
properties like is is mapped to a boolean
attribute. Compile time constants ("public final
static") for primitive types and Strings are mapped
to IDL constants.
RMI.IDL Value Types
RMI/IDL value classes that implement org.omg.CORBA.portable.IDLEntity
and org.omg.CORBA.portable.ValueBase directly
or indirectly are not mapped to OMG IDL because
these Java classes correspond to existing OMG
IDL value types that were mapped to Java using
the OMG IDL to Java mapping.
If the RMI/IDL class extends some base class other
than java.lang.Object or implement any other interface
other than java.io.Serializable or java.io.Externalizable,
and equivalent valuetype of interface is generated
for this. Methods in the Java class is not required
to be present in the generated IDL valuetype,
mainly to avoid spaghetti effect of generating
the entire Java Framework in IDL. As for constructors,
they too are not required to be mapped to valuetype
factories.
Any constants ("public static final") fields for
primitive types and Strings are mapped to similarly
named IDL constants in the target value type with
the same values. All non-constant fields are mapped
to state variables of a valuetype with corresponding
access rights - public and private. The mapping
of java.lang.String is special, its mapped to
a ::CORBA::WstringValue. However, when mapping
a constant string field, it's mapped to a wstring.
So is the case for java.lang.Class, its mapped
to ::javax::rmi::CORBA::ClassDesc.
// Java
package javax.rmi.CORBA;
public class
ClassDesc implements
java.io.Serializable
{
private String
repid;
private String
codebase;
// space-separated
list of URLs.
};
RMI/IDL Arrays
An RMI/IDL Array is mapped to a "boxed" valuetype
containing an IDL sequence. We use the syntax
"valuetype xyz foo" as shorthand for defining
a valuetype named "xyz" that contains a single
field of type "foo".
Primitive OMG IDL types such as long, boolean,
etc, are mapped directly into the ::org::omg::boxedRMI
module. For other types, the module name to formed
by taking the ::org::omg:boxedRMI prefix and then
adding the type's existing module name to identify
a sub-module. So the type ::a::b::c is mapped
to ::org::omg::boxedRMI::a::b.
RMI/IDL Exceptions
OMG IDL does not allow subclassing of exception
types. By contrast, Java programmers tend to make
heavy use of exception subclassing, and the Java
type system is used to distinguish different flavors
of exceptions at run time. It is very common for
a Java interface to say it raises a fairly generic
exception but for implementations to throw more
specific sub-types and for clients to make the
Java instanceof operator to check for specific
subtypes. In addition, RMI/IDL exceptions can
e passed as normal valuetypes whereas OMG IDL
exceptions can only be used in raises clause.
To allow full support for subclassing when communicating
Java to Java we use a mapping where an RMI/IDL
exception type is mapped to both a specific OMG
IDL exception and to an OMG IDL valuetype that
allows subclassing. The OMG IDL exception has
a single field, which holds the corresponding
value object. This solution allows RMI/IDL to
support the normal idiomatic use of Java exceptions,
while still being correctly mappable into OMG
IDL.
CORBA Object Reference
Types
A CORBA Object reference type is mapped directly
to its corresponding OMG IDL interface or to Object
if it is org.omg.CORBA.Object.
IDL Entity Types
An IDL entity type that is not a CORBA object
reference type is mapped to a boxed value type
containing the IDL entity type.
Non-conforming Classes
and Interfaces
All Java interfaces that throw the java.rmi.RemoteException
or a superclass of it are RMI/IDL abstract interfaces.
All other Java interfaces are mapped to OMG IDL
abstract value types with no data members. Non-conforming
Java classes are mapped to OMG IDL abstract value
types with no datamembers.
Abstract Interfaces
Java interfaces that do not extend java.rmi.Remote
directly or indirectly and whose method definitions
all throw java.rmi.RemoteException or a superclass
are mapped to OMG IDL abstract interfaces. Java
interfaces that do not extend the java.rmi.Remote
directly or indirectly and have no methods are
also mapped to OMG IDL abstract interfaces.
Implementation Classes
In general mapping RMI implementation classes
to OMG IDL is not needed. However, if a given
RMI implementation class implement multiple distinct
RMI/IDL remote interfaces, then it is necessary
to generate an OMG IDL type that represents the
unification of the distinct RMI/IDL types. Any
such composite RMI/IDL implementation class is
mapped into an IMG IDL interface with the corresponding
name. Each inherited RMI/IDL remote interface
inherited by the Java implementation class is
represented by an equivalent inherited interface
in the OMG IDL interface. Inherited classes and
inherited interfaces, which are not RMI/IDL remote
interfaces, are ignored. At run time, any instance
of the composite implementation class, must from
a CORBA perspective, implement the corresponding
composite OMG IDL interface. This implies, for
example, they must return true to any calls of
"is_a" on any of the OMG IDL interfaces associated
with the distinct RMI/IDL interfaces.
Each and every technology has its fair share of
criticisms, and so has RMI over IIOP. We did see
that the addition of valuetypes, abstract valuetypes
and abstract interfaces came under a lot of criticism
from the purists. As for what has IIOP brought
for RMI, many have their own arguments. One of
the most pronounced advantages or IIOP is interoperability,
and it does achieve interoperability in simple
applications. But, when it came to Transactions
and Security, it has a major problem when it came
to interoperability between different vendor products.
This is not an RMI/IIOP limitation but a general
CORBA architecture limitation, which I am sure
in time, will get addressed. As for inter ORB
interoperability, you need a CORBA 2.3 ORB, where
as a lot of existing legacy applications deployed
in the enterprise are on CORBA 2.0. But the icing
is the integration between J2EE and advanced CORBA
- CCM that we shall see in detail in the coming
issues.
- Mr.
Jacob Jose Cherakal - Software Architect,
|