CORBA Outline • Introduction to CORBA – Basic concepts – IDL • Simple Client/Server Example • C++ Language Binding • Other Issues – IIOP – Exception Handling – CORBA Object Services – Advanced Example
Jan 08, 2016
CORBA Outline• Introduction to CORBA
– Basic concepts
– IDL
• Simple Client/Server Example• C++ Language Binding• Other Issues
– IIOP
– Exception Handling
– CORBA Object Services
– Advanced Example
Introduction to CORBA
• CORBA Goals and Philosophy– Client/Server architecture
• Intro to CORBA components
• IDL– language constructs– examples
Object Management Group
• Publish CORBA standard
• Over 700 members: CORBA vendors, software vendors, users, academics
• Meet every 6 to 8 weeks all over the world
• Well-defined standardization process– fast, efficient, successful
• Publishes interface standard– companies make compliant implementations
CORBA Key Concepts
• Transparent Distribution
• Objects
• Client / Server model
• Portable– across platforms, languages, networks
• Standard
Distributed Application Architectures
• Multiple computers on a network
• Services can reside on any node– file service– name service– print service
• CORBA transparently distributes applications
Object-Orientation
• Objects - attributes and methods• Classes - clusters of objects with common
behavior• Encapsulation - hide internal structure• Inheritance - define new class using existing
class• Polymorphism - two or more classes respond
to a method invocation differently
Client Server Model• Client makes method call of remote object
• Call is forwarded by ORB to server
• Object implementation receives the call and responds
CORBA Architecture
Dyn.Inter-face
IDLStub
ORBInterface
IDLSkeleton
ObjectAdapter
Object ImplementationClient
Object Services: naming, events, life cycle, persistence, transactions, concurrency, relationships, externalization, object licensing, properties, object query.
ORB
OS KernelOS Kernel OS KernelOS KernelNetwork
CORBA Components
• Object Request Broker (ORB) core
• Interoperability Spec. (GIOP and IIOP)
• Interface Definition Language (IDL)
• Programming Language Mappings
• Static Invocation Interface (SII)
• Dynamic Invocation Interface (DII)
• Dynamic Skeleton Interface (DSI)
• Portable Object Adaptor (POA)
• Interface and implement repositories
• Common Object Services (CORBAServices)
CORBA Services
• Lifecycle• Naming• Event• Persistence• Relationship• Externalization• Transaction• Concurrency
• Security• Time• Licensing• Query• Trader• Scheduling
Interface Definition Language (IDL)
• IDL is object-oriented – specify interfaces containing operation and
attributes– supports interface inheritance (single and multiple)
• IDL designed to map to multiple programming languages
• IDL similar to Java interfaces and C++ abstract classes
Application Interfaces
• Interfaces defined using IDL can be application specific– databases, spreadsheets, spell checker, etc.
• Objects may be defined at any level of granularity– fine-grained GUI objects– multi-megabyte multimedia “Blobs”
OMG IDL Features
• modules• interfaces• operations• attributes• inheritance• basic types
• arrays• sequence• struct• enum• typedef• const• exceptions
IDL vs. C++
• C++ has - not IDL– data members
– pointers
– constructors/destructors
– overloaded methods
– int data type
– templates
– control constructs
• Different in IDL– string type
– sequence type
– exception interface
– unions require a tag
• New in IDL– oneway call semantics
– readonly keyword
– pass “contexts”
– parameter passing modes
Modules
• IDL module defines naming scope for a set of IDL definitions
• Group interface and other IDL type definitions into logical name space
• Avoid name clashes
// IDLmodule finance interface account {. . .};};
• Fully scoped name of interface account is finance::account
Interfaces
• The basic unit is the interface– defining the interface to a type of object
interface account { // operation and attribute definitions};
Operations
• Look like C++/Java member functions
• parameters must be named
• parameter passing mode must be specified
interface account { // operations void makeDeposit (in float amount); boolean makeWithdrawal (in float amount, out float balance);
Parameter Passing Modes
• in passed from caller to called object• out passed from called object to caller• inout passed in both directions
• CORBA must know the direction
– to know how to pass the values
Raising Exceptions in IDL Operations
• Operations can raise exceptions to indicate occurrence of an error
• Two types of exceptions:– System exceptions - standard set defined by CORBA
– User-defined exceptions// IDLmodule finance { interface account { exception WithdrawalFailure { string reason; }; void MakeWithdrawal(in float amount, out float newBalance) raises(WithdrawalFailure); . . . };};
Attributes
• Typically these map to two functions in the programming language– set the value– get the value
• a readonly attribute maps only to a function to get the value
interface account { // attributes readonly attribute string dateLastModified; readonly attribute float balance; attribute string owner;}
Attributes (cont)
• Attributes do not necessarily represent state– e.g.– dateLastModified might be
• stored as a member variable– as a string
– as an integer value
• calculated from the history of transactions
readonly Attributes
• A readonly attribute is not necessarily a constant
• an operation call can change it - e.g.
• bad practice to modify a readonly attribute in the code that sets another attribute
typedef string Date;interface file { readonly attribute Date dateLastModified;
void write (…); void read (…);};
Inheritance
• All attributes and operations of account are valid on objects of interface checkingAccount
interface checkingAccount : account {
attribute float overdraftLimit;
boolean orderCheckBook();
};
• An IDL interface can inherit all elements of one or more other interfaces
Basic Types
• short (16 bit)
• long (32-bit)
• unsigned short (16-bit)
• unsigned long (32-bit)
• long long (64-bit)
• unsigned long long (64-bit)
• float
• double
• char (8-bit)
• wchar (16-bit)
• boolean (TRUE or FALSE)
• octet (8-bit - no conversion)
• any (arbitrary IDL type)
• string (can be bounded)
IDL Constructed Types
• Enumenum currency {pound, dollar, yen, franc};
• Structstruct customerDetails { string name; string age;};
• Unionunion Date switch (short) { case 1: string stringFormat; case 2: long digitalFormat; default: DateStructure structFormat;};
Other IDL Types• String - max can be specified
attribute string sortCode<10>;
• Sequence - 1D array- can be bounded or unbounded
sequence<account, 50> accounts;
• Array- can be multidimensional - always fixed-size
account accounts[3];
• Constantconst long MaxAccounts = 10000;
Mapping to a Programming Language
• for each programming language supported by CORBA, a mapping must be given from IDL to that language
• e.g. C++ client’s view
class account : public virtual CORBA:Object {public: void makeDeposit (…); CORBA::Boolean makeWithdrawal (…); char * dateLastModified (…); CORBA::Float balance (…); char * owner (…); void owner (const char * …);};
Mapping to a Programming Language (cont.)
• e.g. Java client’s view
public interface account extends org.omg.CORBA.Object{ public float balance(); public void MakeDeposit(float f); public void Withdraw(float f);}
• call these methods to make a call to a CORBA object
Static Invocation Interface (SII)
• Most common way of using IDL
• All methods are specified in advance– known to client and server via proxies– also known as surrogates
• Primary advantages of SII– simplicity– typesafety– efficiency
Dynamic Invocation Interface (DII)
• Less common programming API• Enables clients to invoke methods on objects that
aren’t known until run-time• Clients “push” arguments onto a request stack and
identify operations via ASCII name• Type-checking via meta-info in “Interface
Repository”• More flexible than SII• More complicated, less typesafe, inefficient
OMG IDL Compiler
• IDL compiler generates client stubs and server skeletons in specific programming language
• Programmer “fills-in” implementation
• See example later
CORBA Programming Steps• Define IDL interface• Compile IDL interface
– generate Java code
• Implement the interface– represents a CORBA object
• Write a server – that will contain the CORBA object defined in the interface– Initializes the ORB
• Write a client to use the CORBA objects• Compile the client and server applications• Execute the server (and naming service if necessary)• Execute the client application
Example: Remote Quoter Object
A Quoter provides stock quotes to clients
IDL interface to quoter
Client code calls anoperation on remote
quoter objects
Client Process
Server Process
C++ object
REDH$
Other CORBA Object
Server NodeClient Node
MSFT$
IDL Interface for Quoter interface Stock { double price ();
readonly attribute string symbol; readonly attribute string full_name; };
interface Stock_Factory { Stock get_stock (in string stock_symbol) raises (Invalid_Stock_Symbol); };
TAO IDL Compilation
Quoter.idl
Stock_i.cpp, Stock_Factory_i.cpp
client.cpp
Quoter serverexecutable
Quoter client execuable
IDL complier
C++ Compiler
Generated Classes and
Headers
QuoterC.h,QuoterC.i,QuoterC.cpp
QuoterS.h,QuoterS.i,QuoterS.cppQuoterS_T.hQuoterS_T.i,QuoterS_T.cpp
server.cpp
%tao_idl Quoter.idl
Write a Client
• Client initializes access to ORB
• Client gets a reference to the desired object
• Calls methods to access the object
In client.cpp:
int main (int argc, char* argv[]){ try { // First initialize the ORB, that will remove some arguments... CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "" /* the ORB name, it can be anything! */);
// the real code goes here!
orb->destroy (); } catch (CORBA::Exception &ex) { std::cerr << "CORBA exception raised!" << std::endl; } return 0;}
Client - Manage ORB
Client.cpp
Client - Get Quoter Object Ref
In client.cpp:
#include "QuoterC.h”
CORBA::Object_var factory_object = orb->string_to_object(argv[1]);
Quoter::Stock_Factory_var factory = Quoter::Stock_Factory::_narrow (factory_object.in ());
for (int i = 2; i != argc; ++i)
{
try {
// Get the stock object
Quoter::Stock_var stock = factory->get_stock (argv[i]);
Client.cpp
Implementing Stock InterfaceIn stock_i.cpp
class Quoter_Stock_i : public POA_Quoter::Stock {
public: Quoter_Stock_i (const char *symbol, const char*full_name,
CORBA::Double price);
private: std::string symbol_; std::string full_name_; CORBA::Double price_;
}; Stock_i.cpp
Stock Operations and Attributes
In stock_i.cpp:
class Quoter_Stock_i : public POA_Quoter::Stock { public: // some details omitted char *symbol () throw (CORBA::SystemException); char *full_name () throw (CORBA::SystemException);
CORBA::Double price () throw (CORBA::SystemException); };
// In the .cpp file: char * Quoter_Stock_i::symbol () throw (CORBA::SystemException) { return CORBA::string_dup (this->symbol_.c_str
()); }
Stock_i.cpp
Stock Operations and Attributes
In stock_i.cpp:
class Quoter_Stock_i : public POA_Quoter::Stock { public: // some details omitted char *symbol () throw (CORBA::SystemException); char *full_name () throw (CORBA::SystemException);
CORBA::Double price () throw (CORBA::SystemException); };
// In the .cpp file: char * Quoter_Stock_i::symbol () throw (CORBA::SystemException) { return CORBA::string_dup (this->symbol_.c_str
()); }
Stock_i.cpp
Memory management: must copy string into return since CORBA run-time will free space of return value
POAs
• Servants - program language entities that implement CORBA objects.
• Object adapters - link servants to CORBA Objects• Portable Object Adapters (POA) is standard object adapter
(CORBA 2.2)• POAs:
– create CORBA objects and references– dispatching requests to servants– like “main” in our socket assignment
• Servers may have many POAs, must have at least Root POA
Implement Stock Factory
In stock_factory_I.cpp:
class Quoter_Stock_Factory_i : public POA_Quoter::Stock_Factory
{
public:
Quoter_Stock_Factory ();
Quoter::Stock_ptr get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol);
private:
Quoter_Stock_i rhat_; Quoter_Stock_i msft_; };
Two stocks in factory: RHAT, MSFT
Stock_Factory_i.cpp
Implement Get_Stock Method
In stock_factory_i.cpp
Quoter::Stock_ptr Quoter_Stock_Factory_i::get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol) { if (strcmp (symbol, "RHAT") == 0)
{ return this->rhat_._this(); } else if (strcmp (symbol, "MSFT") == 0)
{ return this->msft_._this (); }
throw Quoter::Invalid_Stock_Symbol (); }
Stock_Factory_i.cpp
Implement Get_Stock Method
In stock_factory_i.cpp
Quoter::Stock_ptr Quoter_Stock_Factory_i::get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol) { if (strcmp (symbol, "RHAT") == 0)
{ return this->rhat_._this(); } else if (strcmp (symbol, "MSFT") == 0)
{ return this->msft_._this (); }
throw Quoter::Invalid_Stock_Symbol (); }
Stock_Factory_i.cpp
_this() is a method that comes to all CORBA classes from inheritance. It creates the object using the POA and returns the object reference.
Implement Server
int main (int argc, char* argv[]) { try { // First initialize the ORB, that will remove some arguments…
CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "" /* the ORB name, it can be anything! */);
CORBA::Object_var poa_object = orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow (poa_object.in ());
PortableServer::POAManager_var poa_manager = poa->the_POAManager ();
poa_manager->activate (); // The application code goes here!
// Destroy the POA, waiting until the destruction terminates poa->destroy (1, 1); orb->destroy (); } catch (CORBA::Exception &ex) { std::cerr << "CORBA exception raised!" <<
std::endl; } return 0; }
Server.cpp
TAO IDL Compilation
Quoter.idl
Stock_i.cpp, Stock_Factory_i.cpp
client.cpp
Quoter serverexecutable
Quoter client execuable
IDL complier
C++ Compiler
Generated Classes and
Headers
QuoterC.h,QuoterC.i,QuoterC.cpp
QuoterS.h,QuoterS.i,QuoterS.cppQuoterS_T.hQuoterS_T.i,QuoterS_T.cpp
server.cpp
%tao_idl Quoter.idl
Example: Remote Quoter Object
A Quoter provides stock quotes to clients
IDL interface to quoter
Client code calls anoperation on remote
quoter objects
Client Process
Server Process
C++ object
REDH$
Other CORBA Object
Server NodeClient Node
MSFT$
IDL the C++ Mapping
• General CORBA mapping of IDL constructs to C++ implementation
• Basic types
• Modules
• Interfaces
• Other IDL types
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server NodeClient Node
MSFT$
Client code gets obj ref from
factory then calls an
operation on remote
quoter objects
Example: Remote Quoter Object
IDL Interface for Quoter module Quoter { interface Stock { double price ();
readonly attribute string symbol; readonly attribute string full_name; };
interface Stock_Factory { Stock get_stock (in string stock_symbol) raises (Invalid_Stock_Symbol); };}
Factory Objects
• Factory design pattern - commonly used in CORBA systems
• Factory object provides access to objects
• Focal point for clients– published to well-known place to clients– clients get this ref to get access to other objects
Factory Objects - Scenarios
• Security– client must provide security info before factory object gives
access
• Load-balancing– factory object manages pool of objects
– assigns them to clients based on some algorithm
• Polymorphism– factory object returns references to different implementations
depending on criteria specified by client
TAO IDL Compilation
Quoter.idl
Stock_i.cpp, Stock_Factory_i.cpp
client.cpp
Quoter serverexecutable
Quoter client execuable
IDL complier
C++ Compiler
Generated Classes and
Headers
QuoterC.h,QuoterC.i,QuoterC.cpp
QuoterS.h,QuoterS.i,QuoterS.cppQuoterS_T.hQuoterS_T.i,QuoterS_T.cpp
server.cpp
%tao_idl Quoter.idl
Write a Client
• Client initializes access to ORB
• Client gets a reference to the desired object
• Calls methods to access the object
In client.cpp:
int main (int argc, char* argv[]){ try { // First initialize the ORB, that will remove some arguments... CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "" /* the ORB name, it can be anything! */);
// the real code goes here!
orb->destroy (); } catch (CORBA::Exception &ex) { std::cerr << "CORBA exception raised!" << std::endl; } return 0;}
Client - Manage ORB
Client.cpp
Client - Get Quoter Object Ref
In client.cpp:
#include "QuoterC.h”
CORBA::Object_var factory_object = orb->string_to_object(argv[1]);
Quoter::Stock_Factory_var factory = Quoter::Stock_Factory::_narrow (factory_object.in ());
for (int i = 2; i != argc; ++i)
{
try {
// Get the stock object
Quoter::Stock_var stock = factory->get_stock (argv[i]);
Client.cpp
Implementing Stock InterfaceIn stock_i.cpp
class Quoter_Stock_i : public POA_Quoter::Stock {
public: Quoter_Stock_i (const char *symbol, const char*full_name,
CORBA::Double price);
private: std::string symbol_; std::string full_name_; CORBA::Double price_;
}; Stock_i.cpp
Stock Operations and Attributes
In stock_i.cpp:
class Quoter_Stock_i : public POA_Quoter::Stock { public: // some details omitted char *symbol_ () throw (CORBA::SystemException); char *full_name () throw (CORBA::SystemException);
CORBA::Double price () throw (CORBA::SystemException); };
// In the .cpp file: char * Quoter_Stock_i::symbol () throw (CORBA::SystemException) { return CORBA::string_dup (this->symbol_.c_str
()); }
Stock_i.cpp
Stock Operations and Attributes
In stock_i.cpp:
class Quoter_Stock_i : public POA_Quoter::Stock { public: // some details omitted char *symbol () throw (CORBA::SystemException); char *full_name () throw (CORBA::SystemException);
CORBA::Double price () throw (CORBA::SystemException); };
// In the .cpp file: char * Quoter_Stock_i::symbol () throw (CORBA::SystemException) { return CORBA::string_dup (this->symbol_.c_str
()); }
Stock_i.cpp
Memory management: must copy string into return since CORBA run-time will free space of return value
POAs
• Servants - program language entities that implement CORBA objects.
• Object adapters - link servants to CORBA Objects• Portable Object Adapters (POA) is standard object adapter
(CORBA 2.2)• POAs:
– create CORBA objects and references– dispatching requests to servants– like “main” in our socket assignment
• Servers may have many POAs, must have at least Root POA
Implement Stock Factory
In stock_factory_I.cpp:
class Quoter_Stock_Factory_i : public POA_Quoter::Stock_Factory
{
public:
Quoter_Stock_Factory ();
Quoter::Stock_ptr get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol);
private:
Quoter_Stock_i rhat_; Quoter_Stock_i msft_; };
Two stocks in factory: RHAT, MSFT
Stock_Factory_i.cpp
Implement Get_Stock Method
In stock_factory_i.cpp
Quoter::Stock_ptr Quoter_Stock_Factory_i::get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol) { if (strcmp (symbol, "RHAT") == 0)
{ return this->rhat_._this(); } else if (strcmp (symbol, "MSFT") == 0)
{ return this->msft_._this (); }
throw Quoter::Invalid_Stock_Symbol (); }
Stock_Factory_i.cpp
Implement Get_Stock Method
In stock_factory_i.cpp
Quoter::Stock_ptr Quoter_Stock_Factory_i::get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol) { if (strcmp (symbol, "RHAT") == 0)
{ return this->rhat_._this(); } else if (strcmp (symbol, "MSFT") == 0)
{ return this->msft_._this (); }
throw Quoter::Invalid_Stock_Symbol (); }
Stock_Factory_i.cpp
_this() is a method that comes to all CORBA classes from inheritance. It creates the object using the POA and returns the object reference.
Implement Server
int main (int argc, char* argv[]) { try { // First initialize the ORB, that will remove some arguments…
CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "" /* the ORB name, it can be anything! */);
CORBA::Object_var poa_object = orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow (poa_object.in ());
PortableServer::POAManager_var poa_manager = poa->the_POAManager ();
poa_manager->activate (); // The application code goes here!
// Destroy the POA, waiting until the destruction terminates poa->destroy (1, 1); orb->destroy (); } catch (CORBA::Exception &ex) { std::cerr << "CORBA exception raised!" <<
std::endl; } return 0; }
Server.cpp
TAO IDL Compilation
Quoter.idl
Stock_i.cpp, Stock_Factory_i.cpp
client.cpp
Quoter serverexecutable
Quoter client execuable
IDL complier
C++ Compiler
Generated Classes and
Headers
QuoterC.h,QuoterC.i,QuoterC.cpp
QuoterS.h,QuoterS.i,QuoterS.cppQuoterS_T.hQuoterS_T.i,QuoterS_T.cpp
server.cpp
%tao_idl Quoter.idl
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server NodeClient Node
MSFT$
Client code gets obj ref from
factory then calls an
operation on remote
quoter objects
Example: Remote Quoter Object
IDL the C++ Mapping
• General CORBA mapping of IDL constructs to C++ implementation
• Basic types
• Modules
• Interfaces
• Other IDL types• Detail: ftp://ftp.omg.org/pub/docs/formal/99-07-41.pdf
Mapping for Basic Types
Mapping for Interfaces
class Quoter_Stock_i : public POA_Quoter::Stock {
public: Quoter_Stock_i (const char *symbol, const char*full_name,
CORBA::Double price);
private: std::string symbol_; std::string full_name_; CORBA::Double price_;
};
interface Stock { double price ();
readonly attribute string symbol; readonly attribute string full_name; };
Mapping for Interfaces
class Quoter_Stock_i : public POA_Quoter::Stock {
public: Quoter_Stock_i (const char *symbol, const char*full_name,
CORBA::Double price);
private: std::string symbol_; std::string full_name_; CORBA::Double price_;
};
interface Stock { double price ();
readonly attribute string symbol; readonly attribute string full_name; };
Class Name = Module Name (Quoter) underscore Interface Name (Stock) underscore i
Mapping for Interfaces
class Quoter_Stock_i : public POA_Quoter::Stock {
public: Quoter_Stock_i (const char *symbol, const char*full_name,
CORBA::Double price);
private: std::string symbol_; std::string full_name_; CORBA::Double price_;
};
interface Stock { double price ();
readonly attribute string symbol; readonly attribute string full_name; };
Inherits From IDL Compiler-generated class POA underscore Module Name :: Interface Name
Mapping Object ReferencesIDL interface type denotes an object reference.
Consider the following example for operation newaccount
// IDLinterface bank { account newAccount (in string name);};
Object reference returned by newAccount maps to a C++ _var type of the same name
Can be invoked as follows:
bank_var b;account_var a;. . .a = b->newAccount(“Vic”);a->makeDeposit(10.0);. . .
Example Quoter Object Ref
In client.cpp:
#include "QuoterC.h”
CORBA::Object_var factory_object = orb->string_to_object(argv[1]);
Quoter::Stock_Factory_var factory = Quoter::Stock_Factory::_narrow (factory_object.in ());
for (int i = 2; i != argc; ++i)
{
try {
// Get the stock object
Quoter::Stock_var stock = factory->get_stock (argv[i]);
Mapping for Derived Interfaces• Inherited interfaces in IDL map to public virtual inheritance in C++
• Example checking account inherits from account interface
interface checkingAccount : account { void overdraftLimit(in float limit);}
• Corresponding C++ class:// C++ generated by IDL compiler
class checkingAccount: public virtual account{ virtual void setOverdraftLimit(CORBA::float limit);}
Mapping for Derived Interfaces
• Use narrow method to cast from base class to derived class
CORBA::Object_var factory_object =
orb->string_to_object(argv[1]);
Quoter::Stock_Factory_var factory =
Quoter::Stock_Factory::_narrow (factory_object.in ());
Mapping struct//IDL struct Time { short hour; short minute; short second; }; void updateTime(in Time current); void currentTime(out Time current);};
// C++ generated by IDL compilerstruct Time { CORBA::short hour; CORBA::short minute; CORBA:: short second; public Time() {} public Time (short hour, short minute, short second) {…}}
Mapping for Constants
Constants are straightforward
//IDL
const short MaxLen = 4;
Maps to C++:// C++ generated by IDL compiler const CORBA::short MaxLen = 4;
Mapping for Exceptions• System Exceptions
– mapped to C++ classes that extend CORBA::SystemException
• User-Defined Exceptions– mapped to C++ class that derives from CORBA::UserException
User Exception Example: Quoter Client
try {
// Now get the price
CORBA::Double price = stock-price ();
catch (Quoter::Invalid_Stock_Symbol &) {
cerr << "Invalid stock symbol <" <<< "" << endl; }
System Exception Example: Quoter Client
try {
CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "");
// the real code goes here!
orb->destroy ();
}
catch (CORBA::Exception &ex) {
std::cerr << "CORBA exception raised!" << std::endl;
}
User Exception Throw Example: Quoter Object
Quoter::Stock_ptr Quoter_Stock_Factory_i::get_stock (const char *symbol) throw (Quoter::Invalid_Stock_Symbol)
{
if (strcmp (symbol, "RHAT") == 0) { return this-rhat_._this (); }
else if (strcmp (symbol, "MSFT") == 0) { return this-msft_._this (); }
throw Quoter::Invalid_Stock_Symbol ();
}
Locating Objects
• What is an object reference?
• Using IIOP:– hostname– port number– object key
• Lifetime of obj ref - as long as these don’t change
Stringified Object References• Two operations on ORB interface for converting obj refs to and from
strings:
module CORBA { interface ORB { string object_to_string(in Object obj); Object string_to_object(in string ref); }}
• Create stringified obj ref• Make string available to clients• Client gets string - converts to obj ref
Stringified Object References
• E.g. CORBA::Object_var factory_object = orb-> string_to_object(argv[1]);
• Using a file– write stringified obj ref to a well-known file
• Using a URL– more flexible - don’t need to share file space– publish obj ref in a file accessible as a URL– client uses HTTP or FTP to get it– well-suited for applets
Connecting to Named Objects
• Use object naming as defined above• iiop notation
iiop://hostname:port/object-name
– can be used anywhere stringified obj ref can be used– Example from TAO– iiop:131.128.81.140:11111/NameService is passed as
parameter in to Quoter client and server.
Example: Name ServerFactory registers Its Obj Ref with NameServer
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server Node
Client Node MSFT$
Client code gets obj ref then calls
anoperation on
remotequoter objects
Name-server
Example: Name ServerClient Get Factory Object Ref From Name Server
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server Node
Client Node MSFT$
Client code gets obj ref then calls
anoperation on
remotequoter objects
Name-server
Example: Name Server
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server Node
Client Node MSFT$
Client code gets obj ref then calls
anoperation on
remotequoter objects
Name-server
Client calls Factory to get Obj Ref of a Quoter Object
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server Node
Client Node MSFT$
Client code gets obj ref then calls
anoperation on
remotequoter objects
Name-server
Client finally calls Quoter object
Example: Name Server
Initial Services
• Can use initial services to get an obj ref
• Obj refs of initial services can be obtained using ORB operation:Object resolve_initial_references(in ObjectId identifier)
raises(InvalidName);
• Initial services have well-known names:– Naming Service: “NameService”– Trading Service: “TradingService”
Resolving an Initial Service
• Connect with the naming service:
#include "orbsvcs/CosNamingC.h"
CORBA::Object_var naming_context_object =
orb->resolve_initial_references ("NameService");
CosNaming::NamingContext_var naming_context =
CosNaming::NamingContext::_narrow (naming_context_object.in ());
Naming Service
• Associate a name with an object reference
• Server “binds” an object to a name
• Client “resolves” name to retrieve object reference
• Provides transparency
• More natural
Name Space Hierarchy
• Naming service provides hierarchy of names
• name-to-object association = name binding
• name binding always defined relative to a naming context
• naming context is an object that contains a set of name bindings– each name unique within context
Names
• name = ordered sequence of components
• component consists of two attributes– identifier - represents string name– kind - represents description of type of object
• not used by CORBA - only by application program
• Ex:
NameComponent[] name = new NameComponent[1];name[0] = new NameComponent(“bank”,”financial”);
Naming Contexts
• Creates a naming scope for a set of objects
• Analogous to directory in a file system
• Context can contain other contexts– creates hierarchy– sets up a path to a name
Name Context Example
Root Context
FleetBank BankBoston CitiBank
Boston Providence Providence ProvidenceBoston Boston
• Hierarchy always begins with root naming context• Default context if none is created• FleetBank, BankBoston and CitiBank all define contexts• Names within the contexts are unique• No problem with duplicate names among contexts
•context hierarchy defines path to object name
Binding Objects
• Naming Service supports four operations to create bindings:
void bind(in Name n, in Object obj) raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
void rebind(in Name n, in Object obj) raises(NotFound, CannotProceed, InvalidName);
void bind_context(in Name n, in NamingContext nc) raises(NotFound, CannotProceed, InvalidName, AlreadyBound);
void rebind_context(in Name n, in NamingContext nc) raises(NotFound, CannotProceed, InvalidName);
Binding Objects
• bind - creates a binding of a name and an object in the current naming context
• rebind - creates a binding of a name and an object in the naming context even if the name is already bound in the context
• bind_context - names an object that is a naming context
• rebind_context - creates a binding of a name and a naming context in the specified naming context even if the name is already bound in the context
Exceptions
• NotFound - name does not identify a binding• CannotProceed - implementation has given up
for some reason• InvalidName - name is not valid - correct
format for name• AlreadyBound - object already bound to the
specified name
Resolving Names
• resolve - process of retrieving an object bound to a name in a given context
• Name must match exactly• Naming Service does not return the type of the object• Client is responsible for narrowing to the desired type
Object resolve(in Name n) raises(NotFound, CannotProceed, InvalidName);
Unbinding Names
• unbind - removes a name binding from a context
void unbind (in Name n) raises (NotFound, CannotProceed, InvalidName);
Creating Naming Contexts
• new_context - returns a naming context implemented by the same naming server as the context on which the operation was invoked– not bound to any name
• bind_new_context - creates a new context and binds it to the specified name– implemented in the same server as the context in which it was bound
NamingContext new_context();
NamingContext bind_context(in Name n) raises(NotFound, AlreadyBound, CannotProceed, InvalidName);
Deleting Contexts
• destroy - deletes a naming context
void destroy() raises(NotEmpty);
IDL interface to quoter
Client Process Server Process
C++ object
REDH$
Factory
Server Node
Client Node MSFT$
Client code gets obj ref then calls
anoperation on
remotequoter objects
Name-server
Client finally calls Quoter object
Example: Name Server
Example: Quoter Server With NameServer
#include "orbsvcs/CosNamingC.h"
CORBA::Object_var naming_context_object =
orb->resolve_initial_references ("NameService");
CosNaming::NamingContext_var naming_context =
CosNaming::NamingContext::_narrow (naming_context_object.in ());
CosNaming::Name name (1);
name.length (1);
name[0].id = CORBA::string_dup ("Stock_Factory");
naming_context->bind (name, stock_factory.in ());
In server.cpp
Example: Quoter Client With NameServer
#include "orbsvcs/CosNamingC.h"
CORBA::Object_var naming_context_object = orb->resolve_initial_references ("NameService"); CosNaming::NamingContext_var naming_context = CosNaming::NamingContext::_narrow (naming_context_object.in ());
CosNaming::Name name (1);name.length (1);name[0].id = CORBA::string_dup ("Stock_Factory");
CORBA::Object_var factory_object = naming_context->resolve (name);Quoter::Stock_Factory_var factory = Quoter::Stock_Factory::_narrow (factory_object.in ());
In server.cpp
Portable Object Adapter (POA)
• Adapts programming lang servants to CORBA objects
• Fits between ORB core and static and dynamic skeletons
• Provides policies for creation and maintenance of objects in a CORBA application
Object Adapters
• General construct on which POA is based
• Original CORBA spec had BOA (Basic Object Adapter)
• Too vague– vendors had to add a lot of proprietary features
• OMG developed POA to replace BOA
Terminology
• CORBA object - “virtual” entity capable of being located by an ORB and having client requests delivered to it
• Servant - programming lang entity that exists in the context of a server and implements a CORBA object
• Skeleton - programming lang entity that connects a servant to an OA - allowing OA to dispatch requests to a servant
• Object Id - user or system-defined identifier used to “name” an object in scope of OA– unique to OA
Terminology• Activation - starting an existing CORBA object to allow it to
service requests
• Deactivation - shutting down an active CORBA object– requires destruction of association between CORBA object and servant– can be reactivated to receive more requests
• Incarnation - associating a servant with a CORBA object
• Etherealization - destroying association between CORBA object and servant
• Active Object Map - table maintained by OA
– maps active CORBA objets to associated servants
Object Adapter Functionality
• Request demultiplexing– demultiplex CORBA calls to appropriate servant
– when ORB core receives request - cooperates with OA to ensure request reaches proper servant
• Operation dispatching– locates target servant
– dispatches requested operation
– skeleton used to transform params in request to args of operation
Object Adapter Functionality
• Activation and deactivation– activate CORBA objects
– incarnate servants to handle requests for the objects
– deactivate objects and etherealize corresponding servants
• Generating object references– OA generates obj refs for CORBA objects registered with
it
POA Features
• Object Identifier– ObjectID - used to identify CORBA object within
POA
– invisible to clients - they use obj ref
– can be assigned by application or POA
– object key used by ORB to locate CORBA object
– may specify POA and ObjectID
POA Features
• Persistent vs. Transient Objects– Persistent - lifetime of object independent of
lifetime of server process in which it is activated
• can be activated when necessary
– Transient - lifetime of object bound by lifetime of server in which it is created
• less overhead - no activation information necessary
POA Features• Activation - POA support following styles:
– Explict - application programmer registers servants for CORBA objects using direct calls on POA
– On-demand - application programmer registers servant manager that POA upcalls when it receives a request for a CORBA object not yet activated
– Implicit - an action on a servant results in activation without any explicit calls on POA
• C++ - use servant’s _this method– Default servant - application registers a default servant to
handle any calls on CORBA objects not yet activated
POA Policies
• Root POA - obj ref available from the ORB
• Create new POA by calling create_POA on root POA
• Server can have multiple POAs– support different kinds of objects– characteristics of POA controlled by setting up
policies at creation time
POA Policies• Threading Policy
– single-threaded• all requests POA dispatches are serialized• using single thread• multiple threads synchronized to execute serially
– ORB-controlled threading• ORB determines thread or threads on which POA dispatches
requests
– Limitations - not flexible enough• can’t specify thread pool• can’t specify thread-per-CORBA object
POA Policies
• Servant Retention Policy– RETAIN
• retains associations between servants and CORBA objects
• most widely used
– NON-RETAIN• establishes new CORBA object -> servant assocation for
each incoming request• allows application to supply its own servant manager
that intervenes in every request dispatch
POA Policies
• Request Processing Policy– Consult active object map (only)
• throws exception if requested object not in map
– Use default servant• invoked whenever POA has no servant associated with
ObjectID of requested object in active object map
– Invoke servant manager• application-supplied CORBA object that can incarnate or
activate a servant and return it to the POA
POA Policies• Implicit Activation Policy
– Servant can be activated implicitly if policy supported
• ObjectID Uniqueness Policy– Determines if servant can be associated with only one or with
multiple CORBA objects
• Lifespan Policy– Determines if objects in POA are persistent or transient– Must be determined at POA creation
• ObjectID Assignment Policy– Determines whether ObjectIDs are POA assigned or supplied by
application
POA Example: Quoter Server
int main (int argc, char* argv[]) { try { // First initialize the ORB, that will remove some arguments…
CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "" /* the ORB name, it can be anything! */);
CORBA::Object_var poa_object = orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow (poa_object.in ());
PortableServer::POAManager_var poa_manager = poa->the_POAManager ();
poa_manager->activate (); // The application code goes here!
// Destroy the POA, waiting until the destruction terminates poa->destroy (1, 1); orb->destroy (); } catch (CORBA::Exception &ex) { std::cerr << "CORBA exception raised!" <<
std::endl; } return 0; }
In server.cpp
Example: Quoter POA Implicit Servant Activation
In stock_factory_i.cpp
Quoter::Stock_ptr Quoter_Stock_Factory_i::get_stock (const char *symbol)
throw (Quoter::Invalid_Stock_Symbol) { if (strcmp (symbol, "RHAT") == 0)
{ return this->rhat_._this(); } else if (strcmp (symbol, "MSFT") == 0)
{ return this->msft_._this (); }
throw Quoter::Invalid_Stock_Symbol (); }
_this() is a method that comes to all CORBA classes from inheritance. It creates the object using the POA and returns the object reference.
Event Service
• Provides decoupled communication model between objects
• Broadcast nofitication of named events for synchronization
• Supports typed events using IDL
• Supports non-typed events via any
Example Scenarios
• System admin tool interested in knowing if disk runs out of space– software reports that disk is full
– system admin tool notifies user
• CASE tool interested in being notified when a source program has been modified– source program reports when modified
– unaware of existence of CASE tool
– CASE tool invokes compiler when event occurs
Event Communication
• Two roles for objects:– supplier - produces event data– consumer - processes event data
• Two approaches to initiating event communication– push model - supplier initiates transfer of event data to
consumers– pull model - consumer requests event data from
supplier
Pull Consumer
• Obtain object reference to an event channel
• Invoke on event channel to get Consumer Admin object
• Invoke on Consumer Admin object to get ProxyPullSupplier
• Request data from event channel
interface PullConsumer { void disconnect_pull_consumer();};
Pull Supplier
• Obtain object reference to an event channel
• Invoke an event channel to get Supplier Admin object
• Invoke on Supplier Admin object to get ProxyPullConsumer
• Wait for incoming – pull() - blocks until event data is visible or exception is raised– try_pull - does not block - returns event data if available
interface PullSupplier { any pull() raises(Disconnected); any try_pull(out boolean has_event) raises(Disconnected); void disconnect_pull_supplier();};
Push Consumer
• Obtain object reference to an event channel
• Invoke on event channel to get Consumer Admin object
• Invoke on Consumer Admin object to get ProxyPushSupplier
• Wait for push() from event channel
interface PushConsumer { void push(in any data) raises(Disconnected); void disconnect_push_consumer();};
Push Supplier
• Obtain object reference to an event channel
• Invoke on event channel to get Supplier Admin object
• Invoke on Supplier Admin object to get ProxyPushConsumer
• Push data into event channel via ProxyPushConsumer
interface PushSupplier { void disconnect_push_supplier();};
Event Channel
PushSupplier
PullSupplier
ProxyPushConsumer
ProxyPullConsumer
ProxyPushSupplier
ProxyPullSupplier
PushConsumer
PullConsumer
SupplierAdmin ConsumerAdmin
• Object that allows multiple suppliers to communicate with multiple consumers
• Both a consumer and a supplier of events
Event Channel IDLmodule CosEventChannelAdmin {
exception AlreadyConnected {}; exception TypeError {};
interface ProxyPushConsumer: CosEventComm::PushConsumer { void connect_push_supplier(in CosEventComm:: PushSupplier push_supplier) raises(AlreadyConnected); };
interface ProxyPullSupplier: CosEventComm::PullSupplier { void connect_pull_consumer(in CosEventComm:: PullConsumer pull_consumer) raises(AlreadyConnected); };
Event Channel IDL interface ProxyPullConsumer: CosEventComm::PullConsumer { void connect_pull_supplier(in CosEventComm:: PullSupplier pull_supplier) raises(AlreadyConnected,TypeError); };
interface ProxyPushSupplier: CosEventComm::PushSupplier { void connect_push_consumer(in CosEventComm:: PushConsumer push_consumer) raises(AlreadyConnected, TypeError); };
interface ConsumerAdmin { ProxyPushSupplier obtain_push_supplier(); ProxyPullSupplier obtain_pull_supplier(); };
Event Channel IDL
interface SupplierAdmin { ProxyPushConsumer obtain_push_consumer(); ProxyPullConsumer obtain_pull_consumer(); };
interface EventChannel { ConsumerAdmin for_consumers(); SupplierAdmin for_suppliers(); void destroy(); };};
Example - Push Supplierpackage event;import org.omg.CORBA.*;import org.omg.CosEventComm.*;class PushSupplier_impl extends _PushSupplierImplBase implements Runnable{
private ORB orb_; private BOA boa_; private PushConsumer consumer_; // represents event channel PushSupplier_impl(ORB orb, BOA boa, PushConsumer consumer) { orb_ = orb; boa_ = boa; consumer_ = consumer; } public void disconnect_push_supplier() { consumer_.disconnect_push_consumer(); consumer_ = null; }
Example - Push Supplier
// Supply date and time public void run() { // Main loop while(consumer_ != null) { java.util.Date date = new java.util.Date(); String s = "PushSupplier says: " + date.toString(); Any any = orb_.create_any(); any.insert_string(s); try { // Push event data into event channel consumer_.push(any); } catch(Disconnected ex) { boa_.deactivate_impl(null); return; }
Example - Push Supplier
catch(COMM_FAILURE ex) { boa_.deactivate_impl(null); throw new COMM_FAILURE(); } Thread.yield(); try { Thread.sleep(1000); } catch(InterruptedException ex) { } } boa_.deactivate_impl(null); }}
Example - Push Consumerpackage event;
import org.omg.CORBA.*;import org.omg.CosEventComm.*;
class PushConsumer_impl extends _PushConsumerImplBase{ private BOA boa_; private PushSupplier supplier_; PushConsumer_impl(BOA boa, PushSupplier supplier) {
boa_ = boa; supplier_ = supplier; } public void disconnect_push_consumer() {
supplier_.disconnect_push_supplier();boa_.deactivate_impl(null);
}
Example - Push Consumer
public void push(Any any) { // Display event data if Any is a string
try { String s = any.extract_string(); System.out.println(s);}catch(MARSHAL ex){}
}}
ORB Interoperability
• CORBA 1.0 - up to vendors to implement a protocol for ORBs to communicate over a network
• ORBs could not communicate with each other• CORBA 2.0 (and further) provides
methodology for ORBs to communicate• GIOP - collection of message requests ORBs
can make over a network
ORB Interoperability• OMG describes interoperability in terms of
domains and bridges
• Domains
Domains• Set of objects which are separated from other
objects– for administrative or implementational reasons
• Examples:– Administrative
• naming domains, trust groups, resource management, similar “run-time” characteristics
– Implementational• common protocols, common syntaxes, similar “build-time”
characteristics
Bridges
• Implementations that convert requests between different domain models
• Mapping between domains
• IIOP is the most common ORB bridge
• Translate requests from one ORB to another
• Support management of key tables for object references
Bridges• Two types of bridges:
– Mediated bridging:• interacting elements of different domains are transformed to a mutually agreed
upon form• common form could be standard (like IIOP) or a private agreement between the
two parties
– Immediate bridging:• interacting elements are transformed directly between the internal forms of one
domain to another• faster but less general• often used when crossing domain boundaries that are purely administrative -
security boundaries between similar ORBs
GIOP• GIOP - General Interoperability Protocol
• Maps ORB requests to different network transports
• Analogous to IDL mappings– IDL provides framework for language– need mappings to implementation languages
• GIOP provides framework for communication– need mappings to actual transport protocols
GIOP• OMG defines three parts of GIOP:
– Common Data Representation (CDR)• transfer syntax for mapping IDL to low-level types
between network agents
– GIOP message formats (seven in all)Message Type Originator Value (enum)------- --------------- ------------Request Client 0Reply Server 1CancelRequest Client 2LocateRequest Client 3LocateReply Server 4CloseConnection Server 5MessageError Both 6
GIOP
– GIOP message-transport assumptions• connection-oriented
• reliable
• can be viewed as a byte stream
• provides reasonable notification of connection loss
• model for initiating connections can be mapped onto the general connection model of TCP/IP
Transport Protocols for GIOP• IIOP - Internet Interoperability Protocol
– standardized version that all ORBs must be able to use
– maps GIOP messages to TCP/IP
– ORB uses the internet as a communication bus
• ESIOP - Environment-Specific Interoperability Protocol– maps GIOP messages to a proprietary network protocol
– e.g. DCE (Distributed Computing Environment)
IOR
• Interoperable Object Reference (IOR)– provides a reference that objects in one ORB
can use to access objects in other ORBs
• IOR is created and used when bridging between different reference domains
• Managed internally by the interoperating ORBs
IORmodule IOP { typedef unsigned long ProfileId; const PrifileId TAG_INTERNET_IOP = 0; const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
struct TaggedProfile { PrifileId tag; sequence profile_data; }; struct IOR{ string type_id; sequence profiles; // object specific protocol profiles }; typedefunsigned long ComponentId; struct TaggedComponent { ComponentId tag; sequence component_data; }; typedef sequence MultipleComponentProfile;};
IIOP
• Objects publish object references in IORs called IIOP profiles
module IIOP{ struct Version { char major; char minor; };
struct ProfileBody { Version iiop_version; // version of IIOP at target address string host; // IP host to which messages are sent unsigned short port; // TCP/IP port number of target object sequence object_key; // reference of target object };};
IIOP Example - IDL
interface grid { readonly attribute short height; readonly attribute short width;
void set(in short row, in short col, in long value); void get(in short row, in short col);};
IIOP Example - Serverimport CosNaming.*;import org.omg.CORBA.SystemException;import org.omg.CORBA.UserException;import org.omg.CORBA.Object;
class gridserver { public static void main(String args[]) { // Assume TIE approach. grid gridImpl; ORB orb; // Declare Naming service types. Object initRef; NamingContext initContext; NamingContext objectsContext; NamingContext mathContext; NameComponent[] name;
IIOP Example - Server try { // Create implementation object. gridImpl = new _tie_grid (new gridImplementation(100,100)); // TIE object automatically identified using an IOR } catch (SystemException se) { // Details omitted. } try { // Find initial naming context. orb = ORB.init(args,null); initRef = orb.resolve_initial_references("NameService"); initContext = NamingContextHelper.narrow(initRef); name = new NameComponent[1]; name[0] = new NameComponent("objects",""); objectsContext = initContext.bind_new_context (name); name[0].id = new String ("math"); name[0].kind = new String ("");
IIOP Example - Server mathContext = objectsContext.bind_new_context (name); name[0].id = new String ("grid"); name[0].kind = new String (""); mathContext.bind (name, gridImpl); // associates compound name objects.math.grid with IOR } catch (SystemException se) { // Details omitted. } catch (UserException ue) { // Use the exceptions defined in the // COSNaming IDL } orb.connect(gridImpl); try { Thread.sleep(1000*60*3); } catch (InterruptedException ex) { // Details omitted. }}
IIOP Example - Clientimport CosNaming.*;import IE.Iona.OrbixWeb._CORBA;import org.omg.CORBA.SystemException;import org.omg.CORBA.UserException;import org.omg.CORBA.Object;public class Client { public static void main (String args[]) { NamingContext initContext; NameComponent[] name; ORB orb; Object initRef, objRef; grid gRef; try { orb = ORB.init(args,null); String NSstring = // stringified ref of server’s NS initRef = string_to_object(NSstring); initContext = NamingContext.narrow(initRef); name = new NameComponent[3]; name[0] = new NameComponent ("objects","");
IIOP Example - Client name[1] = new NameComponent ("math",""); name[2] = new NameComponent ("grid",""); objRef = initContext.resolve (name); gRef = grid.narrow (objRef); } catch (SystemException se) { // Details omitted. } catch (UserException ue) { // Use exceptions defined in the COSNaming IDL } try { w = gRef.width(); h = gRef.height(); } catch (SystemException se) { // Details omitted. }
IIOP Example - Client
System.out.println("height is " + h); System.out.println("width is " + w); try { gRef.set((short)2,(short)4,123); v = gRef.get((short)2,(short)4); } catch (SystemException se) { // Details omitted. } System.out.println( "value at grid position (2,4) is " + v); }}