Transcript 16-Corba
CORBA
William Grosso, [email protected] (C) 1999, all rights reserved
This Lecture
Common Object Request Broker Architecture
(CORBA)
Start with Limo example to illustrate general
principles (and IDL syntax)
Naming Service
Recall: Sockets
Streams-based communication between any
two computers on a network
No 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: RMI
Layer on top of Sockets
Has 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 CORBA
Specification for distributed object
communications
Defined and maintained by the Object
Management Group (www.omg.org)
Location transparency and object activation are
fundamental to the specification
Language independent and platform neutral
Large number of extensions (Services and
Facilities) designed by industry working
groups
The Object Management
Group
Industry consortium
At this point, about
800 members
Various types of
members;
Some vote
Some just serve on task
forces
OMG Board
Architecture
Board
Task Forces
History of CORBA
1989: OMG founded by 8 members
1991: CORBA 1.1
Includes IDL and basic functionality definitions
No real specifications for interoperability
1994: CORBA 2.0
Interoperability (GIOP) and the BOA defined
Currently: CORBA 2.4
Minor modifications to 2.0, the definition of the
POA, and objects-by-value
Reference Model
Application Objects
Facilities
Object Request Broker (ORB)
Services
Process-Level Schematic
Client
Object
Static
Stubs
Interface
Repository
Implementation
Repository
Dynamic
Invocation
Orb Functionality
GIOP / IIOP (Wire protocol)
Orb Functionality and
Object Adapters
Dyunaic
Skeleton
Interface
Server
Object
static
Skeletons
The ORB
The ORB, and the associated object
adapters, define the infrastructure for clientserver 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 Independence
The 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
CORBAServices
Idea: standardize common servers and
design decisions
These 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
CORBAFacilities
Oriented towards the end-user, rather than
the developer
Partially 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 Language
Remember-- CORBA wants to be platform
and language independent
What 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 IDL
Rigorously defined language for specifying
an API
Method definitions, but no computational
constructs
C++ 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
Stub
IDL Compilers use mappings to
generate stubs and skeletons in
target languages
Skeleton
Stub
Skeleton
Stub
Skeleton
Stub
The CORBA Development
Cycle
Write IDL definitions
Compile IDL to java
Javasoft has idltojava, Visigenic has idl2java, ...
This will give you stubs and skeletons
Write the server and client code in Java
Use javac to compile the programs
Configure the deployment environment
Recall our Banking Program
We had a set of bank account objects, which
could be found by using the owner’s name.
Each object function as a small server
Persistence was handled by a background
thread
Deactivation 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 IDL
Abstract specification language
Syntax 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 IDL
Data Type
[unsigned] short
Definition
16 bit, specified via 2’s complement
[unsigned] long
32 bit, specified via 2’s complement
[unsigned] long long
float
double
long double
char
wchar
64 bit
16 bit, IEEE standard
32 bit, IEEE standard
64 bit precision
ISO Latin-1 character
Unicode 16 bit representation
Definition
unsigned short trade_balance;
short number_of_legs;
unsigned long height_in_millimeters;
long nanoseconds_until_equinox;
long long atoms_in_universe;
float grade_point_average;
double temperature;
long double pi;
char monogram_initial;
wchar name_in_swedish_characters
boolean
two values: TRUE and FALSE
boolean alive;
string
variable length sequence of characters
string first_name;
wstring
octet
enum
variable length sequence of wchars
8 bits, completely uninterpreted
enumerated type, boils down to named
integers
Generic type, similar to void * with reflection
added. Can represent any IDL type (basic or
constructed, object or non-object)
wstring first_name;
octet identifying_bits;
enum color_list {red, blue, green, mauve};
any
any foo;
Structs
Declared using the keyword struct
Can contain any other types (including
structs and objects)
struct Species{
kingdom kingdom;
phylum phlya;
string formal_name;
};
// an enumerated type defined earlier
// an enumerated type defined earlier
struct BugDescription {
species bug_species;
string first_name;
string last_name;
unsigned short number_of_legs;
unsigned short calories_when_used_as_salad_topping;
};
Exceptions
Almost exactly like structs
Also define types
Can be passed as arguments or returned as
values
Can 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 Types
Sequences and arrays are the standard
containers
sequence <type[, max length]> variable_name
type[int][int] variable_name
Usually typedef’d as well (must be typedef’d
to be used as argument or return types in a
method call)
typedef sequence<Book, 30> BookShelf;
typedef Book[30] BookShelf;
typedef sequence <Book> UnboundedBookShelf;
typedef LastName string<30>
Typedefs
Types 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 ;
Attributes
An attribute is simply shorthand for
declaring an accessor/mutator pair
attribute string food;
attribute long height, width, depth;
Nice part of this: exact syntax of
accessor/mutator is specified in the
language mapping (according to the local
idiom)
readonly attribute string food;
Attributes can be readonly
Method Calls
General syntax is a little more complex than
in Java
delivery-style return-type method-name
(comma delimited sequence of arguments)
raises (comma delimited sequence of exceoptions);
Delivery Style
If omitted, defaults to synchronous delivery
Has at-most-once semantics
Caller blocks until method returns or exception
is thrown
Can be specified as oneway
best-effort semantics
Cannot have any return values or raise
exceptions
Message is sent and client immediately
continues processing
Arguments
Every 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
Interfaces
Interfaces define Servers.
They define “object” in CORBA
Interfaces are like objects that extend Remote
in RMI
Support 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);
};
Modules
A module is a grouping mechanism, much
like a package in Java
Modules can contain other modules
Scoping 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
raises(AlreadyConnected);
};
interface ProxyPullSupplier : CosEventComm::PullSupplier {
void connect_pull_consumer(in CosEventComm::PullConsumer
raises(AlreadyConnected);
};
interface ProxyPullConsumer : CosEventComm::PullConsumer {
void connect_pull_supplier(in CosEventComm::PullSupplier
raises(AlreadyConnected);
};
interface ProxyPushSupplier : CosEventComm::PushSupplier {
void connect_push_consumer(in CosEventComm::PushConsumer
raises(AlreadyConnected);
};
push_supplier)
pull_consumer)
pull_supplier)
push_consumer)
Event Channel IDL III
interface 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
RemoteObject
Remote
RemoteServer
UnicastRemoteObject
Dispatcher
Limo
Serializable
DispatcherImpl
LimoImpl
Passenger
Location
Driver
Limo in IDL
module 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
Cycle
Write IDL definitions
Compile IDL to java
Javasoft has idltojava, Visigenic has idl2java, ...
This will give you stubs and skeletons
Write the server and client code in Java
Use javac to compile the programs
Configure the deployment environment
Break Time
Compiling is Simple
ORB 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
idltojava -fno-cpp -ftie limo.idl
idl2java BankAccount.idl -strict -portable -VBJvmflag ”-Xbootclasspath:%CLASSPATH_WITHOUTINTERBASE%"
The Mapping is more
Complicated
Conceptual Mappings
IDL Concept
module
Java Concept
package
exception
class which extends
org.omg.CORBA.UserException
in argument
out argument
ordinary java argument
“holder” class, related to the type declared in
the IDL
attributes
reader/writer methods
Discussion
Modules inside other modules map to
subpackages
Must be caught in client code
Out, and inout, arguments are impossible to
directly handle in Java. Instead, we use a
wrapper class whose value can be set.
These, alas, do not conform to beans names.
Instead, they simple overload the attributes
name.
Mapping Basic Types
IDL Basic Type
[unsigned] short
[unsigned] long
Java Type
short
int
[unsigned] long long
float
double
long double
long
float
double
NONE YET
char
wchar
char
char
boolean
boolean
string
wstring
octet
any
java.lang.String
java.lang.String
byte
the Java class org.omg.CORBA.Any
Discussion
As the spec evolves, this will probably map
to java.math.BigDecimal
Mapping Constructed Types
IDL Constructed Type
sequence
Java Type
array
array
array
struct
A Java class in the appropriate package
enum
A Java class in the appropriate package and
with the same name as the enumerated type
Automatically translated to original name
An interface in the appropriate package.
typedef
interface
Discussion
Not to Collections classes at all. But simply
to arrays. This preserves strong typing, but is
somewhat foreign to Java.
Not to Collections classes at all. But simply
to arrays. This preserves strong typing, but is
somewhat foreign to Java.
Actually, three classes are defined for structs
and enums. Namely, the base class, a helper
class, and a holder class.
Also has a helper and a holder.
Holders
Problem: 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
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
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 );
}
PassengerHolder
package 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();
}
}
Any
Generic type, similar to void * with reflection
added. Can represent any IDL type (basic or
constructed, object or non-object)
Used in IDL as a type
Corresponds to org.omg.CORBA.Any
Any Methods
boolean 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);
Helpers
Every constructed type has an associated
Helper class as well
Helpers extend the CORBA type system to
deal with your object definitions
They have static methods to
Insert and extract instances from an Any
Get typecodes
Perform narrowing (down-casting) operations
Helpers and Narrowing
Interfaces in IDL have an inheritance
hierarchy
Java is a single (implementation) inheritance
language
Suppose FastLimo was a sub-class of Limo in
our IDL
The FastLimo Hierarchy
org.om g.CORBA.Object
org.om g.CORBA.DynamicImplem entation
Lim o
_LimoStub
_LimoImplBase
FastLim o
_FastLimoImplBase
_FastLimoStub
_LimoTie
_LimoOperations
_FastLimoTie
_FastLimoOperations
Back to our Generated Files
Servers
Interfaces in IDL compile into 7 different
objects
Limo compiles into
_LimoImplBase
_LimoOperations
_LimoTie
_LimoStub
Limo
LimoHelper
LimorHolder
org.omg.CORBA.Object
LimoHolder
Limo
org.omg.CORBA.DynamicImplementation
LimoHelper
_LimoImplBase
_LimoStub
_LimoTie
_LimoOperations
Ties versus Bases
Servers 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 Approach
public 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 II
public 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);
}
Base Approach III
case 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 Approach
package 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 unexplained
Basically, 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_passenge
boolean wantPassenger(grosso.corbalimo.Passenger possible_passenger);
boolean pickupPassenger(grosso.corbalimo.Passenger new_passenger);
}
Fundamental Truth
The 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
Cycle
Write IDL definitions
Compile IDL to java
Javasoft has idltojava, Visigenic has idl2java, ...
This will give you stubs and skeletons
Write the server and client code in Java
Use javac to compile the programs
Configure the deployment environment
Break Time
SimpleClient GUI is the Same
Most SimpleClient code is
identical too
90% of the code is identical to the RMI code
Only difference is in the Button’s listener
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){}
}
CorbaLimoProperties
public 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 JavaIDL
JavaIDL 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
org.omg.CORBA.ORBClass
Defined by
OMG
org.omg.CORBA.ORBSingletonClass
OMG
org.omg.CORBA.ORBInitialHost
org.omg.CORBA.ORBInitialPort
SUN
SUN
Purpose
Name of a java class which implements
org.omg.CORBA.ORB. Instances of this are
created in response to
org.omg.CORBA.ORB.init(....)
Also the name of a java class which implements ....
This one is used to respond to
org.omg.CORBA.ORB.init() [no arguments to init].
In essence, it provides some ORB functionality
without actually having a network presence
Machine running tnameserv (defaults to localhost)
Port that tnameserv is listening on (defaults to 900)
Using Inheritance to build
Servers
We’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_Inheritance
public 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_passen
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);
}
}
Launcher_Dispatcher
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_Limos
public 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 Application
Launch the nameserver
start tnameserv -ORBInitialPort 3500
Launch the dispatcher
start java grosso.corbalimo.Launcher_Dispatcher
Launch the limos
start java grosso.corbalimo.Launcher_Limos Bob Fred Alice
Run the client
java grosso.corbalimo.SimpleClient.java
Infrastructure in CORBA
The 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
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
As usual, defined in IDL
Lots 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);
//....
Stringifying References
The ORB provides basic object management
functionality
One 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 server
Enables bootstrapping of systems
Useful ORB Functionality
String[]
list_initial_services()
Lists the CORBAServices that are available
Object resolve_initial_references(String object_name)
Takes a canonical name (returned from list_initial_services
or known in advance) and returns an object reference
String object_to_string(Object obj)
Stringifies an object reference
Object string_to_object(String str)
Destringifies an object reference
shutdown(boolean wait_for_completion)
Shuts the ORB down. Rarely called on the client side
org.omg.CORBA.Object
Object _duplicate()
boolean _non_existent()
void _release()
Request _create_request(Context ctx,
NVList arg_list, NamedValue
Request _create_request(Context ctx,
NVList arg_list, NamedValue
ContextList ctxlist)
Request _request(String operation)
String operation,
result)
String operation,
result, ExceptionList exclist,
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 Requests
public 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.TCK
org.omg.CORBA.Any _possible_passenger = r.add_in_arg();
grosso.corbalimo.PassengerHelper.insert(_possible_passenger, possible_passeng
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.TCK
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 JavaIDL
All 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
objects
They’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 Adapters
Recall our previous (from slide 10) picture:
GIOP / IIOP (Wire protocol)
Orb Functionality and
Object Adapters
The Object Adapter is a server-side layer,
living between the skeletons and the ORB,
that helps to answer these Server
questions.
Dyunaic
Skeleton
Interface
static
Skeletons
Object
Common Threading Policies
Thread-per-request
Spawns a new thread for each incoming request
Thread-per-client
A different thread is used for each client connection.
General thread pool
Has a single thread pool for all the client requests
that come in
This decision is made in the
Object Adapter
The 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
skeletons
So it has a chance to check security, or spawn a
thread or ....
The State of Object Adapters
JavaIDL doesn’t provide an implementation
The 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 Service
Defined 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 Service
Finding a naming service can be vendor
specific
Finding the Naming Service
One 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 specific
Recall CorbaLimoProperties
Sun specific
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;
}
OMG defined
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");
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.COSNaming
public 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
Interface
BindingType
IDLEntity
BindingTypeHolder
Binding
BindingTypeHelper
BindingIterator
BindingHolder
BindingHelper
BindingIteratorHolder
NamingContext
BindingIteratorHelper
NamingContextHolder
NameCom ponent
NameCom ponentHelper
NamingContextHelper
NameCom ponentHolder
org.omg.CORBA.portable.ObjectImpl.
_BindingIteratorIm plBase
_BindingIteratorStub
_NamingContextIm plBase
_NamingContextStub
References
Henning 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
Homework
Change 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