Title: Developing Basic CORBA Applications
1Developing Basic CORBA Applications
- DS 520 - Distributed System Frameworks
2Developing Basic CORBA Applications
- Review
- Summary of CORBA Interfaces
- Steps in Developing Basic CORBA-Java Application
- Example The Count Application
- Today
- Converting IORs to Strings for Portability
- More on IDL to Java Mapping
- Handling Exceptions
- Stock Server Example
- Project Phase I
3Summary of CORBA Interfaces
Implementation Installation
IDL Interface Definitions
Interface Repository
Implementation Repository
Client Stubs
Implementation Skeletons
Describes
Includes
Accesses
Includes
Client
Object Implementation
- All objects are defined in IDL by specifying
their interfaces. - Object definitions (interfaces) are manifested as
objects in the Interface Repository, as client
stubs, and as implementation skeletons. - Descriptions of object implementations are
maintained as objects in the Implementation
Repository.
4Steps in Developing CORBA Applications
- Write specification for each object using IDL
- Use IDL Compiler (e.g., idl2java) to generate
- Client Stub code
- Server Skeleton code
- Write the client (in Java, can be applications or
applets) - Write the server object implementation code (the
servant) - Compile the client and server code
- Start the server
- Run the client application
5The CORBA Count Example
- The Count Program
- the client will invoke a method increment() on
the remote object Count - increment() adds 1 to the value of the attribute
sum and returns the value to the client program - the initial value of sum is set by the client
(sum is a read/write attribute, so the client can
use CORBAs built-in accessor functions to
manipulate it.
- // Count.idl
- module Counter
-
- interface Count
-
- attribute long sum
- long increment()
-
-
First we must start with an IDL definition for
the Count object
6The IDL Compiler
- Now you can compile the IDL definition
- gt idl2java -no_tie Count.idl
- Important Notes
- if you are using Visibroker 3.3, you need JDK
1.1.8 as VBJ 3.3 is not compatible with Java 2
platform - in VBJ 4.x, idl2java compiler generated code is
based on the POA (portable object adapter)
semantics in order to use BOA semantics, must
use - gt idl2java -boa Count.idl
- also some additional casting needs to be done in
BOA initialization (more on this later, but see
Chapters 30 and 31 of the VBJ 4.x Programmers
Guide) - in VBJ 3.x, the idl2java compiler generated code
is based on BOA semantics (also the API for the
stub and skeleton code is different than those in
VBJ 4.x)
7Generated Classes Interfaces
- Counter._st_Count implements the client-side
stub for the Count object it provides the
marshaling functions for the client. _CountStub
in VBJ 4.x. - Counter._CountImplBase implements the
server-side skeleton for Count it unmarshals the
arguments passes by the client. CountPOA in VBJ
4.x using POA. - Counter.CountHelper provides some additional
utility functions for the client, including the
narrow operation for downcasting CORBA object
references, and (in this case) the Visibroker
specific bind operation for finding the remote
object. - Counter.CountHolder it is used as a wrapper for
passing out and inout parameters of type Count
(Java only natively supports in parameters). - Counter.Count contains the Java interface
corresponding to the IDL interface for Count the
object implementation for Count must implement
this interface. - Counter._example_Count a sample class for the
Count object implementation which could be
filled-in by the programmer. not generated in
VBJ 4.x.
package Counter public interface Count extends
org.omg.CORBA.Object public void sum(int
sum) public int sum() public int
increment()
8Class Hierarchy for BOA Count Interface
class org.omg.CORBA.portable.Skeleton (provided
by the ORB)
class org.omg.CORBA.portable.ObjectImpl (provided
by the ORB)
interface Counter.Count (generated by id2java)
Extends
Extends
abstract class Counter._CountImplBase (generated
by id2java)
Implements
abstract class Counter._st_Count (generated by
id2java)
Extends
class CountImpl (written by programmer and used
by the server)
Note in case of POA, the object skeleton
CountPOA extends org.omg.CORBA.PortableServer.Se
rvant
9Steps in Developing the Count Application
- Write a client program in Java
- this can be an applet or an application
- in this case we write a Java application
CountClient.java. - Write the server-side code for the Count
application - write a server application which creates and
serves instance(s) of the Count object (instances
of the class CountImpl) - write the object implementation (CountImpl).
- Object Implementation
- CORBA inheritance model the implementation class
is always derived from the corresponding
_XXXImplBase class generated by IDL compiler (in
this case from _CountImplBase Note with POA
this is XXXPOA, e.g., CountPOA - this inheritance allows the servant class to
obtain the properties of both CORBA and Java
object models - the alternative to inheritance model is to use
delegation (in CORBA terminology the Tie method)
if -no_tie option is not used with idl2java
relevant classes will be generated - in this case we create our CountImpl by modifying
the file _example_Count.java.
10The BOA Count Object Implementation
// CountImpl.java The Count Implementation class
CountImpl extends Counter._CountImplBase
private int sum // Constructors
CountImpl(String name) super(name)
System.out.println("Count Object Created")
sum 0 // get sum public int sum()
return sum // set sum public void
sum(int val) sum val // increment
method public int increment() sum
return sum
11Tasks Performed by the Main Server Class
- Initialize the Object Request Broker
- done by creating an instance of the ORB
pseudo-object - the static Java method init() on the class
org.omg.CORBA.ORB returns an instance of an ORB. - Initialize the Basic Object Adaptor
- a reference to an instance of the BOA is obtained
via the method BOA_init(). - Create the object (an instance of the class
implementation) - in this case we create an instance of CountImpl
class - Activate the newly created object
- in BOA this is done by calling the obj_is_ready()
method of the ORB instance on the object - this action exports the object to the ORB.
- Wait for incoming requests
- in BOA this is done by calling the
impl_is_ready() method of the ORB instance on the
object
12TheBOA Count Server
// CountServer.java The Count Server main
program class CountServer static public
void main(String args) try //
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() // Note if using VBJ 4.x
with -boa option the BOA // initialization
must be done with following cast //
com.inprise.vbroker.CORBA.BOA boa //
((com.inprise.vbroker.CORBA.ORB)orb).BOA_init()
// Create the Count object CountImpl
count new CountImpl("My Count") //
Export to the ORB the newly created object
boa.obj_is_ready(count) // Ready to
service requests boa.impl_is_ready()
catch(org.omg.CORBA.SystemException e)
System.err.println(e)
13Tasks Performed by the Client
- Initialize the ORB
- done the same way as for the server.
- Locate the Remote Object
- in this case client binds to the object via the
Visibroker bind() method. - Perform Operations via Remote Methods
- set the remote sum attribute to zero
- calculate the start time
- invoke the increment method 1000 times
- calculate the elapsed time
- print the results.
14The BOA Count Client
// CountClient.java Static Client, VisiBroker
for Java class CountClient public static void
main(String args) try //
Initialize the ORB org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init(args, null) //
Bind to the persistent Count Object reference
Counter.Count counter Counter.CountHelper.bi
nd(orb, "My Count") // Set sum to initial
value of 0 counter.sum((int)0) //
Calculate Start time long startTime
System.currentTimeMillis() // Increment
1000 times for (int i 0 i lt 1000 i
) counter.increment() // Calculate
stop time print out statistics long
stopTime System.currentTimeMillis()
System.out.println("Avg Ping "
((stopTime-startTime)/1000f)" msecs")
System.out.println("Sum " counter.sum())
catch(org.omg.CORBA.SystemException e)
System.err.println("System Exception")
System.err.println(e)
15Building and Running the Count Example
- Compile the client, server, and the
implementation classes - vbjc CountClient.java
- vbjc CountServer.java
- vbjc CountImpl.java
- Note you can use the -d option to place
generated classes in your specified direcotry - Start the Visibroker Smart Agent (OSAgent)
- osagent -c OR start osagent -c
- OSAgent may be installed as an NT Service or
started using the icon in the program menu - Start the Count Server vbj CountServer
- Execute the Client Application vbj CountClient
16POA BasicsRead Section 2.3.6 of Brose
- The POA is the portable mechanism used to
determine which servant should be invoked as a
result of a client request - POA maps an object reference to a servant that
implements the object - It allows for associating policy information with
objects - The POA policies can be used to transparently
activate objects, or to provide object
persistence over several server process lifetimes
(POA instances can be viewed as policy domains) - One POA (called the root POA) is supplied by each
ORB additional child POAs can be created and
configure them with different behaviors - the rootPOA, by default, provides a TRANSIENT
lifespan policy for objects - each POA has a name relative to the POA in which
it was created - There is a unique identifier (Object ID)
associated with each POA, that the POA uses to
identify an abstract object - Associations among object ids servants are kept
in an Active Object Map - POAs have manager objects that activate them or
change their processing state
17Basic Steps in setting up a POA
- Obtaining a reference to the root POA
- always done by calling resolve_initial_references(
"RootPOA") on the ORB instance - the returned CORBA object must be narrowed to the
correct type (which in this case is
PortableServerPOA) - Defining the POA policies
- child POAs do not inherit policies of their
parents, so policies must be set explicitly for
each POA instance - this done by populating an array of type
org.omg.CORBA.Policy - Creating a POA as a child of the root POA
- done by calling create_POA() on the instance of
the parent POA (e.g., the rootPOA) - Creating a servant and activating it
- creation of the servant is done in the same
manner as in BOA case - Activating the POA through its manager
18The POA Count Server
// CountServer.java The Count Server main
program import java.util.Properties import
org.omg.CORBA. import org.omg.PortableServer.
public class CountServer public static void
main(String args) try // Initialize the
ORB ORB orb ORB.init(args, null)
// get a reference to the root POA and
activate POA rootPOA
POAHelper.narrow(orb.resolve_initial_references("R
ootPOA")) Policy policies new
org.omg.CORBA.Policy
rootPOA.create_lifespan_policy(LifespanPolicyValue
.PERSISTENT) // Create countPOA
with the right policies POA countPOA
rootPOA.create_POA("count_poa",
rootPOA.the_POAManager(), policies)
// Create the Count object CountImpl
count new CountImpl() // Activate
the servant with the ID on rootPOA
byte countId "My Count".getBytes()
countPOA.activate_object_with_id(countId,
count) // Activate the POA manager
rootPOA.the_POAManager().activate()
// Wait for incoming requests
System.out.println("Count Server is ready.")
orb.run() catch(Exception e)
e.printStackTrace()
19The POA count Object Implementation
// CountImpl.java The Count Implementation class
CountImpl extends Counter.CountPOA private
int sum // Constructors CountImpl()
System.out.println("Count Object Created")
sum 0 // get sum public int sum()
return sum // set sum public void
sum(int val) sum val //
increment method public int increment()
sum return sum
Note For this application, the only difference
with the BOA version is that CountImpl
extends Counter.CountPOA rather than
Counter._CountImplBase.
20The POA CountClient
class CountClient public static void
main(String args) try //
Initialize the ORB System.out.println("Initi
alizing the ORB") org.omg.CORBA.ORB orb
org.omg.CORBA.ORB.init(args, null) // Get
the count Id byte countId "My
Count".getBytes() // Locate Count Object
System.out.println("Binding to Count
Object") Counter.Count counter
Counter.CountHelper.bind(orb, "/count_poa",
countId) // Set sum to initial value of
0 System.out.println("Setting sum to 0")
counter.sum(0) // Calculate Start
time long startTime System.currentTimeMill
is() // Increment 1000 times
System.out.println("Incrementing") for
(int i 0 i lt 1000 i )
counter.increment() // Calculate
stop time print out statistics long
stopTime System.currentTimeMillis()
System.out.println("Avg Ping ((stopTime -
startTime)/1000f) " msecs")
System.out.println("Sum " counter.sum())
catch(org.omg.CORBA.SystemException e)
21Using Stringified IORs for Portability
- Interoperable Object References
- Recall that CORBA uses IOR as a pointer to a
specific instance of a class in a distributed
environment - The IOR encodes host, port, and object identity
- May be externalized (using object_to_string)
- The resulting string can be passed to clients by
a variety of methods (e.g., read in from a file,
passed as an argument, accessed via a URL, smoke
signals) - The clients can convert these strings back into
live objects by calling string_to_object on the
ORB instance
22Using Stringified IORs for Portability
class CountServer static public void
main(String args) try
org.omg.CORBA.ORB orb org.omg.CORBA.ORB.init(arg
s, null) org.omg.CORBA.BOA boa
orb.BOA_init() CountImpl count new
CountImpl("My Count") try
String ior orb.object_to_string(count)
String iorFile count.ior"
java.io.PrintWriter out new
java.io.PrintWriter(new java.io.FileOutputStream(i
orFile)) out.println(ior)
out.flush() catch
(java.io.IOException ex)
ex.printStackTrace() System.exit(1)
boa.obj_is_ready(count)
boa.impl_is_ready() catch(org.omg.CORBA
.SystemException e) System.err.println(e)
23Using Stringified IORs for Portability
class CountClient public static void
main(String args) try
org.omg.CORBA.ORB orb org.omg.CORBA.ORB.init(arg
s, null) String ior null
System.out.println("Looking up IOR from local
file") try String iorFile
count.ior" java.io.BufferedReader in
new java.io.BufferedReader(new
java.io.FileReader(iorFile)) ior
in.readLine() catch(java.io.IOExcep
tion iox) iox.printStackTrace()
System.exit(1) org.omg.CORBA.Objec
t obj orb.string_to_object(ior) counter
Counter.CountHelper.narrow(ior)
counter.sum(0) // rest of the program as
before . . .
24The Structure of CORBA IDL
- Modules
- provide namespaces for a set of related class
descriptions - map to Java packages with the same name
- Interfaces
- specification of the operations a client can
invoke on a remote object - in addition to operations, interfaces include
constructs such as - constant declarations
- attributes (can be read/write or readonly
implementation automatically creates get and set
operations for these attributes) - exceptions (raised if the operations do not
perform successfully) - Operations
- CORBA equivalent of methods in Java
- IDL defines the operations signature parameters
and return values/types - parameters can be in, out, or inout
- IDL also defines what exceptions can be raised by
the operation
25Data Types in CORBA IDL
- Basic Types
- short, long, unsigned long, unsigned short,
float, double, long double, char, wchar, boolean,
string, octet, etc. - Constructed Types
- struct and union (similar to C can be used in
conjunction with a typedef) - sequence (variable sized arrays of objects)
- any (generic type which represents any possible
IDL types similar to the Java Object type) - enum (enumerated type with named integer values)
- arrays
- valuetypes (similar to interfaces preceded with
keyword valuetype to provide pass-by-value
semantics) - Each CORBA IDL data type gets mapped to a native
data type via the appropriate language binding
(e.g, IDL-to-Java mapping).
26An IDL Example
module RoomBooking interface Meeting
readonly attribute string purpose
readonly attribute string participants
oneway void destroy() interface
MeetingFactory Meeting CreateMeeting(in
string purpose,in string participants)
interface Room // A Room provides
methods to view, make,cancel bookings.
enum Slot am9, am10, am11, pm12, pm1,
pm2, pm3, pm4 const short MaxSlots
8 typedef Meeting Meetings MaxSlots
exception NoMeetingInThisSlot
exception SlotAlreadyTaken
readonly attribute string name
Meetings View() void Book( in Slot
a_slot, in Meeting a_meeting )
raises(SlotAlreadyTaken) void Cancel( in
Slot a_slot ) raises(NoMeetingInThisS
lot)
27Methods and Parameters
- Marshalling
- Before a method is invoked, parameters are
marshaled across the network to the remote object - After the method executes, any out and inout
parameters--along with the method's return value,
if any, are marshaled back to the calling object.
- Note that inout parameters are marshaled
twice--once as an input value and once as an
output value - oneway Methods
- Normally, when an object calls a method on a
remote object, that calling object waits (this is
called blocking) for the method to execute and
return. When the remote object finishes
processing, it returns to the calling object,
which then continues its processing. - When a method is declared oneway, the calling
object will not block it will call the remote
method and continue processing, while the remote
object executes the remote method. - In a oneway method, the return value must be
declared void, and all parameters must be
declared as in (out and inout parameters are
not allowed). A oneway method cannot raise any
exceptions.
28Blocking v. oneway Calls
Component A
Component B
method invocation
X
blocked on method call
processing
method returns
processing resumes
Component A
Component B
oneway method invocation
processing contnues (no blocking)
processing
method finishes
29Attributes
- An attribute of an IDL always have public
visibility (everything in an IDL interface has
public visibility.) - The general syntax for defining an attribute
- readonly attribute attribute_type
attributeName - IDL attributes map to accessor and mutator
methods - attribute short myChannel
- maps to the following two methods
- short myChannel()
- void myChannel(short value)
- For a readonly attribute the IDL compiler will
generate only an accessor method. Value of a
readonly attribute cannot be modified directly by
an external object (the object implementing the
interface, however, can modify values of its own
attributes).
30The any Type
- When any is used as the type of a parameter or
return value, that value can literally be any IDL
type - the browseObject() method accepts a single
parameter of type any - a client calling this method can use an object of
any IDL type to fill this parameter - internally to browseObject(), the method will
attempt to determine what the actual type of
object is - if it determines that object is a type of object
it can interact with, it will do so - otherwise, it will raise the UnknownObjectType
exception, which is returned to the caller
interface ObjectBrowser exception
UnknownObjectType string message
void browseObject(in any object) raises
(UnknownObjectType)
31The TypeCode Pseudotype
- TypeCode is not actually an IDL type it provides
type information to a CORBA application - when a method accepts an any type as an argument,
the actual type of that object is unknown - both standard types and user-defined types have
unique TypeCodes - the TypeCode interface describes the various
types that are defined in IDL and allows them to
be created and examined at runtime - a method implementation can determine which type
of object was sent through its any parameter - when the object's type is determined, the method
can act on that object - think of TypeCodes as a sort of runtime-type
information for CORBA applications
32Java Mapping Exceptions and Declarations
- If the IDL interface contains exception
declarations, then the IDL Compiler generates a
new package containing the helper, holder, and
the implementation classes for the exception
(this also applies to other interface
declarations such as typedef and constant
declarations). - For instance, in the Room Booking example, the
directory \RoomBooking\RoomModule will include
the following files - MaxSlots.java
- MeetingsHelper.java
- MeetingsHolder.java
- NoMeetingInThisSlot.java
- SlotAlreadyTaken.java
- NoMeetingInThisSlot.java
- . . .
- Slot.java
- SlotHelper.java
- SlotHolder.java
33Using the Generated Exceptions The Room Booking
Example
public void Book( Slot slot, Meeting meeting )
throws RoomBooking.RoomPackage.SlotAlreadyTak
en if( meetingsslot.value() null )
meetingsslot.value() meeting else
throw new RoomBooking.RoomPackage.SlotAlready
Taken() return public void
Cancel( Slot slot ) throws RoomBooking.RoomPacka
ge.NoMeetingInThisSlot System.err.println("ca
ncel " slot ) if( meetingsslot.value() !
null ) meetingsslot.value().destroy()
meetingsslot.value() null else
throw new RoomBooking.RoomPackage.NoMeetingInTh
isSlot()
// RoomImpl.java public class RoomImpl
extends _RoomImplBase private String name
private Meeting meetings // constructor
public RoomImpl( String name )
super(name) this.name name meetings
new Meeting MaxSlots //
attributes public String name() return
name // operations public
Meeting View() return meetings
34Example A CORBA Stock Server
// StockMarket.idl module Stocks // The
StockSymbol type is used for symbols (names) //
representing stocks. typedef string
StockSymbol // A StockSymbolList is a
sequence of StockSymbols. typedef
sequenceltStockSymbolgt StockSymbolList // The
StockMarket interface is the interface for a //
server which provides stock market information.
interface StockMarket // getStockValue()
returns the current value for // the given
StockSymbol. If the given StockSymbol // is
unknown, the results are undefined float
getStockValue(in StockSymbol symbol) //
getStockSymbols() returns a sequence of all
// StockSymbols known by this StockServer.
StockSymbolList getStockSymbols()
- The IDL interface for the CORBA Stock Server
35Stock Server StockMarketImpl
// StockMarketImpl.java import java.util.Vector i
mport org.omg.CORBA.ORB public class
StockMarketImpl extends Stocks._StockMarketImplBas
e private Vector myStockSymbols private
Vector myStockValues private static char
ourCharacters 'A','B','C','D','E','F','G','H'
, 'I', 'J','K','L','M','N','O','P','Q','R','S','
T','U','V','W','X','Y','Z' public
StockMarketImpl(String name) // the
constructor super(name) myStockSymbols
new Vector() myStockValues new
Vector() // Initialize the symbols and
values with some random values for (int i
0 i lt 10 i) // Generate a string of
four random characters StringBuffer
stockSymbol new StringBuffer(" ") for
(int j 0 j lt 4 j)
stockSymbol.setCharAt(j, ourCharacters(int)(Math.
random() 26f))
myStockSymbols.addElement(stockSymbol.toString())
// Give the stock a value between 0 and
100. myStockValues.addElement(new
Float(Math.random() 100f)) . .
.
36Stock Server StockMarketImpl (Cont.)
// StockMarketImpl.java ... // Return the
current value for the given StockSymbol. public
float getStockValue(String symbol) // Try
to find the given symbol int stockIndex
myStockSymbols.indexOf(symbol) if
(stockIndex ! -1) // Symbol found
return its value return ((Float)myStockValue
s.elementAt(stockIndex)).floatValue() else
// Symbol was not found return 0f
// Return a sequence of all
StockSymbols known by this StockServer. public
String getStockSymbols() String
symbols new StringmyStockSymbols.size()
myStockSymbols.copyInto(symbols) return
symbols
37Stock Server The Server Application
// Server.java import java.util.Vector import
org.omg.CORBA.ORB import org.omg.CORBA.BOA clas
s Server static public void main(String
args) try // Initialize the ORB
ORB orb ORB.init(args, null) //
Initialize the BOA org.omg.CORBA.BOA boa
orb.BOA_init() // Create a
StockMarketImpl object and register it with the
ORB StockMarketImpl stockServer
new StockMarketImpl("My Stocks")
boa.obj_is_ready(stockServer) //
Ready to service requests
boa.impl_is_ready() catch
(org.omg.CORBA.SystemException ex)
System.err.println("Couldn't bind StockServer "
ex)
38Stock Server The Client Application
// Client.java import org.omg.CORBA.ORB //
StockMarket Client is a simple client of a
StockServer. class Client public static
ORB myORB // My StockServer private
Stocks.StockMarket myStockServer // Create
a new Client Client() // Run the
Client public void run()
connect() if (myStockServer ! null)
doSomething()
...
39Stock Server The Client Application (Cont.)
// Client.java ... protected void connect()
// Connect to the Server try
myStockServer Stocks.StockMarketHelper.bind(myOR
B, "My Stocks") catch (Exception ex)
System.err.println("Couldn't resolve
StockServer " ex) myStockServer
null return
System.out.println("Succesfully bound to a
StockServer.") protected void
doSomething() try // Get
the valid stock symbols from the StockServer.
String stockSymbols
myStockServer.getStockSymbols() //
Display the stock symbols and their values.
for (int i 0 i lt stockSymbols.length
i) System.out.println(stockSym
bolsi " "
myStockServer.getStockValue(stockSymbolsi))
catch (org.omg.CORBA.SystemEx
ception ex) System.err.println("Fata
l error " ex)
40Stock Server The Client Application (Cont.)
// Client.java ... // Start up a Client
public static void main(String args)
// Initialize the ORB myORB
ORB.init(args, null) Client stockClient
new Client() stockClient.run()
41Stock Server Simple GUI Client
42Stock Server Simple GUI Client
// Client.java import java.awt. import
org.omg.CORBA.ORB class Client extends Frame
public static ORB myORB private static
Stocks.StockMarket myStockServer Button
button1 new java.awt.Button() TextArea
textArea new java.awt.TextArea() Label
label1 new java.awt.Label() public Client()
// Initialize GUI setLayout(null) ...
button1.setLabel("Get Stocks") add(button1)
... add(textArea) ... add(label1) ...
ClientAction lAction new ClientAction() butt
on1.addActionListener(lAction)
43Stock Server Simple GUI Client (Cont.)
// Client.java ... public void
setVisible(boolean b) if(b)
setLocation(50, 50) super.setVisible(b)
public static void main(String args)
// Initialize the ORB myORB
ORB.init(args, null) // Create new client
frame (new Client()).setVisible(true)
try myStockServer
Stocks.StockMarketHelper.bind(myORB, "My
Stocks") catch (Exception ex)
System.err.println("Couldn't resolve
StockServer " ex)
System.out.println("Succesfully bound to a
StockServer.")
44Stock Server Simple GUI Client (Cont.)
// Client.java ... class ClientAction
implements java.awt.event.ActionListener
public void actionPerformed(java.awt.event.Act
ionEvent event) Object object
event.getSource() if (object
button1) button1_ActionPerformed(event)
void button1_ActionPerformed(java.awt.event.Ac
tionEvent event) try // Get
the valid stock symbols from the StockServer.
String stockSymbols
myStockServer.getStockSymbols() //
Display the stock symbols and their values.
for (int i 0 i lt stockSymbols.length
i) textArea.append(stockSymbol
si " "
myStockServer.getStockValue(stockSymbolsi)
"\n") catch
(org.omg.CORBA.SystemException ex)
System.err.println("Fatal error " ex)
45Stock Server Using Exceptions
// StockMarket.idl module Stocks exception
InvalidStockSymbolException typedef
string StockSymbol // A StockSymbolList is a
sequence of StockSymbols. typedef
sequenceltStockSymbolgt StockSymbolList // The
StockMarket interface is the interface for a //
server which provides stock market information.
interface StockMarket // getStockValue()
returns the current value for // the given
StockSymbol. If the given StockSymbol // is
unknown, the results are undefined float
getStockValue(in StockSymbol symbol)
raises (InvalidStockSymbolException) //
getStockSymbols() returns a sequence of all
// StockSymbols known by this StockServer.
StockSymbolList getStockSymbols()
- The IDL interface for the CORBA Stock Server
46Stock Server Using Exceptions
- In the object implementation the getStockValue
will throw a - Java exception, in case there is an invalid stock
symbol.
// StockMarketImpl.java ... // Return the
current value for the given StockSymbol. public
float getStockValue(String symbol) throws
InvalidStockSymbolExceptio
n // Try to find the given symbol int
stockIndex myStockSymbols.indexOf(symbol)
if (stockIndex ! -1) // Symbol found
return its value return ((Float)myStockValue
s.elementAt(stockIndex)).floatValue() else
// Symbol was not found throw new
InvalidStockSymbolException() . . .
47Stock Server Using Exceptions
- In the client application the exception can be
incorporated by - including a new try-catch block.
// Client.java ... protected void
doSomething() try // Get the
valid stock symbols from the StockServer.
String stockSymbols myStockServer.getStockSymb
ols() // Display the stock symbols and
their values. for (int i 0 i lt
stockSymbols.length i) try
System.out.println(stockSymbolsi " "
myStockServer.getStockValue(stockS
ymbolsi)) catch
(InvalidStockSymbolException ex)
System.out.println("Invalid stock symbol.")
catch (org.omg.CORBA.Syst
emException ex) System.err.println("
Fatal error " ex)
48Project Phase 1
- Server supports one auction at a time, with a
single seller and multiple bidders - each auction corresponds to a single item
- Once the item is sold, another auction may be
started by a seller - Simple GUI interface needed for Bidder Seller
- Server must not lose information if clients are
shut down and restarted - Errors must produce reasonable output (both on
client and server sides)
Bidder
Bidder
Bidder
Auction
Seller
49Project Phase 1
If the auction is empty, any user may become
a Seller by offering an item for sale.
Offer
The Seller provides a user ID, a description of
the item, and an initial price.
If at least one Bid has been accepted, the Seller
may sell the item. The actual sale is assumed to
take place outside the scope of the Auction.
Sell
The Seller must identify itself by providing the
same userID that was used in the offer operation
Seller
By providing its userID, the current Seller may
view the userID of the current high bidder, if
any.
View_high_bidder
50Project Phase 1
Any user may place a bid on the current
item, provided There is a current item that has
not yet been sold. The user is identified by a
userID different from the userID of the current
Seller. The bid price is higher than the initial
price and the prices of all other bids that have
been placed so far for the current item. If the
bid succeeds, the bidder's userID is stored
as the current high bidder, and the price
becomes the current price. If the bid succeeds,
the bidder's userID is stored as the current high
bidder, and the price becomes the current price.
Bid
Bidder
By providing its userID, any user can determine
if it is the current high bidder. This operation
will fail if the auction is not currently active
(no item for sale, or current item already sold).
View_bid_status
51Project Phase 1
Any user may view the current status of the
auction. Status information includes auction
state (empty or active) and, if the auction is
active, description of the item and its current
price (initial price or highest bid so far).
Seller
View_auction_status
Bidder
52Auction Server GUI Separate Applications
53Auction Phase I A Sample IDL
module AuctionModule interface Auction
exception InvalidBidException string
description exception InvalidSellException
string description ... typedef struct
AuctionStatus string item float
currentPrice Status // seller accessible
methods boolean offer(in string sellerId, in
string item, in float initPrice) boolean
sell(in string sellerId) raises
(InvalidSellException) string
viewHighBidder(in string sellerId) raises
(InvalidSellException) // bidder accessible
methods boolean bid(in string userId, in float
bidPrice) raises (InvalidBidException) boole
an viewBidStatus(in string userId)
raises (InvalidBidException) // universally
accessible methods Status viewAuctionStatus()
raises ()