It must be
admitted, CORBA is the first thing we have
looked at that is bigger
than Java, as if that were possible!
Java is just one of many languages that is able to use the
CORBA
architecture.
The great thing about CORBA is that
it allows many different
languages
to
communicate with
each other.
The Problem of Integrating
Heterogeneous
Platforms
'The Java Developer's Handbook' by Heller
&
Robert's
describes a scenario that many major
corporations found
themselves in. By the mid-seventies, many
companies
had mainframes they used for
various
business support
chores, including tracking inventory, doing trend analysis
and generating artwork for branding and advertisement.
In 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
might have added IBM PCs.
Company Heterogeneous Computers in the
Mid-Seventies
When networking became a
possibility,
the idea of the
company
connecting all the different computer types
became very alluring. What the firms found
out though
was that the many different machines
had not been
conceived or designed with
inter-communication
in mind.
To make many machines, working on different operating
systems and
hardware and programmed in different types
of programming languages communicate turned
out
to be
a difficult
and
expensive
proposition.
The Object Management Group, OMG
The Object Management
Group
was formed to address
this issue. Initially OMG was just a
group of
engineers,
but with time, 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.
Now OMG is also the
custodian of UML, the Unified
Modeling
Language,
which is a related topic in that UML
provides a language neutral,
object-oriented
visual
modeling
language. OMG also overlooks
the ODMG,
which stands for Object Data Standard.
ODMG
provides an object-oriented way to manage
databases.
Following is a link
to the OMG FAQ page introducing
CORBA.
OMG's FAQ Introducing CORBA
http://www.omg.org/gettingstarted/corbafaq.htm
What is CORBA? // the trick is IDL
CORBA is described 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 with
each other using a language neutral interface
language
called IDL or Interface
Definition Language.
//
CORBA allows a heterogeneous set of computers communicate
// via IDL,Interface Definition
Language which is language neutral.
CORBA uses 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 that CORBA utilizes.
//
ORBs or Object Request Brokers 'broker' method
// invocations between objects
running on
different machines
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. As well, IBMs 'WebSphere',
comes
with
an ORB implementation.
More Recently the
Open Source community and projects
like JBoss are providing support for CORBA Orbs.
Why Use CORBA?
//
legacy migration
One of the
major benefits of CORBA beyond
allowing
different platforms to communicate is
it provides a
vehicle for the migration of legacy
code and data, worth
billions of dollars, into
a network-centric model. Legacy
code can continue to run along side newer types of
information
systems.
OMA , Object
Management Architecture
The OMG calls 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.
//
framework of applications --> Object Management Architecture
Each station, both client and server, will have
an ORB
or Object Request Broker brokering CORBA messages.
A CORBA
system will have a COS or Common Object
Service. (The COS is also called
CORBAServices.)
Every CORBA implementation
is based on
the use of
IDL or Interface Definition Language.
Each CORBA
implementation supplies 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.
Core
Aspects
of a CORBA Implementation
The final aspect that is described as part of
the system is
the CORBAFacilities, also called Common
Frameworks.
This aspect of the specification is variably supported and
may be viewed as an 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 server's ORB. The ORB on the server
translates the
language-neutral message back into it's
native language,
processes the message and returns a response back
through the system.
Practically speaking the messages are method
calls,
similar
to Java's RMI where arguments are passed and return values
are received. The ORB is the 'go-between' taking care of
translating
native code into, and out of, the language
neutral
forms used by the ORBs.
The ORB is Sometimes
Called an 'Object Bus'
The ORB is sometimes also described as an
'object
bus'
as it provides a pathway
for objects to be made available
across different
address spaces. Each computer that
is a
node on CORBA network will be
represented
to the system
by an ORB whether client
or server. Clients and servers
communicate over
the CORBA system via their ORBs.
In addition to allowing
computers to communicate remotely
the CORBA
ORB adds the unique service of
'brokering'
requests and responses between
totally
different machines
using
different languages, hardware and operating
systems.
A hypothetical analogy here might
be a phone service
where people speaking
different
languages have their
conversations
translated so they can understand each
other.
// CORBA limit it's translations to
arguments & return values
CORBA is much more limited than this analogy
implies.
CORBA limits it's heterogeneous platform
communication
to the transmission of
method parameters and return values.
French
English Language Translation Analogy
For
instance,
one machine might say 'Donnez moi
deux
pommes'. The other machine hears 'Give me
two apples'
and replies '2 apples sent'.
The original machine hears
'Deux pommes
envoyees'.
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. Beyond
the basic responsibilities of handling the
network
connections and the message parameters
the ORB is
also responsible for concurrency or
synchronizing
simultaneous requests that
might come from multiple
clients.
//
the
ORB also provides multiple request synchronization
CORBA Client Server Exchange Pattern
CLIENT
<->
ORB <-
object
bus-> ORB <-> SERVER
COS // Common Object Services
The Common Object
Services define a number of services
that CORBA
specifies including features needed by CORBA
to operate as a single secure
distributed
system. Services
include mechanisms to
locate services, respond to events,
maintain security and provide
transactional
processing against
databases. Other services include time services,
processes
to
allow data replication, messaging services and ways to
store stateful
objects in long
term memory. The services
that are deemed essential to CORBA's
operation
will
come
with the vendor's ORB implementation.
Four Main
COS Services
Other Notable COS Services
In addition to the services listed above there
are also
Licensing, Data Interchange,
Change Management,
Messaging and Start-up
Services.
IIOP // Internet Inter-ORB Protocol
The IIOP is an abbreviation of
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 over networks. The GIOP
specification describes how messages are to be sent, how
bytes are
ordered
and how parameters are handled during
remote method calls.
//
GIOP specifies how messages are sent, how bytes
// are ordered and how parameters are
handled
CORBA 2.0 Compliance
Has Strengthened CORBAs Position
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
inter operable.
//
CORBA 2 strengthens CORBA's footing as it specifies
// that different vendor's ORBs must
be inter operable
Object
Adapters
// server-side runtime environment, like a servlet engine
An Object Adapter
is a server side application that supplies
a
runtime
environment
in which CORBA objects can be
managed. The
Object
Adapter serves in a way similar
to how AppletContext provides a runtime
environment
for
applets or a Web server's servlet
engine supplies an runtime
environment for servlets to
run in.
The first Object Adapter that
CORBA 2.0 specified was
called the BOA or Basic
Object Adapter. It is a basic
adapter
that needs to be supplied with every
ORB implementation.
With CORBA
2.2 the POA or Portable Object Adapter was
introduced.
The
BOA
or Basic Object Adapter // from
BOA to POA
Early CORBA
specified a BOA or Basic Object Adapter.
The BOA instantiated CORBA objects and returned
references to them that could
be used
by clients. The
BOA also invoked object
methods
on behalf of clients.
Other tasks included maintaining
security
and activating
and deactivate CORBA objects to and from
a
persistent
state.
However, the BOA
specification was vague and led to
much variation in how
different vendors implemented
the BOA's tasks. ORBs were created that
to
different
degrees took on the Object Adapters tasks for themselves.
//
BOA specification was vague and standarization
// was being lost to proprietary implementations
The
POA or Portable Object Adapter //
carefully defined
To overcome these
problems, the BOA was deprecated
in favor of a
carefully
defined POA or Portable Object
Adapter. The POA standardized the
relation
between
the objects, the adapter and the ORB implementation.
The POA
was
designed to be portable so that a CORBA
object collection could be used with different ORB
products.
The POA was again
charged with
providing
persistence
and transparent activation support for CORBA remote
objects.
The
POA was given additonal duties in managing
CORBA such as lifecycle management.
Description of a Portable Object Adapter in a CORBA System
Client
Set
of Corba Objects
|
|
Stub
POA
|
|
Client ORB
<-network->
Server ORB
In the early years, say between 1997 and 2002, the BOA
had been implemented by
many different
vendors, while
the POA was still in
the process of being adopted. Now
however the POA is alive and well as of JDK1.4 and later
so we can expect to hear less and less of BOA and more
and more of POA!
CORBA 3 &
Where CORBA is going " Embedded systems developers have embraced the Common Object Request Broker Architecture (CORBA) standard as a means for integrating with enterprise systems and supporting network management. Despite the overall popularity of CORBA, it has not been widely used for developing time-critical components of distributed real-time applications. This is because CORBA did not address real-time requirements, leaving it as an exercise to the user or CORBA vendor. In order to extend the benefits of CORBA to real-time systems, the Real-Time CORBA specification was adopted in 1999. This standard tackles the key issue of end-to-end predictability across a CORBA system, and provides its solution in terms of priority control, synchronization, protocol selection and other forms of resource control. " -from CORBA web site http://www.omg.org/news/whitepapers/index.htm#CORBA/IIOP |
Following is a
simplification of a detailed description
provided
originally by David Chizmadia, in a "Quick Tour of the CORBA
Security Service", found at the OMG website.
A Description CORBA Interactions
The stub routine makes a native
call on the ORB. The
ORB transforms the native
call into a GIOP Request
which contains a CDR or Common Data
Representation.
The
CDR can represent all the IDL types in seven basic
formats that can
cover every possible
interaction. The
GIOP also carries an IOR, or Interoperable Object
Reference
that allows
the CORBA object that represents
a service to publish where client
ORBs can find it.
//
native
call to GIOP Request containing IDL representations
The GIOP is then
passed to the transport layer. The
message that is
sent over IIOP or
Internet Inter-ORB
Protocol for transmission over the Internet is
called
the
transport
message.
At the server, in
addition to a basic reversal of the process
described above, parameters have to
be extracted and
applied to a call on a method defined by a CORBA object
stored on the
Server.
This
management of the CORBA object can be thought of
actions
of a
Skeleton, Object Adapter or a combination of
both. The call on the
Server objects
will be native so the return
values will need to be retranslated into
the neutral dialect
of
CORBA and sent back to the client.
Table
with
Key Points From Detailed Description
of
the CORBA Transaction
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) |
RMI-IIOP
CORBA is similar in
function to RMI but more complicated
having
added
the extra
IDL layer to translate the differences
between languages, operating
systems, and
hardware.
Because of the
similarities, little modification of the CORBA
system is
required to to support RMI over IIOP and there is
strong support for bridging the use of RMI with CORBA in
an API called RMI-IIOP.
CORBA
Name
Service
Like RMI, CORBA
uses a name service to locate remote
objects.
Resolving
and binding of remote objects is managed
in a separate process. The
Java
Development Kit supplies
a transient name service called 'tnameserv'.
It does not
persist objects it registers. Name services that come with
commercial
CORBA
products will provide persistent name
services.
CORBA code is more
complicated
and has more steps
then RMI as the naming service has to first be
resolved
from
among the other COS services that are available.
This will be apparent
when we
look at code examples.
The following example shows the CORBA naming
service
being started to run on port 1050.
Starting Java's Transient CORBA Name Service
C:\> tnameserv
-ORBInitialPort 1050
//
DOS
IDL, 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). IDL or
Interface
Definition Language is
a language-neutral
grammer.
IDL
is said to be compiled but it is really
does a translation
via some language specific tool,
into a native language's
interfaces. IDL
compilers
are available for C, C++, Java,
SmallTalk, COBOL and Ada and other languages. The
CORBA interface
definitions (ORB, COS &
Common
Frameworks) are all written in IDL
language
constructs.
'idlj'
Replaces 'idltojava'
In Java, code for a
CORBA application is
first descibed in
the interfaces of IDL. On older Java systems, (JDK 1.2 and
earlier) the IDL
script
is then run
through the 'idl to java' compiler,
called 'idltojava'.
On newer JDK
releases the 'idlj'
compiler is used to
generate the 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 'idlj' compiler has provided.
The idlj
compiler
The idlj compiler
has been available since Java's JDK1.3.x.
The compiler comes with the distribution so does not have to
be downloaded. The following page is still active at the Sun
site (as of 2010 ) and describes the transistion between the
two systems.
http://java.sun.com/j2se/1.3/docs/guide/idl/jidlChanges.html
The Interface Definition Language resembles more
than
any other language, C.
It adopts C syntax for legacy C
types such as
structures unions and enumerated
types.
IDL does not support operation
overloading or overriding
but does support
single and multiple inheritence.It borrows
the
C++ colon syntax to dictate support
for inheritance.
IDL has a number of types that
are used to map support
for Java's
primitive types, arrays, class objects, methods
and exceptions.
The IDL file //
save IDL files to the .idl extension
The IDL code is
written and saved to a file with an .idl
extension.
This file will
translate into a structure in the
native language for which the
translator
was written,
in
our case, Java. The IDL file is passed to idlj
(or idltojava)
compiler which
creates the corresponding CORBA files
in the native language for which
the
compiler has been
designed.
Primitives and String type
IDLs float and double map to Java's float and
double.
IDL's long and unsigned
long map to Java's int type.
IDL long long and
unsigned long long map to Java's
long.
The IDL short and unsigned short map to
the Java type
by the same name.
IDL char and wchar both map to
Java's char type.
The boolean type is the same
in both
languages.
IDL uses the classic 'octet'
keyword for one byte of data
that
maps to Java's byte type. IDL's string and
wstring
map to the Java object type
String. The IDL boolean
constants TRUE and FALSE
are mapped to Java's
boolean literals, 'true' and
'false'.
Table of IDL to Java Mappings
for Primitive Types
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 |
Mapping to Java's package, class, interface, method & constant
The following table
shows IDL structural types, operations,
exceptions
and
attributes map to Java types. The IDL
keyword 'module' corresponds to
the
Java package. The
C type, enum, struct and union all map to Java's
class.
The IDL interface,
aside from mapping to a Java interface,
also results
in the
creation of the set of CORBA support
classes generated by the IDL to
Java
compilers. The
constant IDL type translates to the Java's equivalent of a
constant, a type with the modifiers public static and final
prefixed.
The IDL exception maps to a Java class.
The IDL 'readonly' and 'readwrite'
attributes map to Java
methods, either just an accessor method or both
'get' and
'set' methods in the case of a 'readwrite' attribute.
Table
showing
other IDL to Java type Mappings
IDL
type
|
Java
Type |
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' like 'method' is not a key word |
Note from Mapping IDL to Java
"When a CORBA operation takes
a type that corresponds to a Java object
type 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."
- jdk1.2.2/docs/guide/idl/mapping/jidlMapping.html
The IDL module // maps to Java package
The IDL module construct defines the enclosing
scope of
one or more IDL
interfaces and may contain other nested
module constructs. The
module
maps to a Java package.
Example
module
Z_Company{
module Department{
interface Files{
};
};
};
Saving this code to a file called Z_Company and
passing
it as an argument
to either the idltojava or idlj compiler will
generate a package in a package,
Z_Company.Department
in which is the Java
code for the Files interface and associated
CORBA
Java files. The contents
varies depending on the
translator. The following
shows the output of the
classic
'idltojava' translater. It is similar to the output of the newer
RMI compiler. Note though that Java source files have been
created by the idl compilers.
Example
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
Example
1)
Book.java
2) BookImplBase.java
3) BookStub.java
4) BookHelper.java
5) BookHolder.java
The idlj Compiler Options
The new idlj compiler is used a little differently.
It separates
the classes that
will be needed by the Client from those that
are needed by the Server. When
used
to
generate CORBA
client classes the
-fclient
option is used to generate
the same
set of classes as the idltojava compiler
would create except,
an 'Operations' class is added
and the 'ImplBase' or
implementation base class
is omitted.
When the idlj
compiler is used to generate server side CORBA
classes the ImplBase class
is generated along with an Operations
class and
the services interface.
//
Using
idlj with -fclient generates an XXXOperations class and not an
// ImplBase class. On the server side, an ImplBase class is generated
// along with an Operations class and the services interface
idlj Compiler Generation Example // client
1)
Book.java
2) BookOperations.java
3) _BookStub.java
4) BookHelper.java
5) BookHolder.java
idlj Compiler Generation Example // server
The IDL attribute // variables with assc. methods
IDL uses the
'attribute' keyword to mark CORBA variable
types. These attibutes
are automatically translated into
methods by the IDL to Java compilers.
If the attribute
is marked 'readonly' then only an accessor method is
generated. If the
attribute is
marked 'readwrite' then
both an accessor and mutator method is generated.
In the
following example the attribute is not marked
'readonly' or 'readwrite'
and so will
default to readwrite
and generate both methods. This is the output
using
the idlj
compiler.
IDL Input // save as Price.idl
interface Price{
attribute float price;
};
//
supply as argument to idlj
> idlj -fclient Price.idl
Java
Operations
Interface Created
// with other classes
/* CORBA style comments omitted */
public interface PriceOperations
{
float price ( );
void price (float newPrice);
} // interface PriceOperations
The get and set
methods corresponding to the
price attribute are by default created.
IDL Operations
Operations compile
to Java methods. There isn't an
operation keyword.
All
that needs to be done is to supply
the signature of the method you
want to
include. There
are some rules as follows. The key difference between
Java
methods and IDL methods is the inclusion of the
'in', 'out', or 'inout'
keywords
in the parameter area.
Rules
Governing
IDL Operations
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.
The reason 'out' and 'inout' parameters map to a
holder
class is that Java doesn't
support these types directly.
The same behaviour can be emulated by a Java
object
type
being passed into a method as an argument and
then the same object being returned after modifications
are made. This is what the holder class does, act as a
wrapper for these
special
non-Java
types.
IDL Exception
IDL allow the
creation of exceptions that generate the
type of exception
one expects
from Java. There are a
couple of things to note. First, exceptions
must be declared
before they are called. Also exceptions are not mapped
directly to
Java Exceptions.
Instead they are created as
subclasses of
org.omg.CORBA.UserException.
IDL Exception Example
exception EastWindException{
string
reason;
};
The
IDL 'raises' Keyword
IDL operations can
be declared as throwing exceptions
with the IDL keyword 'raises'.
IDL Input
module C_Company{
exception
EastWindException{
string
reason;
};
interface Winds{
void
prevailing_wind(in boolean WEST)
raises
(EastWindException);
};
};
idlj Output
public
interface
WindsOperations
{
void prevailing_wind (boolean WEST) throws
C_Company.EastWindException;
} // interface WindsOperations
IDL struct
As mentioned
earlier IDL uses some C data types. For
instance in
the following
example the struct is used to
create a collection of data for a
book.
A single Java
class with public data members.
Example
struct Book {
string title;
string author;
string isbn_number;
float price;
};
Among the classes
created, the one that represents the
'struct' defined
above is marked 'public' and 'final'. Book
with a no-args constructor and
a constructor
that will
accept initialization for all the variables in the order
they
are listed in the
structure.
IDLJ
Output
public
final
class Book implements org.omg.CORBA.portable.IDLEntity
{
public String title = null;
public String author = null;
public String isbn_number = null;
public float price = (float)0;
public
Book ( )
{
} // ctor
public
Book (String _title, String _author, String
_isbn_number, float _price)
{
title = _title;
author = _author;
isbn_number = _isbn_number;
price = _price;
}
// ctor
} // class
Book
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.
A helper class is created to
allow a Java type to be represented by
a
different name.
Example
typedef
string
Name;
typedef
long
Salary;
typedef sequence <long> ID;
The helper class is
stored in a FunctionsPackage and has
a Java file
named
after the name adopted to represent the
type definition. The class
stands
in for the typedef, reading
and writing to stream the required
definitions
as needed.
IDL sequence
The IDL sequence
represents a single dimension array.
The sequence may
be bounded where it's maximum value
is set or unbounded. In the
following
example ten IDL longs
will create a single dimension int array in Java
with
ten cells.
As with other type definitions a helper class is generated
and also
a holder class to hold the values of the array in
the CORBA system.
Example
typedef sequence < long, 10 > Orders;
The holder class
generated for this example is called
OrdersHelper.java
and
contains a regular Java style int
array. It also contains a constructor
that receives
an
array and a read and write methods to send and receive
values to
and from it.
//
Creates a holder class with an array and associated
// accessor and mutator methods
IDL Arrays
IDL also supplies
an array construct to creates a single-
dimension array
which
appears more like a Java style
array.
Example
const long length =
20;
typedef string name[length];
IDL enum
The IDL enum type
creates an enumerated list. The list
is emulated by
three classes, a Java with same name
and a helper and holder class.
Example
module F_Company{
enum Teams { Yankees, Expos, BlueJays };
};
There are some
other IDL types like the Union that behaves
like the
struct
which maps to a Java class. Also of note
are constants which map to
public,
static final variable
in the Java code.
IDL Constant
Declaration
We will end this
quick tour
of IDL with
an example of an IDL constant declaration.
Example
const float baseValue = 1000.00;
idlj Output
public static final baseValue = 1000.00;
We have looked at
the parts of the CORBA architecture
now it is time
to go
through the steps of creating a CORBA
client server application. The
recipe
for creating CORBA
applications is similar to RMI but with the added
step of
creating the IDL interface definitions which need then be
mapped to
the Java
language.
The steps in brief
are first to create the IDL file, compile
with an IDL to Java compiler. If the newer idlj compiler is
used the compiler
will be used
twice, once for the client
with the appropriate flags and then for
the server
with
the -fserver flag.
The generated class
files are then used in creating an
implementation of the CORBA services. These may be
compiled first. A client and server will have to be built
and then all three of these
will also need
to be compiled.
The system is then ready to be tested.
The naming
service
is started first followed by the server
and then the client. The steps
to take
are listed below.
The list is adapted from one in the Developer's
Handbook
by Heller & Roberts. It has been modified to provide to the
new
idlj compiler.
Note: the idltojava
command
//
You
might want to stick with the new trail using idlj
Summary
of
the Steps in Creating a Classic CORBA
System // See link below for new 10 Steps with a
POA
1. Create the IDL file
2. a) Compile using idlj for each of the client and the
server
b) OR
if you have an old JDK compile the
IDL file using idltojava
3. Compile the generated .java
classes
using javac
4. Implement the methods
5. Create the implementation server
6. Create the client application
7. Compile the implementation, server
and client code
8. Start the Naming Service, tnameserv
9. Start the server
10. Start the client
1. Create the IDL file
We have spent sometime looking at IDL so this
part of it
should be straight ahead.
First the interface for the services
and
structure
of the remote Corba object must
be defined.
We are going to build a voting
system.
In our example we
will illustrate the use of both, the
classic idltojava compiler
and the newer idlj
compiler.
Following is a declaration that
will result in a package
that contains
an interface called votes being created.
The
interface defines two methods that
return how many
votes were cast for the Liberals
or the Tories.
IDL Example
module vote_poll{
interface votes{
long get_Liberal(
);
long get_Tory( );
};
};
2. a )
Compile the IDL using
idlj
// Things have
changed again with CORBA! To
continue with
// this 'recipe' we need to specify the -oldImplBase flag when
'
// idljing' the server. This creates the _votesImplBase class we
// extend to create an implementation base.
If using the idlj
compiler which comes with the new JDKs
a different
option is
used to generate the classes for the
client then is used for the
server.
The following
line is an
example of the client stubs being generated.
Client
Example
idlj -fclient vote_poll.idl
// this command generates
votesHolder.java, votesHelper.java,
// _votesStub.java
votes.java
and votesOperations.java
Notice we are using the -oldImplBase flag to generate
an _votesimplBase.java class.
Server
Example
idlj -fserver -oldImplBase vote_poll.idl
// this command generates votes.java
and votesOperations.java
// and _votesimplBase.java
When using the idlj compiler the primary
interface
no
longer carries the methods
that are defined in the IDL
file. Instead, an
operations class is generated and
housed
in a subdirectory that contains these
methods.
This operations interface is
shared by both stubs and
skeletons. The
operations
interface is not used directly
by
the developer so we don't have to worry about
it.
OLD OPTION
2. b) Compile the IDL using idltojava // for older JDKs
The above IDL
module needs to be saved as a text file with
an .idl extension.
If it was compiled using the classic idltojava
compiler the command
would take
the following form. The
idltojava is written
in native C++. That is why the -fno-cpp
flag is used. These are preprocessor directives
where
-fno-cpp option turns off
C/C++ preproccessing. The newer
idlj is written
all in Java and so doesn't require
these options.
Example idltojava-fno-cpp vote_poll.idl
// leaving out the no pre-proccessor flag results in an error
A new directory called vote_poll is created in
the current
directory
which contains the following Java files,
votes.java,
_votesStub.java,
_votesImplBase.java, votesHolder.java
and
votesHelper.java.
votesHolder.java | - holds parameter types not supported by Java |
votesHelper.java | - provides other kinds of help accessing types |
_votesStub.java | - provides a proxy for the client to make remote calls |
votes.java | - provides the interface implemented by the remote object |
_votesImplBase.java | - extended to supply the remote object implementation |
3. Compile the generated java files
Once the files are
generated they can be compiled. Notice
they are in
a package that corresponds to a directory so
they are compiled from.
Example
javac
vote_poll \*.java
4. Create the implementation class
The implementation class is created by extending
the
_nameImplBase and
providing definitions for the methods
defined
in the idl file. By extending the
implementation
class, all the hooks neccessary
for the object to cooperated
with the CORBA system are automatically added.
All this
is cleanly hidden
away and the developer can concentrate
on
supplying
definitions for the
method signatures.
Implementation
Example
package vote_poll;
public class votesImpl extends
_votesImplBase{
static int l = 0;
static int t = 0;
public votesImpl(
){ // recommended
no-arg,
empty constructor
}
/*
method
implementations */
public int get_Liberal( ){
l ++ ;
return l ;
}
public int get_Tory( ){
t ++ ;
return t;
}
}
5. Writing the Server
The server class starts by calling init( ) on
the ORB class
to return an ORB object.
Notice OBBs are not instantiated
but rather
returned
from an init( ) method. The
init( ) method
has three overloaded variations
all which return an ORB
object. The
no-args form is used internally by the CORBA
system. The second form takes an
applet instance and an
Properties object. This
form of the method is used with
applets.
The third that takes a String array and a
Properties
object is used with stand-alone
applications.
Notice the third form designed
for standalone applications
has a string
array that corresponds to the main( ) method
array that receives parameters at the
command line. The
array in the init( ) method
allows passing in parameters
directly
from the command line. The properties object
can
be used to pass in other
parameters.
Variations in Signatures of ORB's init( ) Method
After the ORB is obtained the implementation object
is
instantiated and it's
reference is passed to the connect( )
method
of the orb. This object needs
to be bound or
registered with the naming
service.
First the Naming
Service
is resolved from among the various CORBA
COS
services. This reference is
then narrowed to a
NamingContext object.
A name,
in our example Votes' is
encapsulated as a
NameComponent object and then
in turn an array of
NameComponents. This is the form that is
needed to
bind
the name to the remote service
object. This is done
using the rebind( ) method
of the NamingContext object.
The object then uses Java's Object class wait(
) method
to wait to be called
into service.
Corba Server Code Example
import vote_poll.*;
import org.omg.CosNaming.* ;
import
org.omg.CosNaming.NamingContextPackage.*
;
import org.omg.CORBA.* ;
public class vote_poll_server {
public static void main( String
args[] )
{
try{
ORB
orb = ORB.init(args,null);
votesImpl
vI = new votesImpl( );
orb.connect(vI);
// binding the object with the name service
org.omg.CORBA.Object
corba_object = orb.resolve_initial_references("NameService");
NamingContext
naming_context = NamingContextHelper.narrow(corba_object);
NameComponent
namecomponent = new NameComponent("Vote", "");
NameComponent
path[ ] = { namecomponent };
naming_context.rebind(path,
vI);
//
Synch
on Object object and wait for client invocations
java.lang.Object
sync = new java.lang.Object( );
synchronized
(sync) {
sync.wait(
);
}
}
catch(Exception
e){
System.err.println("Error
" + e);
}
}
}
6. Writing the Client
The client locates
a reference to the CORBA object using
the Naming
Service.
The Naming Service location can be
specified at the command line as
an option
or as a property
passed to the ORB. The following examples show
both
these
options.
Example
Starting
Client Specifying Host and Port Number
java Client -ORBInitialHost 234.23.4.5 -ORBInitialPort 1050
// supplying the name service
IP address and port from the command line
Example
Passing
Host and Port Information via Properties Object
Properties
props=new
Properties( );
props.put("org.omg.CORBA.ORBInitialHost", "234.23.4.5");
props.put("org.omg.CORBA.ORBInitialPort", "1050");
Orb orb=ORB.init(args, props);
// supplying the name service IP address and port as a Property object
As described
earlier for the server code, in CORBA the
Naming Service
has
to first be filtered from other COS
services. This is done using
the resolve_initial_references( )
method for the particular service needed, in
this case the
naming service.
The naming service
then supplies an initial context
which
is obtained by first using the narrow( ) method of the
NamingContext's
helper
class. The narrow( ) method
returns an object of the NamingContext
class.
The
following two lines shows these steps.
Example Showing Service and
NamingContext
Narrowed
org.omg.CORBA.Object cor_obj =
orb.resolve_initial_references("NameService");
NamingContext naming_context =
NamingContextHelper.narrow(cor_obj);
Once the naming
context has been returned, the object
reference can be
obtained
for the CORBA remote service.
First the service name is wrapped
in a
NameComponent
object. The NameComponent constructor takes a String
that
represents the name of the CORBA object and a
second string that can
be empty
that supplies a description.
The resolve( )
method of the naming
context
object
takes
a NameComponent array. The following lines shows the
"Vote"
name being
packaged in the form needed by the
resolve( ) method which takes the NameComponent array
reference as an argument. Notice it had to undergo another
narrrowing via the narrow( ) method of the votesHelper class.
Example
NameComponent nc = new NameComponent( "Vote",
"");
NameComponent path[] = { nc };
votes vI =
votesHelper.narrow(naming_context.resolve(path));
Finally the
returned object reference can be used via the
dot operator
like any
other object to call the objects methods.
The following Client example
shows
all these stages.
Corba Client Example
import vote_poll.* ;
import org.omg.CosNaming.* ;
import
org.omg.CosNaming.NamingContextPackage.*
;
import org.omg.CORBA.* ;
public class vote_poll_client{
public static void main(
String args[] ){
if (args.length!=1){
System.out.println("Vote
by specifying a party, Liberal or Tory. ");
System.exit(1);
}
String
party_vote=args[0];
try{ //
Use the ORB instance and Naming Service to obtain a remote reference
ORB
orb = ORB.init(args, null);
org.omg.CORBA.Object corba_object =
orb.resolve_initial_references("NameService");
NamingContext naming_context = NamingContextHelper.narrow(corba_object);
NameComponent nc = new NameComponent( "Vote", "");
NameComponent path[ ] = { nc };
votes vI = votesHelper.narrow(naming_context.resolve(path));
//
use the reference to call remote CORBA methods
if (party_vote.equals("Liberal"))
System.out.println(
"The vote is Liberal and the new tally is " +
vI.get_Liberal());
else
if
(party_vote.equals("Tory"))
System.out.println(
"The vote is Tory and the new tally is " +
vI.get_Tory());
else
System.out.println("Your
ballot has been discounted");
}
catch(Exception e)
{
System.out.println("ERROR
: " + e);
}
}
}
7. Compile the Server and the Client & Implementation class
In the case of the client and server they have
been defined
as importing the vote_poll
directory. So these classes
should be compiled
in the directory above vote_poll
directory.
On the other hand the votesImpl class is
declared
as being part of the package vote_poll
so it
should go inside the vote_poll directory.
The following
example shows the appropriate compiles.
Command Line javac Compilations
>javac vote_poll_client.java
>javac vote_poll\votesImpl.java
//
votesImpl
is in the vote_poll package
>javac vote_poll_server.java
8. Run the Name
Server
Because we are using the
command line to supply
arguments we will use the default technique which
will start the CORBA system on port 900. To use
another port, we could use the Properties object
to supply alternate addressing. This way the command
line remains unencumbered to pass in arguments.
Enter tnameserv at
the command line and press enter.
The service will
default
to port number 900. The following
examples shows how the initial port
can
be explicitely
specified.
C:\> tnameserv
//
naming service default
port
number is 900
When you start the tnameserv you will see a very
long
number. That is the IOR
or Interoperable Object Reference
followed by
the current port number. The IOR
describes
a service and where it's located.
9. Run the server
The following shows
the server being started on the
default port number 900.
>
java vote_poll_server
10. Run the client
> java vote_poll_client
If everything runs
as expected the client will prompt the
user to enter
Liberal
or Tory at the command line and
will keep a tally of each type of vote.
CORBA Recipe Using the POAAdapter
CORBA is a moving
target. The POAAdapter is now
part of the active scenario and a new heavier weight
naming service is included in latest JDK distributions.
Rather than make
this note too long I include a link
to a page which shows a summary of the new formula
which makes use of CORBA's new pieces.
Conclusion
That is the basics of creating a CORBA service.
There
are few subjects we
are leaving out. For instance the
issue with
dealing with out and inout parameters.
If you
need details of using out and inout
parameters
this
information can be
obtained in the documentation or at
the Sun site. IDL mapping information accompanies the
JDK distributions.
There is also an interesting
API called DII or Dynamic
Invocation Interface
that allows a client to access a
CORBA object even though it doesn't have a client
CORBA stub.
Finally the
adoption of RMI for use with CORBA in the
RMI_IIOP is a significant
trend in that allows the developer
to return to writing RMI applications that run over the
CORBA system.
Note any one of the
assignments is optional. If you have
enough in you are finished your term work. However this
assignment is straight ahead and you may wish to do it
anyway for the hands on experience.
On the other hand,
if you are missing an assignment you
should do this one as it is just of casing of running the
supplied code. There is a minor bonus point for running
the code and submitting in the case that all your assignments
are in.
In the following
you may choose to use the new POA
formula or the older formula in which case additional
flags are now required.
1. Run the
Vote code and submit screen shot of the output.
Optional
2. Create a CORBA
Client and Server Example that returns a
credit rating
for an individual name passed in. If the name is not
in the list a
message to
indicate no credit rating is available
should be returned.