Introducing CORBA
What is CORBA?
The wikipedia page says it all:
The Common Object Request Broker Architecture (CORBA) is a standard defined by the Object Management Group (OMG) that enables software components written in mutiple computer languages and running on multiple computers to work together (i.e., it supports mutiple platforms).
The standard was created twenty years ago, in 1991. The technology can
be used in many programming languages: Python, Java, C++, C, etc.
Hence you can write a software in your favorite programming language,
exposing services that others will be able to call using a different
language. (Nowadays you can do the same with WebServices. This article
is about CORBA.)
All CORBA specifications are available on [OMGSPEC]; latest version
is [CORBA3.1].
[MCHALE] book is a very good way to learn CORBA.
How does it work?
CORBA is language agnostic because it relies on its own language: the
Interface Definition Language (IDL for short). The IDL defines the
contract between the client (software calling the service) and the
server (software implementing the service). The service is exposed
through a remote object.
IDL is used to define:
- modules, which are called namespaces in C++ (or packages in
Java) - structs, which are like C structs: they can contain data only
(the data part of the contract) - interfaces, which contain methods specification (the service
part of the contract) - exceptions that can be raised by a method
- typedefs which are type aliases
- unions, à la C
- enums, enumerations
- constants
IDL comes with existing types:
- char, octet
- string, wstring
- short, long, long long (signed if unspecified, unsigned
if prefixed with unsigned) - float, double, long double
- arrays
- sequences
- any which can be any existing or user-defined type
From this contract, the following code will be generated using a
dedicated tool:
- client-side code, called stubs
- server-side code, called skeletons
So to call a CORBA remote service in a given programming language, we
will generate stubs from the IDL, then write code relying on these
stubs. To provide a CORBA service in a given progamming language, we
will generate skeletons from the IDL, then extend them with our
implementation.
The dispatching and networking machinery is handled by the Object
Request Broker (ORB for short). That's the most important part of the
CORBA system: it's the component that hides away remoting aspects to
make distant objects appear as if they were embedded within the local,
client-side code.
Telecom Log Service example
The Telecom Log Service [TLOG] is an OMG specified service that
defines two interfaces:
- Log, to add, search and delete records
- LogMgr, a Log container to lookup a given log, or list all
contained logs
The specification details five sub-interfaces of the log service,
grouped into three different approaches:
- basic implementation. This is the service depicted below.
- event-based implementation. The Event Service [EVENT] is another
CORBA service specification. Combining both services means that
software emitting events can be plugged to an Event Log without
modification. - notify-based implementation. The Notification Service [NOTIF] is
another CORBA service specification, built on top of the Event
Service, with added filtering facility. Again, combining these two
services provide easier integration with existing software.
Here is the UML representation of key base interfaces (in yellow),
basic implementation (in blue) and important date structures (in
green):
Here is the simplified IDL for these parts:
#include <TimeBase.idl> // IDL can include each other #pragma prefix "omg.org" // extra prefix to use in front of type names // DsLogAdmin definition // Because of the #pragma prefix above, the complete name of this module // is omg.org/DsLogAdmin module DsLogAdmin { // E X C E P T I O N -------------------------------------------------- exception InvalidGrammar {}; // empty exception exception InvalidConstraint {}; // empty exception exception LogFull { short n_records_written; }; // one attribute exception LogOffDuty {}; // empty exception exception LogLocked {}; // empty exception exception LogDisabled {}; // empty exception // T Y P E A L I A S ------------------------------------------------ typedef unsigned long LogId; typedef sequence<LogId> LogIdList; // LogIdList is a sequence of LogId typedef unsigned long long RecordId; typedef string Constraint; typedef TimeBase::TimeT TimeT; // TimeT type defined in TimeBase module typedef sequence<any> Anys; // Anys is the name of a sequence of any // S T R U C T U R E S ------------------------------------------------ struct NVPair { string name; any value; }; // <-- Mandatory semi-colon typedef sequence<NVPair> NVList; // Give a name to a sequence of NVPair struct LogRecord { RecordId id; TimeT time; NVList attr_list; any info; }; typedef sequence<LogRecord> RecordList; // I N T E R F A C E S ------------------------------------------------ // Iterator interface specification interface Iterator { // get() method: // - two input parameters // - returning a list of LogRecord // - possibly raising InvalidParam exception RecordList get(in unsigned long position, in unsigned long how_many) raises (InvalidParam); void destroy(); }; // <-- Mandatory semi-colon // Forward declaration interface LogMgr; interface Log { LogMgr my_factory(); LogId id(); // retrieve() method: // - two input parameters // - one output parameter // - returning a list of LogRecord // This method will actually return two objects: the // RecordList and the Iterator RecordList retrieve(in TimeT from_time, in long how_many, out Iterator i); RecordList query(in string grammar, in Constraint c, out Iterator i) raises (InvalidGrammar, InvalidConstraint); unsigned long delete_records(in string grammar, in Constraint c) raises (InvalidGrammar, InvalidConstraint); void write_records(in Anys records) raises (LogFull, LogOffDuty, LogLocked, LogDisabled); }; typedef sequence<Log> LogList; // Give name LogList to sequence of Log // inteface BasicLog derives from interface Log interface BasicLog : Log { void destroy(); }; interface LogMgr { LogList list_logs(); Log find_log(in LogId id); LogIdList list_logs_by_id(); }; // inteface BasicLogFactory derives from interface LogMgr interface BasicLogFactory : LogMgr { BasicLog create( in LogFullActionType full_action, in unsigned long long max_size, out LogId id) raises (InvalidLogFullAction); BasicLog create_with_id( in LogId id, in LogFullActionType full_action, in unsigned long long max_size) raises (LogIdAlreadyExists, InvalidLogFullAction); }; }; // <-- Mandatory semi-colon
The complete IDL file for the Basic Telecom Log Service is available
here.
[CORBA3.1] http://www.omg.org/spec/CORBA/3.1/
[MCHALE] http://www.ciaranmchale.com/corba-explained-simply/
[OMGSPEC] http://www.omg.org/technology/documents/spec_catalog.htm#Middleware
[TLOG] http://www.omg.org/spec/TLOG/
[EVENT] http://www.omg.org/spec/EVNT/
[NOTIF] http://www.omg.org/spec/NOT/