Grosso, [email protected] (C) 1999, all rights re CORBA
Dec 26, 2015
William Grosso, [email protected] (C) 1999, all rights reserved
CORBA
This LectureCommon Object Request Broker
Architecture (CORBA)Start with Limo example to illustrate
general principles (and IDL syntax)Naming Service
Recall: SocketsStreams-based communication between
any two computers on a networkNo requirement that the both client and
server use Java (language independence)Connection, location, and lifecycle
management written by application programmers
Application programmers must convert data and method calls into and out of stream format (marshalling)
Recall: RMILayer on top of SocketsHas solutions for all the Socket red stuff
Connection management and marshalling is in the stubs
Location management via the registry Lifecycle management via activation
Both client and server must be Java Distributed garbage collection, Can pass (serializable) objects by value
What is CORBASpecification for distributed object
communications Defined and maintained by the Object
Management Group (www.omg.org) Location transparency and object activation are
fundamental to the specificationLanguage independent and platform
neutralLarge number of extensions (Services and
Facilities) designed by industry working groups
The Object Management GroupIndustry consortiumAt this point, about
800 members Various types of
members;Some voteSome just serve on
task forces
OMG Board
Architecture Board
Task Forces
History of CORBA1989: OMG founded by 8 members1991: CORBA 1.1
Includes IDL and basic functionality definitions
No real specifications for interoperability1994: CORBA 2.0
Interoperability (GIOP) and the BOA definedCurrently: CORBA 2.4
Minor modifications to 2.0, the definition of the POA, and objects-by-value
Reference Model
Object Request Broker (ORB)
Application Objects
Services
Facilities
Process-Level Schematic
GIOP / IIOP (Wire protocol)
ClientObject
Static Stubs
Dynamic Invocation
Orb Functionality
InterfaceRepository
ImplementationRepository
ServerObject
staticSkeletons
Dyunaic SkeletonInterface
Orb Functionality and Object Adapters
The ORBThe ORB, and the associated object
adapters, define the infrastructure for client-server programming
More conceptual than architectural There is no distinct process you can point to
and say “that’s the orb” It’s a library you link into your code
A client uses an object reference and a method call (in the client language) ORB handles the rest of the networking details
IIOP ORB IndependenceThe ORB is a message bus that takes
client language message calls and translates them into IIOP invocations
The ORB is a message bus that takes IIOP invocations and translates them into server language method calls
Works across vendors Code can be ported to a different vendor Client and server don’t need to be using
same vendor’s orb
CORBAServicesIdea: standardize common servers and
design decisionsThese are not things in the environment
(like printers) so much as objects that most developers, across most domains, use
Examples: Naming, Trader, Events, Lifecycle, Transaction, Properties
You can go out and buy an event service and plug it into your orb
CORBAFacilitiesOriented towards the end-user, rather
than the developerPartially abstractions of standard
environmental features Printing Facility Systems Management Facility
Also contains things like a document model (pretty much OpenDoc) and the Mobile Agent Facility
Interface Definition LanguageRemember-- CORBA wants to be
platform and language independentWhat does this mean ?
You can write a client in one language You can have an already existing server
written in another language CORBA will connect them
The way CORBA achieves this is through IDL
Define Interfaces in IDLRigorously defined language for
specifying an API Method definitions, but no computational
constructsC++ like syntax (and preprocessor)CORBA spec contains a complete
definition of IDL and a set of mappings from IDL to target languages Other groups have proposed additional
mappings
Language Independence ?
Server Interfaces Defined in IDL
Skeleton
StubSkeleton
Stub Stub
Skeleton
Stub
Skeleton
IDL Compilers use mappings togenerate stubs and skeletons in target languages
The CORBA Development CycleWrite IDL definitionsCompile IDL to java
Javasoft has idltojava, Visigenic has idl2java, ...
This will give you stubs and skeletonsWrite the server and client code in JavaUse javac to compile the programs Configure the deployment environment
Recall our Banking ProgramWe had a set of bank account objects,
which could be found by using the owner’s name.
Each object function as a small serverPersistence was handled by a
background threadDeactivation handled by use of
Unreferenced and the activation framework
BankAccount
public interface BankAccount extends Remote{ public String getOwner() throws RemoteException; public float getBalance() throws RemoteException; public boolean withdrawCash(float amount) throws RemoteException; public boolean depositCash(float amount) throws RemoteException;}
IDL for a Similar Server
module grosso { module simplebank { exception NegativeAmountException{}; exception OverdraftException { boolean succeeded; }; interface BankAccount{ attribute string owner; readonly attribute float balance; void withdrawCash(in float amount) raises (NegativeAmountException, OverdraftException); void depositCash(in float amount) raises(NegativeAmountException); }; };};
The Structure of IDLAbstract specification languageSyntax derived from C++
C++ style comments All declarations end in semicolons Standard preprocessor commands (#ifdef,
#define, #include, #pragma)Case sensitive but with an exclusionary rule
Two constructs cannot upper-case to the same string
All identifiers start with a letter
Basic Types in IDLData Type Definition Definition[unsigned] short 16 bit, specified via 2’s complement unsigned short trade_balance;
short number_of_legs;[unsigned] long 32 bit, specified via 2’s complement unsigned long height_in_millimeters;
long nanoseconds_until_equinox;[unsigned] long long 64 bit long long atoms_in_universe;float 16 bit, IEEE standard float grade_point_average;double 32 bit, IEEE standard double temperature;long double 64 bit precision long double pi;char ISO Latin-1 character char monogram_initial;wchar Unicode 16 bit representation wchar name_in_swedish_characters
boolean two values: TRUE and FALSE boolean alive;
string variable length sequence of characters string first_name;
wstring variable length sequence of wchars wstring first_name;octet 8 bits, completely uninterpreted octet identifying_bits;enum enumerated type, boils down to named
integersenum color_list {red, blue, green, mauve};
any Generic type, similar to void * with reflectionadded. Can represent any IDL type (basic orconstructed, object or non-object)
any foo;
StructsDeclared using the keyword structCan contain any other types (including
structs and objects)
struct BugDescription { species bug_species; string first_name; string last_name; unsigned short number_of_legs; unsigned short calories_when_used_as_salad_topping;};
struct Species{ kingdom kingdom; // an enumerated type defined earlier phylum phlya; // an enumerated type defined earlier string formal_name;};
ExceptionsAlmost exactly like structsAlso define typesCan be passed as arguments or
returned as valuesCan also be raised by methods
enum Rationale { bug_never_existed, bug_escaped, bob_ate_it};
exception BugNotFound{ bug_description the_bug; rationale why_missing;};
Template TypesSequences and arrays are the standard
containers
Usually typedef’d as well (must be typedef’d to be used as argument or return types in a method call)
sequence <type[, max length]> variable_nametype[int][int] variable_name
typedef sequence<Book, 30> BookShelf;typedef Book[30] BookShelf;typedef sequence <Book> UnboundedBookShelf;
typedef LastName string<30>
TypedefsTypes are frequently aliased and
renamed in IDL.This is especially true for structs and
template types
typedef old_type_name new_type_name;
typedef template_definition new_type_name ;
AttributesAn attribute is simply shorthand for
declaring an accessor/mutator pair
Nice part of this: exact syntax of accessor/mutator is specified in the language mapping (according to the local idiom)
Attributes can be readonly
attribute string food;attribute long height, width, depth;
readonly attribute string food;
Method CallsGeneral syntax is a little more complex
than in Javadelivery-style return-type method-name
(comma delimited sequence of arguments)raises (comma delimited sequence of exceoptions);
Delivery StyleIf omitted, defaults to synchronous
delivery Has at-most-once semantics Caller blocks until method returns or exception
is thrownCan be specified as oneway
best-effort semantics Cannot have any return values or raise
exceptions Message is sent and client immediately
continues processing
ArgumentsEvery argument must have a
directional indicator in: this argument is sent to the server, but
need not be sent back out: this argument is, in essence, a return
value inout: this argument is sent to the server.
The server will also send back a value for this argument to assume
InterfacesInterfaces define Servers.
They define “object” in CORBA Interfaces are like objects that extend
Remote in RMISupport multiple inheritance
interface BankAccount { attribute string owner; readonly attribute float balance; void withdrawCash(in float amount)
raises (NegativeAmountException, OverdraftException); void depositCash(in float amount) raises(NegativeAmountException); };
ModulesA module is a grouping mechanism,
much like a package in JavaModules can contain other modulesScoping of references is done with
the :: operator containing-module::inner-
module::interface
Event Channel IDL// CosEventComm.idl
#pragma prefix "omg.org"
module CosEventComm { exception Disconnected {}; interface PushConsumer { void push(in any data) raises(Disconnected); void disconnect_push_consumer(); }; interface PushSupplier { void disconnect_push_supplier(); }; interface PullSupplier { any pull() raises(Disconnected); any try_pull(out boolean has_event) raises(Disconnected); void disconnect_pull_supplier(); }; interface PullConsumer { void disconnect_pull_consumer(); };};
Event Channel IDL II// CosEventChannelAdmin.idl
#include "CosEventComm.idl"
#pragma prefix "omg.org"
module 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); }; interface ProxyPullConsumer : CosEventComm::PullConsumer { void connect_pull_supplier(in CosEventComm::PullSupplier pull_supplier) raises(AlreadyConnected); }; interface ProxyPushSupplier : CosEventComm::PushSupplier { void connect_push_consumer(in CosEventComm::PushConsumer push_consumer) raises(AlreadyConnected); };
Event Channel IDL IIIinterface ConsumerAdmin { ProxyPushSupplier obtain_push_supplier(); ProxyPullSupplier obtain_pull_supplier(); };
interface SupplierAdmin { ProxyPushConsumer obtain_push_consumer(); ProxyPullConsumer obtain_pull_consumer(); };
interface EventChannel { ConsumerAdmin for_consumers(); SupplierAdmin for_suppliers(); void destroy(); };
interface EventChannelFactory {
exception AlreadyExists {}; exception ChannelsExist {}; EventChannel create(); EventChannel create_by_name(in string name) raises(AlreadyExists); EventChannel lookup_by_name(in string name); void destroy() raises(ChannelsExist);
};};
Limos Revisited
Remote
RemoteObject
UnicastRemoteObject Dispatcher Limo
DispatcherImpl LimoImpl
DriverLocationPassenger
Serializable
RemoteServer
Limo in IDLmodule grosso{ module corbalimo{ struct Location { short x; short y; }; struct Passenger{ Location starting_location; Location destination; }; struct Driver{ string name; };
interface Limo; // Forward declaration to break compiler // circularity
interface Dispatcher{ Limo hailLimo(in Passenger new_passenger); void limoAvailable(in Limo limo); void limoUnavailable(in Limo limo); };
Limo in IDL
//....
interface Limo { attribute Dispatcher current_ispatcher; readonly attribute Location current_location; readonly attribute Driver current_driver; boolean getIsCarryingPassenger(out Passenger current_passenger);
/* multiple return values */ boolean wantPassenger(in Passenger possible_passenger); boolean pickupPassenger(in Passenger new_passenger); }; };};
The CORBA Development CycleWrite IDL definitionsCompile IDL to java
Javasoft has idltojava, Visigenic has idl2java, ...
This will give you stubs and skeletonsWrite the server and client code in JavaUse javac to compile the programs Configure the deployment environment
Break Time
Compiling is SimpleORB vendors are required to provide
an IDL to Java compiler that implements the standard mapping Input: IDL Output: Java source code
Warning: vendors frequently implement other mappings as well
idl2java BankAccount.idl -strict -portable -VBJvmflag ”-Xbootclasspath:%CLASSPATH_WITHOUTINTERBASE%"
idltojava -fno-cpp -ftie limo.idl
The Mapping is more Complicated
Conceptual Mappings
IDL Concept Java Concept Discussionmodule package Modules inside other modules map to
subpackagesexception class which extends
org.omg.CORBA.UserExceptionMust be caught in client code
in argument ordinary java argumentout argument “holder” class, related to the type declared in
the IDLOut, and inout, arguments are impossible todirectly handle in Java. Instead, we use awrapper class whose value can be set.
attributes reader/writer methods These, alas, do not conform to beans names.Instead, they simple overload the attributesname.
Mapping Basic Types
IDL Basic Type Java Type Discussion[unsigned] short short[unsigned] long int
[unsigned] long long longfloat floatdouble doublelong double NONE YET As the spec evolves, this will probably map
to java.math.BigDecimalchar charwchar char
boolean boolean
string java.lang.Stringwstring java.lang.Stringoctet byteany the Java class org.omg.CORBA.Any
Mapping Constructed Types
IDL Constructed Type Java Type Discussionsequence array Not to Collections classes at all. But simply
to arrays. This preserves strong typing, but issomewhat foreign to Java.
array array Not to Collections classes at all. But simplyto arrays. This preserves strong typing, but issomewhat foreign to Java.
struct A Java class in the appropriate package Actually, three classes are defined for structsand enums. Namely, the base class, a helperclass, and a holder class.
enum A Java class in the appropriate package andwith the same name as the enumerated type
typedef Automatically translated to original nameinterface An interface in the appropriate package. Also has a helper and a holder.
HoldersProblem: out, and inout, arguments do
not correspond to anything in the java language
Solution: Wrap the value in a holder class which can read and write the argument to a stream
Method calls which have out, or inout, arguments take a holder class instead of the original type Additional complexity for client side developer
public interface Limo extends org.omg.CORBA.Object { public void current_ispatcher(grosso.corbalimo.Dispatcher current_ispatcher); public grosso.corbalimo.Dispatcher current_ispatcher(); public grosso.corbalimo.Location current_location(); public grosso.corbalimo.Driver current_driver(); public boolean getIsCarryingPassenger(grosso.corbalimo.PassengerHolder
current_passenger ); public boolean wantPassenger(grosso.corbalimo.Passenger possible_passenger); public boolean pickupPassenger(grosso.corbalimo.Passenger new_passenger );}
Holders in Limo interface Limo { attribute Dispatcher current_ispatcher; readonly attribute Location current_location; readonly attribute Driver current_driver; boolean getIsCarryingPassenger(out Passenger current_passenger);
/* multiple return values */ boolean wantPassenger(in Passenger possible_passenger); boolean pickupPassenger(in Passenger new_passenger); };
becomes
PassengerHolderpackage grosso.corbalimo; final public class PassengerHolder implements org.omg.CORBA.portable.Streamable { public grosso.corbalimo.Passenger value; public PassengerHolder() { } public PassengerHolder(grosso.corbalimo.Passenger value) { this.value = value; } public void _read(org.omg.CORBA.portable.InputStream input) { value = grosso.corbalimo.PassengerHelper.read(input); } public void _write(org.omg.CORBA.portable.OutputStream output) { grosso.corbalimo.PassengerHelper.write(output, value); } public org.omg.CORBA.TypeCode _type() { return grosso.corbalimo.PassengerHelper.type(); }}
AnyGeneric type, similar to void * with
reflection added. Can represent any IDL type (basic or constructed, object or non-object)
Used in IDL as a typeCorresponds to org.omg.CORBA.Any
Any Methodsboolean equal(Any a) ;
Any extract_any() ;boolean extract_boolean(); char extract_char() ;char extract_wchar(); String extract_string(); String extract_wstring(); BigDecimal extract_fixed(); double extract_double(); float extract_float() ;short extract_short() ; short extract_ushort(); int extract_long(); int extract_ulong(); long extract_longlong(); long extract_ulonglong(); Object extract_Object(); byte extract_octet(); TypeCode extract_TypeCode(); TypeCode type() ;void type(TypeCode t);
insert_any(Any a); insert_boolean(boolean b); insert_char(char c) ;insert_wchar(char c); insert_string(String s); insert_wstring(String s); insert_fixed(BigDecimal bD); insert_double(double d); insert_float(float f); insert_short(short s); insert_ushort(short s); insert_long(long l) ;insert_ulong(long l); long insert_longlong(long l); insert_ulonglong(long l) ;insert_Object(Object o); insert_Object(Object o, TypeCode t);insert_octet(byte b);
HelpersEvery constructed type has an
associated Helper class as wellHelpers extend the CORBA type system
to deal with your object definitionsThey have static methods to
Insert and extract instances from an Any Get typecodes Perform narrowing (down-casting)
operations
Helpers and NarrowingInterfaces in IDL have an inheritance
hierarchyJava is a single (implementation)
inheritance languageSuppose FastLimo was a sub-class of
Limo in our IDL
The FastLimo Hierarchy
_LimoImplBase
org.omg.CORBA.DynamicImplementation
_LimoStub
Limo
_LimoOperations
_LimoTie
org.omg.CORBA.Object
FastLimo
_FastLimoImplBase_FastLimoStub
_FastLimoOperations
_FastLimoTie
Back to our Generated Files
Interfaces in IDL compile into 7 different objects
Limo compiles into_LimoImplBase_LimoOperations_LimoTie_LimoStubLimoLimoHelperLimorHolder
Servers
_LimoImplBase
org.omg.CORBA.DynamicImplementation
_LimoStub
Limo
LimoHelper
LimoHolder
_LimoOperations_LimoTie
org.omg.CORBA.Object
Ties versus BasesServers can be built by inheriting from
an abstract superclass which knows about IIOP and how to send messages / marshall data over the wire _xxxImplBase has a set of template
methods that you can implement in a subclass in order to build a server
You can also build them by aggregating out the “real server functionality” to a servant class.
Base Approachpublic abstract class _LimoImplBase extends org.omg.CORBA.DynamicImplementation
implements grosso.corbalimo.Limo { // Constructor public _LimoImplBase() { super(); } // Type strings for this class and its superclases private static final String _type_ids[] = { "IDL:grosso/corbalimo/Limo:1.0" };
public String[] _ids() { return (String[]) _type_ids.clone(); }
private static java.util.Dictionary _methods = new java.util.Hashtable(); static { _methods.put("_get_current_dispatcher", new java.lang.Integer(0)); _methods.put("_set_current_dispatcher", new java.lang.Integer(1)); _methods.put("_get_current_location", new java.lang.Integer(2)); _methods.put("_get_current_driver", new java.lang.Integer(3)); _methods.put("getIsCarryingPassenger", new java.lang.Integer(4)); _methods.put("wantPassenger", new java.lang.Integer(5)); _methods.put("pickupPassenger", new java.lang.Integer(6)); }
Base Approach IIpublic void invoke(org.omg.CORBA.ServerRequest r) { switch (((java.lang.Integer) _methods.get(r.op_name())).intValue()) { case 0: // grosso.corbalimo.Limo.current_dispatcher { org.omg.CORBA.NVList _list = _orb().create_list(0); r.params(_list); grosso.corbalimo.Dispatcher ___result = this.current_dispatcher(); org.omg.CORBA.Any __result = _orb().create_any(); grosso.corbalimo.DispatcherHelper.insert(__result, ___result); r.result(__result); } break; case 1: // grosso.corbalimo.Limo.current_dispatcher { org.omg.CORBA.NVList _list = _orb().create_list(0); org.omg.CORBA.Any _arg = _orb().create_any(); _arg.type(grosso.corbalimo.DispatcherHelper.type()); _list.add_value("arg", _arg, org.omg.CORBA.ARG_IN.value); r.params(_list); grosso.corbalimo.Dispatcher arg; arg = grosso.corbalimo.DispatcherHelper.extract(_arg); this.current_dispatcher(arg); org.omg.CORBA.Any a = _orb().create_any(); a.type(_orb().get_primitive_tc(org.omg.CORBA.TCKind.tk_void)); r.result(a); } break;
Base Approach IIIcase 2: // grosso.corbalimo.Limo.current_location { org.omg.CORBA.NVList _list = _orb().create_list(0); r.params(_list); grosso.corbalimo.Location ___result = this.current_location(); org.omg.CORBA.Any __result = _orb().create_any(); grosso.corbalimo.LocationHelper.insert(__result, ___result); r.result(__result); } break; case 3: // grosso.corbalimo.Limo.current_driver { org.omg.CORBA.NVList _list = _orb().create_list(0); r.params(_list); grosso.corbalimo.Driver ___result = this.current_driver(); org.omg.CORBA.Any __result = _orb().create_any(); grosso.corbalimo.DriverHelper.insert(__result, ___result); r.result(__result); } break;
// and so on ...
Tie Approachpackage grosso.corbalimo;public class _LimoTie extends grosso.corbalimo._LimoImplBase { public grosso.corbalimo._LimoOperations servant; public _LimoTie(grosso.corbalimo._LimoOperations servant) { this.servant = servant; } public grosso.corbalimo.Dispatcher current_dispatcher() { return servant.current_dispatcher(); } public void current_dispatcher(grosso.corbalimo.Dispatcher arg) { servant.current_dispatcher(arg); } public grosso.corbalimo.Location current_location() { return servant.current_location(); } public grosso.corbalimo.Driver current_driver() { return servant.current_driver(); } // and so on ... }
The Operations Class_LimoOperations still unexplainedBasically, the Limo interface without
any extra funcitonality Unlike Limo, which inherits from
org.omg.CORBA.Object
package grosso.corbalimo;public interface _LimoOperations { grosso.corbalimo.Dispatcher current_dispatcher(); void current_dispatcher(grosso.corbalimo.Dispatcher arg); grosso.corbalimo.Location current_location(); grosso.corbalimo.Driver current_driver(); boolean getIsCarryingPassenger(grosso.corbalimo.PassengerHolder current_passenger); boolean wantPassenger(grosso.corbalimo.Passenger possible_passenger); boolean pickupPassenger(grosso.corbalimo.Passenger new_passenger);}
Fundamental TruthThe code we just went through did three
things: The client connected to the server The client sent a request The client got a response
All methods for distributed programming, at their core, must handle these three things.
The way to understand an architecture is to make the above sequence into questions
The CORBA Development CycleWrite IDL definitionsCompile IDL to java
Javasoft has idltojava, Visigenic has idl2java, ...
This will give you stubs and skeletonsWrite the server and client code in JavaUse javac to compile the programs Configure the deployment environment
Break Time
SimpleClient GUI is the Same
Most SimpleClient code is identical too
private class ButtonAction implements ActionListener{ public void actionPerformed(ActionEvent e){ try{ Dispatcher dispatcher = CorbaLimoProperties.getDispatcher(); Limo limo = dispatcher.hailLimo(getPassenger()); if (null!=limo){ Driver driver = limo.current_driver(); _reportsBack.append("Limo is driven by " + driver.name +"\n"); } else{ _reportsBack.append("No limos available \n"); } } catch (Exception ee){} }
90% of the code is identical to the RMI code
Only difference is in the Button’s listener
CorbaLimoPropertiespublic class CorbaLimoProperties { private static Properties _properties; public static Properties getProperties() { if (null==_properties) { _properties = new Properties(); _properties.put("org.omg.CORBA.ORBInitialPort", "3500"); _properties.put("org.omg.CORBA.ORBInitialHost", "localhost"); _properties.put("org.omg.CORBA.ORBClass", "com.sun.CORBA.iiop.ORB"); } return _properties; } public static Dispatcher getDispatcher(){ try{ Properties properties = CorbaLimoProperties.getProperties(); ORB orb = ORB.init((String[]) null, properties); org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext nameServer = NamingContextHelper.narrow(objRef); NameComponent ourComponent = new NameComponent("Dispatcher", ""); NameComponent path[] = {ourComponent}; org.omg.CORBA.Object dispatcherRef = nameServer.resolve(path); return DispatcherHelper.narrow(dispatcherRef); } catch (Exception e){ e.printStackTrace(); } return null; }}
Properties used by JavaIDLJavaIDL is the free CORBA
implementation Supplied by Javasoft Not really intended for industrial-strength
use (no real support for servers or object adapters)
4 properties can be set
Property Defined by Purposeorg.omg.CORBA.ORBClass OMG Name of a java class which implements
org.omg.CORBA.ORB. Instances of this arecreated in response toorg.omg.CORBA.ORB.init(....)
org.omg.CORBA.ORBSingletonClass OMG Also the name of a java class which implements ....This one is used to respond toorg.omg.CORBA.ORB.init() [no arguments to init].In essence, it provides some ORB functionalitywithout actually having a network presence
org.omg.CORBA.ORBInitialHost SUN Machine running tnameserv (defaults to localhost)org.omg.CORBA.ORBInitialPort SUN Port that tnameserv is listening on (defaults to 900)
Using Inheritance to build ServersWe’re going to separate out the
launchers from the servers again (just like in the RMI case)
We’ll build Limo_Inheritance as a subclass of _LimoBaseImpl
We’ll build Dispatcher_Inheritance as a subclass of _DispatcherBaseImpl
Limo_Inheritancepublic class Limo_Inheritance extends _LimoImplBase { private boolean _havePassenger; private Dispatcher _dispatcher; private Location _currentLocation; private Driver _driver; private Passenger _passenger; public Limo_Inheritance (Dispatcher dispatcher, Driver driver) { _havePassenger = false; _dispatcher = dispatcher; _driver = driver; dispatcher.limoAvailable(this); } public grosso.corbalimo.Dispatcher current_dispatcher() { return _dispatcher; }
Limo_Inheritance II
public void current_dispatcher(grosso.corbalimo.Dispatcher arg) { if ((false==_havePassenger) &&(null!=_dispatcher)) { _dispatcher.limoUnavailable(this); if(null!=arg) { arg.limoAvailable(this); } } _dispatcher = arg; }
public grosso.corbalimo.Location current_location() { return _currentLocation; }
public grosso.corbalimo.Driver current_driver(){ return _driver; }
Limo_Inheritance III public boolean getIsCarryingPassenger(grosso.corbalimo.PassengerHolder current_passenger){ if (null!=_passenger) { current_passenger.value = _passenger; // using a Holder class } return _havePassenger; }
public boolean wantPassenger(grosso.corbalimo.Passenger possible_passenger) { return (false ==_havePassenger); // a very simple model of // cabbie decision making }
public boolean pickupPassenger(grosso.corbalimo.Passenger new_passenger) { if (true==_havePassenger) { return false; } _dispatcher.limoUnavailable(this); _passenger = new_passenger; _currentLocation=new_passenger.destination;// in theory we'd drive around for a while now _passenger=null; _dispatcher.limoAvailable(this); return true; }}
Dispatcher_Inheritance public class Dispatcher_Inheritance extends _DispatcherImplBase { private ArrayList _availableLimos;
public Dispatcher_Inheritance () { _availableLimos= new ArrayList(); }
public grosso.corbalimo.Limo hailLimo(grosso.corbalimo.Passenger new_passenger) { Collections.shuffle(_availableLimos); Iterator i = _availableLimos.iterator(); while(i.hasNext()) { Limo limo = (Limo) i.next(); if (limo.pickupPassenger(new_passenger)){ return limo; } } return null; } public void limoAvailable(grosso.corbalimo.Limo limo) { if (false==_availableLimos.contains(limo)) { _availableLimos.add(limo); } }
Dispatcher_Inheritance II
public void limoUnavailable(grosso.corbalimo.Limo limo) { _availableLimos.remove(limo); }}
public class Launcher_Dispatcher { public static void main(String[] args) { try { Properties properties = CorbaLimoProperties.getProperties(); ORB orb = ORB.init(args, properties); Dispatcher_Inheritance dispatcher = new Dispatcher_Inheritance(); orb.connect(dispatcher); // This is pretty much a JavaIDL hack
// JavaIDL doesn't really support servers well org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext nameServer = NamingContextHelper.narrow(objRef); NameComponent ourComponent = new NameComponent("Dispatcher", ""); NameComponent path[] = {ourComponent}; nameServer.rebind(path, dispatcher); (new SelfCleaningFrame("Dispatcher Server")).show(); //hack to keep JVM alive
//because JavaIDL uses Daemon threads } catch (Exception e){ e.printStackTrace(); } }}
Launcher_Dispatcher
Launcher_Limospublic class Launcher_Limos { public static void main(String[] args) {// In reality, we'd probably do something a little cleverer // here (use more command line args or use a factory server)
try {// first we find the dispatcher Dispatcher dispatcher = CorbaLimoProperties.getDispatcher(); for (int currentTaxiDriver=0; currentTaxiDriver < args.length;
currentTaxiDriver++) { Driver driver = new Driver(args[currentTaxiDriver]); Limo currentLimo = new Limo_Inheritance(dispatcher, driver); } (new SelfCleaningFrame("Limos Server")).show(); //hack to keep JVM alive
//because JavaIDL uses daemon threads
} catch (Exception e){ e.printStackTrace(); } }}
Running the ApplicationLaunch the
nameserverLaunch the
dispatcherLaunch the limos
Run the client
start java grosso.corbalimo.Launcher_Dispatcher
start tnameserv -ORBInitialPort 3500
start java grosso.corbalimo.Launcher_Limos Bob Fred Alice
java grosso.corbalimo.SimpleClient.java
Infrastructure in CORBAThe org.omg.CORBA.ORB class provides
basic infrastructure for object management Creation of CORBA types Stringifying and destringifying object references
All xxxBaseImpl objects implement org.omg.CORBA.Object Extra methods that can be called on the object
reference (but which are handled locally)Defined using pseudo-idl (the //PIDL
comment)
org.omg.CORBA.ORB
As usual, defined in IDLLots of functionality (cf: Chapter 4 of
the CORBA spec)interface ORB { string object_to_string(in Object obj); Objecxt string_to_object(in string str);
//....
The ORB object is the interface to those functions which do not depend on which object adapter is used. These operations are the same for all ORBs and all object implementations and can be performed either by clients of the objects or by implementations
Stringifying ReferencesThe ORB provides basic object
management functionalityOne important piece of functionality is
stringifying object references Any CORBA object reference may be stringified The string can be converted back to an object
reference String format defined by OMG, encodes all the
information needed to connect to serverEnables bootstrapping of systems
Useful ORB FunctionalityString[] list_initial_services()
Object resolve_initial_references(String object_name)
String object_to_string(Object obj)
Object string_to_object(String str)
shutdown(boolean wait_for_completion)
Lists the CORBAServices that are available
Takes a canonical name (returned from list_initial_services or known in advance) and returns an object reference
Stringifies an object reference
Destringifies an object reference
Shuts the ORB down. Rarely called on the client side
org.omg.CORBA.ObjectObject _duplicate() boolean _non_existent() void _release()
Request _create_request(Context ctx, String operation, NVList arg_list, NamedValue result) Request _create_request(Context ctx, String operation, NVList arg_list, NamedValue result, ExceptionList exclist,
ContextList ctxlist) Request _request(String operation)
DomainManager[] _get_domain_managers()
Object _get_interface_def() boolean _is_a(String repositoryIdentifier) boolean _is_equivalent(Object other) int _hash(int maximum)
Object _set_policy_override(Policy[] policies, SetOverrideType set_add) Policy _get_policy(int policy_type)
Example use of Requestspublic class _LimoStub extends org.omg.CORBA.portable.ObjectImpl implements grosso.corbalimo.Limo {
//...
// IDL operations // Implementation of attribute ::current_dispatcher public grosso.corbalimo.Dispatcher current_dispatcher() { org.omg.CORBA.Request r = _request("_get_current_dispatcher"); r.set_return_type(grosso.corbalimo.DispatcherHelper.type()); r.invoke(); grosso.corbalimo.Dispatcher __result; __result = grosso.corbalimo.DispatcherHelper.extract(r.return_value()); return __result; } public void current_dispatcher(grosso.corbalimo.Dispatcher arg) { org.omg.CORBA.Request r = _request("_set_current_dispatcher"); org.omg.CORBA.Any _current_dispatcher = r.add_in_arg(); grosso.corbalimo.DispatcherHelper.insert(_current_dispatcher, arg); r.invoke(); }
More _LimoStub // Implementation of ::grosso::corbalimo::Limo::wantPassenger public boolean wantPassenger(grosso.corbalimo.Passenger possible_passenger) { org.omg.CORBA.Request r = _request("wantPassenger"); r.set_return_type(org.omg.CORBA.ORB.init().get_primitive_tc(org.omg.CORBA.TCKind.tk_boolean)); org.omg.CORBA.Any _possible_passenger = r.add_in_arg(); grosso.corbalimo.PassengerHelper.insert(_possible_passenger, possible_passenger); r.invoke(); boolean __result; __result = r.return_value().extract_boolean(); return __result; } // Implementation of ::grosso::corbalimo::Limo::pickupPassenger public boolean pickupPassenger(grosso.corbalimo.Passenger new_passenger) { org.omg.CORBA.Request r = _request("pickupPassenger"); r.set_return_type(org.omg.CORBA.ORB.init().get_primitive_tc(org.omg.CORBA.TCKind.tk_boolean)); org.omg.CORBA.Any _new_passenger = r.add_in_arg(); grosso.corbalimo.PassengerHelper.insert(_new_passenger, new_passenger); r.invoke(); boolean __result; __result = r.return_value().extract_boolean(); return __result; }
Servers in JavaIDLAll the above code is generic (either
works or can easily be modifed to work with any CORBA 2.x ORB)
But there’s a remarkably large and unspecified piece in the middle of it What is the following code really doing ?
Dispatcher dispatcher = CorbaLimoProperties.getDispatcher(); for (int currentTaxiDriver=0; currentTaxiDriver < args.length;
currentTaxiDriver++) { Driver driver = new Driver(args[currentTaxiDriver]); Limo currentLimo = new Limo_Inheritance(dispatcher, driver); }
Real Questions ?It’s clearly creating a bunch of server
objectsThey’re probably in a single JVM
Probably in the same JVM as the code that creates them
How many sockets have been allocated ?How many threads are listening at the
sockets ?What’s the request handling policy ?
Object AdaptersRecall our previous (from slide 10) picture:
The Object Adapter is a server-side layer, living between the skeletons and the ORB, that helps to answer these questions.
GIOP / IIOP (Wire protocol)
ServerObject
staticSkeletons
Dyunaic SkeletonInterface
Orb Functionality and Object Adapters
Common Threading PoliciesThread-per-request
Thread-per-client
General thread pool
Spawns a new thread for each incoming request
A different thread is used for each client connection.
Has a single thread pool for all the client requests that come in
This decision is made in the Object AdapterThe Object Adapter is a layer between
the ORB and the skeletons. ORB does “generic CORBA stuff” like
unmarshalling parameters and passes the method call along to the Object Adapter
Object Adapter does “server-side specific” stuff and then passes the request along to the skeletonsSo it has a chance to check security, or spawn
a thread or ....
The State of Object AdaptersJavaIDL doesn’t provide an
implementationThe OMG has specified two different
Object Adapters BOA: Basic Object Adapter.
Every commercial vendor has this right now
POA: Portable Object Adapter. Basically, the next generation of BOA
• Fixes some loopholes in the spec • Includes support for common server-side idioms and
activation
The Naming ServiceDefined as “white pages” for object
systems If you know the name, you can contact the
server Supports notion of tree-like directory structures
Runs as a server, with an IDL specification If you have the object reference, you can talk to
any vendor’s Naming ServiceFinding a naming service can be vendor
specific
Finding the Naming ServiceOne way to find the Naming Service is
to have a pointer to it already Stringified IIOR can be very useful for this
Getting an original reference to a naming service is more problematic You use the reserved name and hope that
the ORB can find it
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
How ORB finds Naming Service is vendor specificRecall CorbaLimoProperties if (null==_properties) { _properties = new Properties(); _properties.put("org.omg.CORBA.ORBInitialPort", "3500"); _properties.put("org.omg.CORBA.ORBInitialHost", "localhost"); _properties.put("org.omg.CORBA.ORBClass", "com.sun.CORBA.iiop.ORB"); } return _properties; }
public static Dispatcher getDispatcher() { try { Properties properties = CorbaLimoProperties.getProperties(); ORB orb = ORB.init((String[]) null, properties); org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
Sun specific
OMG defined
IDL for the Naming Service#pragma prefix "omg.org"
module CosNaming {
typedef string Istring; struct NameComponent { Istring id; Istring kind; }; typedef sequence<NameComponent> Name;
enum BindingType { nobject, ncontext }; struct Binding { Name binding_name; BindingType binding_type; }; typedef sequence<Binding> BindingList;
interface BindingIterator; // forward declaration
Naming Service IDL (NamingContext Interface)
interface NamingContext {
enum NotFoundReason { missing_node, not_context, not_object }; exception NotFound { NotFoundReason why; Name rest_of_name; }; exception CannotProceed { NamingContext cxt; Name rest_of_name; }; exception InvalidName {}; exception AlreadyBound {}; exception NotEmpty {};
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); Object resolve(in Name n) raises(NotFound, CannotProceed, InvalidName); void unbind(in Name n) raises(NotFound, CannotProceed, InvalidName); NamingContext new_context(); NamingContext bind_new_context(in Name n) raises(NotFound, CannotProceed, InvalidName, AlreadyBound); void destroy() raises(NotEmpty); void list(in unsigned long how_many, out BindingList bl, out BindingIterator bi);};
org.omg.COSNamingpublic interface NamingContext { public void bind_context(NameComponent[] n, NamingContext nc) ; public NamingContext bind_new_context(NameComponent[] n) ; public void bind(NameComponent[] n, Object obj); public void destroy() ; public void list(int how_many, BindingListHolder bl, BindingIteratorHolder bi); public NamingContext new_context() ; public void rebind_context(NameComponent[] n, NamingContext nc); public void rebind(NameComponent[] n, Object obj) ; public Object resolve(NameComponent[] n) ; public void unbind(NameComponent[] n);}
public class NameComponent { public String id public String kind public NameComponent() public NameComponent(String __id, String __kind) }
Naming Service IDL III interface BindingIterator { boolean next_one(out Binding b); boolean next_n(in unsigned long how_many,
out BindingList b); void destroy(); };
interface NamingContextFactory { NamingContext create_context(); oneway void shutdown(); };
// The Extended factory contains a root context which allows // clients to bootstrap to a particular factory through // resolve_initial_references()
interface ExtendedNamingContextFactory : NamingContextFactory { NamingContext root_context(); };
org.omg.COSNaming in UML
Binding
BindingHelper
BindingHolder
BindingIteratorHelper
BindingIteratorHolder
BindingTypeHelper
BindingTypeHolder
NameComponent
NameComponentHelper
NameComponentHolderNamingContextHelper
NamingContextHolder
BindingIterator
NamingContext
BindingType
IDLEntity
Interface
_BindingIteratorImplBase
_BindingIteratorStub
_NamingContextImplBase
_NamingContextStub
org.omg.CORBA.portable.ObjectImpl.
ReferencesHenning and Vinoski, Advanced CORBA
Programming with C++ (Addison Wesley) A Great Book. Period. Of the 1,000 pages, 400 are C++ specific. The
rest constitute the best possible 600 page overview of the CORBA standard
Vogel and Duddy, Java Programming with CORBA (Wiley) A good book; we’ve covered most of it though. Java specific
HomeworkChange the limo example so that the
limos launch first and insert themselves into the naming service (under the NamingContext “Limos”)
When the dispatcher is launched, it finds all the limos and calls current_dispatcher on them (with itself as argument)
From then on, the application is identical