Title: CORBA Design Patterns Structures Factories ORBlets
1CORBA Design PatternsStructures Factories
ORBlets
- Review
- Project Phase 1
- CORBA StockServer Example
- Today
- Object Factories
- Complex Types, and Pass by value via structures
- Building and Deploying CORBA Clients as Applets
- Introduction to Distributed Callbacks
2Example Bank Manager
// Bank.idl module Bank interface Account
float balance() interface
AccountManager Account open(in string
name)
In this application, the client can query the
bank to find the balance on an account. Note
that this time there are two interfaces. The IDL
compiler now generates the stub, skeleton,
helper/holder files, and interfaces for each of
these objects.
- We still need to provide implementations for both
of the interfaces Account and AccountManager - The Account objects simply provide a method for
retrieving the current balance - The AccountManager is an example of an object
factory design pattern - it creates an instance of the AccountImp at run
time according to a client request.
3Object Factories
In the Object Factory design pattern, a factory
object is responsible for creating objects of a
particular type. For example, the AccountManager
object can be thought of as an Account factory,
since Banks are responsible for creating all
Account objects in the system.
- Example A Widget Factory -
4Bank Manager (Cont.)
// Bank.idl module Bank interface Account
float balance() interface
AccountManager Account open(in string
name)
We still need to provide implementations for both
of the interfaces Account and AccountManager
// AccountImpl.java public class AccountImpl
extends Bank._AccountImplBase public
AccountImpl(float balance) _balance
balance public float balance()
return _balance private float _balance
The Account objects simply provide a method for
retrieving the current balance.
5Bank Manager (Cont.)
// AccountManagerImpl.java import
java.util. public class AccountManagerImpl
extends Bank._AccountManagerImplBase public
AccountManagerImpl(String name) super(name)
public synchronized Bank.Account open(String
name) // Lookup the account in the account
dictionary. Bank.Account account
(Bank.Account) _accounts.get(name) // If
there was no account in the dictionary, create
one. if(account null) // Make up
the account's balance, between 0 and 1000
dollars. float balance Math.abs(_random.ne
xtInt()) 100000 / 100f // Create the
account implementation, given the balance.
account new AccountImpl(balance) // Make
the object available to the ORB.
_boa().obj_is_ready(account) // Print out
the new account. System.out.println("Created
" name "'s account " account) //
Save the account in the account dictionary.
_accounts.put(name, account) // Return
the account. return account private
Dictionary _accounts new Hashtable() private
Random _random new Random()
6The Bank Client
// Client.java public class Client public
static void main(String args) //
Initialize the ORB. org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init(args,null) // Locate
an account manager. Bank.AccountManager
manager Bank.AccountManagerHelper.bind(orb,
"BankManager") // use args0 as the account
name, or a default. String name args.length
gt 0 ? args0 "Jack B. Quick" // Request
the account manager to open a named account.
Bank.Account account manager.open(name) //
Get the balance of the account. float balance
account.balance() // Print out the
balance. System.out.println ("The
balance in " name "'s account is "
balance)
7The Bank Server
// Server.java public class Server public
static void main(String args) //
Initialize the ORB. org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init(args,null) //
Initialize the BOA. org.omg.CORBA.BOA boa
orb.BOA_init() // Create the account manager
object. Bank.AccountManager manager
new AccountManagerImpl("BankManager") //
Export the newly create object.
boa.obj_is_ready(manager) System.out.println(
manager " is ready.") // Wait for incoming
requests boa.impl_is_ready()
8Activating Multiple Objects Directly
// Server.java public class Server public
static void main(String args) //
Initialize the ORB. org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init(args,null)
// Initialize the BOA. org.omg.CORBA.BOA boa
orb.BOA_init() // Create the account
manager object for Chicago. Bank.AccountManager
chicago new AccountManagerImpl("Chicago"
) // Create the account manager object for
Dallas. Bank.AccountManager dallas new
AccountManagerImpl("Dallas") // Export the
newly created objects. boa.obj_is_ready(chicago
) boa.obj_is_ready(dallas)
System.out.println(chicago " is ready.")
System.out.println(dallas " is ready.") //
Wait for incoming requests boa.impl_is_ready()
This example shows that the server can activated
multiple objects. The client(s) now have a choice
of querying each of these objects through the
Account interface.
9The Bank Manager in Action
10The POA Bank Manager - The Server
// Server.java import java.io.FileInputStream imp
ort java.util.Properties import
org.omg.CORBA. import org.omg.PortableServer.
public class Server public static void
main(String args) try //
Initialize the ORB. ORB orb
ORB.init(args, null) // get a reference to
the root POA POA rootPOA
POAHelper.narrow(orb.resolve_initial_references("R
ootPOA")) // Create bankPOA with the
right policies for registering AccountManager
Policy policies new org.omg.CORBA.Policy
rootPOA.create_lifespan_policy(Lifespan
PolicyValue.PERSISTENT) POA bankPOA
rootPOA.create_POA("bank_agent_poa",rootPOA.
the_POAManager(), policies) // Create
accountPOA with the right policies for
registering Accounts policies new
org.omg.CORBA.Policy
rootPOA.create_lifespan_policy(LifespanPolicyValue
.TRANSIENT) POA accountPOA
rootPOA.create_POA("account_agent_poa",
rootPOA.the_POAManager()
, policies) . . .
11The POA Bank Manager - The Server
// (Continued) // Create the servant
AccountManagerImpl managerServant new
AccountManagerImpl() // Activate the
servant with the ID on myPOA byte
managerId "BankManager".getBytes()
bankPOA.activate_object_with_id(managerId,
managerServant) // Activate the POA
manager rootPOA.the_POAManager().activate()
System.out.println("Bank Server is
ready.") // Wait for incoming requests
orb.run() catch (Exception e)
e.printStackTrace()
12POA Bank - AccountManager
// AccountManagerImpl.java import
org.omg.PortableServer. import
java.util. public class AccountManagerImpl
extends Bank.AccountManagerPOA public
synchronized Bank.Account open(String name)
// Same as before if(account null)
// Make up the account's balance Same as
before AccountImpl acctServant new
AccountImpl(balance) try //
Activate it on the transient POA POA
rootPOA POAHelper.narrow(_orb().reso
lve_initial_references("RootPOA")) POA
acctPOA rootPOA.find_POA("account_agent_poa",
true) acctPOA.activate_object(acctServant
) account
Bank.AccountHelper.narrow(acctPOA.servant_to_refer
ence(acctServant)) catch (Exception e)
e.printStackTrace() // Print out the new
account. System.out.println("Account"
name " is created.") // Save the
account in the account dictionary Same as
before return account // Same as
before
13POA Bank - the Client
// Client.java public class Client public
static void main(String args) //
Initialize the ORB. org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init(args,null) // Get
the manager Id byte managerId
"BankManager".getBytes() // Locate an
account manager. Bank.AccountManager manager
Bank.AccountManagerHelper.bind(orb,
"/bank_agent_poa", managerId) // use
args0 as the account name, or a default.
String name args.length gt 0 ? args0 "Jack
B. Quick" // Request the account manager to
open a named account. Bank.Account account
manager.open(name) // Get the balance of the
account. float balance account.balance()
// Print out the balance.
System.out.println ("The balance in "
name "'s account is " balance)
14Bank Example Using Holder Classes
- New IDL file specifies a method withdraw
- throws an exception InsufficientFunds
- uses an out parameter fee to represent
transaction fee charged by the bank (in this case
generated randomly) - returns the new balance after deducting amount
and fee
// Bank.idl module Bank interface Account
exception InsufficientFunds float
balance() float withdraw(in float amount,
out float fee) raises (InsufficientFunds)
interface AccountManager Account
open(in string name)
15Bank Example Using Holder Classes
// Client.java import org.omg.CORBA. import
java.util. public class Client public
static void main(String args) ORB orb
ORB.init(args,null) // Locate an account
manager. Bank.AccountManager manager
Bank.AccountManagerHelper.bind(orb,
"BankManager") String name args.length gt 0
? args0 "Jack B. Quick" Bank.Account
account manager.open(name) float balance
account.balance() System.out.println("The
balance in "name"'s account is "balance)
Random _random new Random() FloatHolder
fee new FloatHolder() float amount
Math.abs(_random.nextInt()) 100000 / 100f
try System.out.println ("Trying to withdraw
"amount" from your account...")
System.out.println("New Balance
"account.withdraw(amount, fee))
System.out.println ("You were charged
"fee.value" for withdrawal.") catch
(Bank.AccountPackage.InsufficientFunds ex)
System.out.println("Insufficient Funds for
Transaction!")
16Bank Example Using Holder Classes
// AccountImpl.java import org.omg.CORBA. import
java.util. public class AccountImpl extends
Bank._AccountImplBase public
AccountImpl(float balance) _balance
balance public float balance()
return _balance public float
withdraw(float amount, FloatHolder fee)
throws Bank.AccountPackage.Insufficien
tFunds Random _random new Random()
fee.value Math.abs(_random.nextInt()) 100000
/ 1000f if (amountfee.value lt _balance)
_balance _balance - amount - fee.value
else throw new Bank.AccountPackage.Ins
ufficientFunds() return _balance
private float _balance
17Bank Example Sample Run
Client
gtvbj Client ... The balance in Jack B. Quick's
account is 84.26 Trying to withdraw 2.58 from
your account.... New Balance 81.422 You were
charged 0.258 for withdrawal. gtvbj
Client ... The balance in Jack B. Quick's
account is 81.422 Trying to withdraw 898.29
from your account.... Insufficient Funds for
Transaction! gtvbj Client Bamshad ... The
balance in Bamshad's account is 880.54 Trying to
withdraw 660.53 from your account.... New
Balance 169.02295 You were charged 50.987 for
withdrawal.
18Bank Example Sample Run
Server
gtvbj Server AccountManagerImplServer,oidPersist
entIdrepIdIDLBank/AccountManager1.0,objectName
BankManager is ready. Created Jack B. Quick's
account AccountImplServer,oidTransientIdrepId
IDLBank/Account1.0,serverId2,creationTime17311
28880 Created Bamshad's account
AccountImplServer,oidTransientIdrepIdIDLBank
/Account1.0,serverId4,creationTime1731246860
- Notes
- account objects have been created with transient
object references - no account object was created for the second
client with default account name (Jack B. Quick)
19Using Complex Datatypes
- Lets consider a generic example of using an
array of complex types, being passed as in, out,
and inout parameters
module arrayOfStruct struct BasicStruct lo
ng longVal string stringVal typedef
BasicStruct BasicStructArray2 interface
ArrayOfStructTest long testArrayOfStruct(
in BasicStructArray inBasicStructArray, inout
BasicStructArray inoutBasicStructArray, out
BasicStructArray outBasicStructArray)
20Complex Datatypes - Object Implementation
package arrayOfStruct public class
ArrayOfStructTestImpl extends _ArrayOfStructTestIm
plBase //Constructor for transient
object public ArrayOfStructTestImpl()
//Constructor for persistent object public
ArrayOfStructTestImpl(String name) super(name)
public int testArrayOfStruct( BasicStruct
inBasicStructArray, BasicStructArrayHolder
inoutBasicStructArray, BasicStructArrayHolder
outBasicStructArray) //Change the values
in the inout array inoutBasicStructArray.value0
.longVal 6 inoutBasicStructArray.value0.stri
ngVal "fromServer" inoutBasicStructArray.value
1.longVal 6 inoutBasicStructArray.value1.s
tringVal "fromServer" //Create a new array
for the out value then assign values outBasicStru
ctArray.value new BasicStruct2 outBasicStru
ctArray.value0 new BasicStruct(6,
"fromServer") outBasicStructArray.value1
new BasicStruct(6, "fromServer") return 0
. . .
21Complex Datatypes - The Server
. . . public static void main(String args)
try // Initialize the ORB. org.omg.CORBA.
ORB orb org.omg.CORBA.ORB.init() //
Initialize the BOA. org.omg.CORBA.BOA boa
orb.BOA_init() // Create the
object ArrayOfStructTestImpl arrayOfStructTest
new ArrayOfStructTestImpl("ArrayOfStruct
Sample") // Export the newly create
object. boa.obj_is_ready(arrayOfStructTest)
System.out.println(arrayOfStructTest " is
ready.") // Wait for incoming
requests boa.impl_is_ready() catch(org.omg.
CORBA.SystemException ex) ex.printStackTrace(
)
22Complex Datatypes - The Client
package arrayOfStruct public class Client
public static void main(String args)
try //Initialize the ORB and Bind to
Implementation org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init() ArrayOfStructTest
arrayOfStructTest ArrayOfStructTestHelpe
r.bind(orb, "ArrayOfStruct Sample")
// Create the array of BasicStrut's and
initialize BasicStruct inArrayOfStruct
new BasicStruct2 inArrayOfStruct0 new
BasicStruct(5, "fromClient")
inArrayOfStruct1 new BasicStruct(5,
"fromClient") // Create holder for the
array, using the same array (just for
convenience) BasicStructArrayHolder
inoutArrayOfStruct new
BasicStructArrayHolder(inArrayOfStruct)
// Create the holder for the out param
BasicStructArrayHolder outArrayOfStruct new
BasicStructArrayHolder() //Call the
remote method with the in, inout, and out
parameters int returnValue
arrayOfStructTest.testArrayOfStruct( inArrayOf
Struct, inoutArrayOfStruct, outArrayOfStru
ct) catch(org.omg.CORBA.SystemExcep
tion ex) ex.printStackTrace()
23Using Structs in Auction Server
module AuctionModule interface Auction
typedef struct AuctionStatus string
item float currentPrice Status
// exception and attribute declarations //
seller accessible methods boolean offer(in
string sellerId, in string item, in float
initPrice) raises . . . boolean
sell(in string sellerId) raises . . . string
viewHighBidder(in string sellerId) raises . .
. // bidder accessible methods boolean
bid(in string userId, in float price) raises . .
. boolean viewBidStatus(in string userId)
raises . . . // universally accessible
methods Status viewAuctionStatus() raises . .
.
24Stubless Clients
- Two methods for building clients that do not
require (precompiled) object stubs - Using Dynamic Invocation Interface
- Requires the client to manually create a requests
that will be forwarded to the object
implementation on the server side - Requires knowledge of the object interfaces
- Requires the additional overhead of building,
registering, and maintaining an Interface
Repository - Use an applet for the client
- Object stubs are still precompiled, but they can
reside on the Web server along with the applet
and the implementation classes, and they are
downloaded to the client browser along with the
applet - Requires additional mechanisms to get around
applet sandboxing problems and firewall
restrictions (these are generally proprietary
tools) - Also Netscape (4.05 and higher) has bundled the
Java ORB class libraries and runtime with the
browsers which in turn eliminates the need for
the client to download these along with the
client stubs from the server
25The Applet option
- Java Applets
- Complete UI capabilities
- Local state management and interactivity
- Sandbox security
- Can interact outside scope of Web server?
- Browser compatibility is problematic
- ActiveX Components similar concept, except
- Platform dependent
- Poor security
- Using Applets
- Subclass java.awt.Applet
- Create HTML page with ltappletgt tag
- Install applet code and HTML page in server
hierarchy - Test with appletviewer
- Applet can open URLs, and open connections on Web
host including iiop - Applet can access Browser context
26Applet Sandboxing
- Applets cannot access local disks
- Applets cannot open a socket connection to any
other host other than the codebase machine - this eliminates the scalability benefits inherent
in CORBA to allow processing on multiple objects
on several physical hosts - Applets cannot use UDP broadcasting
- so applets cant communicate with smart agent to
locate server object - Visibroker runtime compensates for this
restriction - Applets cannot accept incoming communication
- applet objects cant host any object
implementation - prevents server callbacks
- The Visibroker Answer
- the GateKeeper
See the Gatekeeper Guide and the Gatekeeper FAQ
on the Inprise Site (http//www.borland.com/techpu
bs/visibroker/)
27Visibroker GateKeeper
- Gatekeeper serves three main purposes
- Acts as a Sandbox Proxy
- Acts as an HTTP Tunneling Proxy (for firewalls)
- Acts as a lightweight HTTP Daemon (for testing)
- Sandbox Proxy
- Applet communicates with Gatekeeper which then
acts as a universal client - It takes on responsibility for UDP broadcasting
and locating appropriate object servers (possibly
on multiple hosts) - It receives results and sends them back to client
- This also allows applets to receive callbacks
- HTTP Tunneling
- IIOP requests from clients are wrapped in HTTP
(so they can get through firewalls) - Gatekeeper accepts and decodes the HTTP requests
- HTTP Daemon
- Not production quality
28The Applet Environment
- Applet Basics
- Its a Panel, not a Window
- Position and size are determined by the ltappletgt
tag - Browser calls init() method on startup
- Java class loader retrieves classes from the
applets code base, or from pre-loaded jar files - Parameters are passed with ltparamgt tags, accessed
with getParameter(name) - Methods getDocumentBase and getCodeBase return
URLs for the document and the applet - Applet context object gives access to browser (to
load documents) and to other applets on the same
page
29The Count Client Applet
// CountClientApplet.java Applet Client,
VisiBroker for Java import java.awt. public
class CountClientApplet extends
java.applet.Applet private TextField
countField, pingTimeField private Button
runCount private Counter.Count counter
public void init() // Create a 2 by 2 grid of
widgets. setLayout(new GridLayout(2, 2, 10,
10)) // Add the four widgets, initialize
where necessary add(new Label("Count"))
add(countField new TextField())
countField.setText("1000") add(runCount
new Button("Run")) add(pingTimeField new
TextField()) pingTimeField.setEditable(false)
try // Initialize the ORB.
showStatus("Initializing the ORB")
org.omg.CORBA.ORB orb org.omg.CORBA.ORB.init(thi
s, null) // Bind to the Count Object
showStatus("Binding to Count Object")
counter Counter.CountHelper.bind(orb, "My
Count") catch(org.omg.CORBA.SystemException
e) showStatus("Applet Exception"
e) e.printStackTrace(System.out)
Note that a reference to the applet object is
passed a s a parameter of the ORB.init() method.
30The Count Client Applet (cont.)
public boolean action(Event ev, Object arg)
if(ev.target runCount) try //
Set Sum to initial value of 0
showStatus("Setting Sum to 0")
counter.sum((int)0) // get data from
and set value of applet fields
showStatus("Incrementing") int stopCount
Integer.parseInt(countField.getText())
pingTimeField.setText(" ") long
startTime System.currentTimeMillis()
for (int i 0 i lt stopCount i )
counter.increment() long
stopTime System.currentTimeMillis()
pingTimeField.setText("Avg Ping "
Float.toString((float)(stopTime-
startTime)/stopCount) " msecs")
showStatus("Sum " counter.sum())
catch(org.omg.CORBA.SystemException e)
showStatus("System Exception" e)
e.printStackTrace() return true
return false
31Count Applet HTML File
lth1gtCount Client Appletlt/h1gt lthrgt ltcentergt ltAPPLET
codebase. CODECountClientApplet.class
WIDTH300 HEIGHT60gt ltparam
nameorg.omg.CORBA.ORBClass valuecom.visigenic.vb
roker.orb.ORBgt lt/APPLETgt lt/centergt lthrgt
- Notes
- Note that the ORB classes are included as a
parameter in the APPLET tag. - Also make sure that the Applet class file is in
the same directory as the HTML file. - The gatekeeper is started from the Web server
directory containing the HTML and class files it
writes the file gatekeeper.ior in the same
directory.
32Count Applet Server Side
- Notes
- Technically the Server can be started anywhere
(even on a different machine) - The Gatekeeper (started in the Web server
directory) can cooperate with the OSAgent to find
the server object. - The server must be started prior to starting the
Gatekeeper.
33The CountClient Applet
34Count Applet the Gatekeeper
35CORBA Applets Deployment Checklist
- Compile your IDL and the generated Java classes
in the usual way - Move the applet, the html file and your class
files (both client-side and server-side classes)
to a directory on the Web server - Start the Visibroker Smart Agent (OSAGENT)
- Start the server application
- Start the gatekeeper promptgt gatekeeper
- Point a client browser to the URL for the
application HTML file - Some other notes
- Gatekeeper should be started in the same
directory as the server application - If gatekeeper is being used as a Web server, then
the URL should contain the port used by
gatekeeper (usually 15000) - Gatekeeper provides a combined HTTP and IIOP
server stack this allows the applets to interact
with object implementations on hosts other than
the Web server. It also allows IIOP messages to
be transported through firewalls disguised as
HTTP packets (HTTP tunnelling).
36POA Count Applet in VBJ 4.x
lthrgt ltcentergt ltapplet archive"vbjorb.jar"
codebase"." code"CountClientApplet.class"
width300 height60gt ltparam
name"org.omg.CORBA.ORBClass" value"com.inprise.v
broker.orb.ORB"gt ltparam name"vbroker.orb.gate
keeper.ior" value""gt ltparam
name"vbroker.orb.alwaysProxy" value"true"gt
lt/appletgt lt/centergt lthrgt
- Notes
- Depending on configuration, the file vbjorb.jar
may need to be copied into the Web server
directory containing the HTML and class files. - In VBJ 4.x the gatekeeper has been re-implemented
based on the Java Servlet Interfaces. This
requires that the servlet.jar file contained in
JSDK (downloaded from java.sun.com) be placed on
the CLASSPATH.
37POA Count Applet in VBJ 4.x
38POA Count Applet in VBJ 4.x
39The Bank Client Applet
// ClientApplet.java import java.awt. public
class ClientApplet extends java.applet.Applet
private TextField _nameField, _balanceField
private Button _checkBalance private
Bank.AccountManager _manager public void
init() // This GUI uses a 2 by 2 grid of
widgets. setLayout(new GridLayout(2, 2, 5,
5)) add(new Label("Account Name"))
add(_nameField new TextField())
add(_checkBalance new Button("Check
Balance")) add(_balanceField new
TextField()) // make the balance text field
non-editable. _balanceField.setEditable(false)
// Initialize the ORB (using the Applet).
org.omg.CORBA.ORB orb org.omg.CORBA.ORB.init(t
his, null) _manager Bank.AccountManagerHelp
er.bind(orb,"BankManager") public boolean
action(Event ev, Object arg) if(ev.target
_checkBalance) // Request the account
manager to open a named account. // Get the
account name from the name text widget.
Bank.Account account _manager.open(_nameField.ge
tText()) // Set the balance text widget to
the account's balance. _balanceField.setText
(Float.toString(account.balance())) return
true return false
40The Bank Applet
41CORBA/Java Threading Model
- Client-Side Threading
- Multithreaded clients spawn separate threads for
each activity associated with a certain user
event - This is done by creating a threaded proxy object
on the client-side to handle the threaded
operation.
Client Object
delivers results
An alternative to threads is to use the DII,
using methods such as send_deferred(),
get_response(), and poll_response(), on the
constructed request.
Creates
Proxy Thread
Client Proxy
starts
invocation
Server
Object Implementation
42CORBA/Java Threading Model
- Threading on the Server-Side
- Server-side multithreading is particularly
important in distributes applications, since a
server may potentially have to handle thousands
of concurrent clients. - ORBs provide 3 different threading models on the
server-side - Single-threaded servers place incoming requests
on a queue and process one invocation at a time. - Thread-per-connection one worker thread for each
network connection (all invocations from a single
JVM to target objects on the server are
multiplexed over the same connection invocations
from this JVM are processed sequentially). - Thread-per-request creates a new worker thread
for each incoming call. Usually, there is a
maximum number of threads available per server.
Visibroker uses thread pooling by default to
minimize the cost of creating new threads. - ORBs have built-in mechanisms for multithreaded
servers, and furthermore, Java allows methods and
classes to be declared synchronized and then
automatically synchronizes their use.
43Distributed Callbacks
- Distributed callbacks break a synchronous call
that returns some data into a pair of calls a
request and a response - The request call is made by the client which
(supply an object reference to accept a response - The response call is made on this object
reference by the server-side object
implementation - To allow the server-side object to call the
client back, the client must host an object that
implements an IDL defined callback interface
the reference of this client-side object is
provided as an in parameter of the request call.
Client Object
delivers results
Note The client creates an object that
implements the callback interface this could be
done globally (one callback object that receives
all callbacks), or a separate callback object can
be instantiated for each invocation.
calls
Client Proxy
Callback Object
response
request
Server
Object Implementation
44Distributed Callbacks
- When do we want to use callbacks
- The client application must manage one or more
activities concurrently, such as the user
interface and ORB service invocations. - When object operations take a long time and the
client application cannot afford to suspend
processing waiting for results. - When a client wants to have several services
process operations on its behalf simultaneously
and can receive results in any order when
processing has completed. - When it is necessary for a client to continue
local processing while sending CORBA requests. - When the client only wants to accept results, if
available, at specific intervals.
45Using Distributed Callbacks
- Define interfaces for the client and server
- For each method the client intends to make
asynchronous, the client should define a callback
object in OMG IDL. - The callback should contain parameters for all of
the return information required from the server.
For increased performance, the client callback
may be defined as a CORBA "oneway" operation. - The conversion to oneway
- "in" parameters should remain the same
- "inout" parameters should be converted to an "in"
parameter and also added to the list of return
information in the client callback - "out" parameters should be removed from the OMG
IDL interface and added to the list of parameters
in the client callback - if the operation has a return type, it should be
replaced with a void and added as a parameter in
the client callback interface
46The Distributed Callback Pattern
module DC forward foo_callback / This
interface defines server object operation of
interest to the client. / / It is defined
as oneway operation to allow the client to
continue processing / / while the server
performs the operation.
/ interface foo oneway
void op1(in object dataobj, in foo_callback
client) / This interface must be
implemented by the client / interface
foo_callback oneway void op1_cb(in
object dataobj, in long status)
In the implementation of foo op1, the last call
should be an invocation on foo_callback, using
the object reference passed into the op1
invocation. The server may optionally want to
check for an exception in case the client no
longer exists, or it may just wish to ignore it.
Also, by convention, if the client is not
interested in receiving the results of the
operation, it can pass in a NULL object
reference, in which case the server would not
invoke on the object reference upon operation
completion.
47Example Bank with a Callback Interface
- // Bank.idl
- module CallbackBank
- // IDL Interface for the Callback Proxy
- interface Callback
- oneway void sendMessage(in string str)
-
- interface Account
- float balance()
-
- interface AccountManager
- Account open(in Callback cb, in string name)
-