// IDL // IOn the server side, the overall aim will be to create a server that contains a singlen,
for example,
"bank.idl"1. interface Account { // Bank accounts. readonly attribute float balance; void makeDeposit(in float f); void makeWithdrawal(in float f); }; // A factory for bank accounts.
interface Bank { // Make a new account to be associated with // the person or company whose name is given. Account newAccount(in string name); // Delete an account. void deleteAccount(in Account a); };
Bank
object that will accept operation calls such as newAccount()
from clients. In this example, all of the objects (both Bank
and Account
objects) will be in a single server; although in a real system several servers may be used and objects may also exist in clients. The server in our example will be called BankSrv
. Note that a server can, without difficulty, manage objects of two different interfaces.The remainder of this chapter will cover the following programming steps:
Account
and Bank
.
Bank
object.
newAccount()
, in order to illustrate the use of Holder
classes.In subsequent chapters, we will add further functionality to the
Account
and Bank
interfaces defined above; for the time being, these basic interfaces are sufficient to illustrate the main points. Later chapters will allow operations to raise user-defined exceptions and add a further interface defined using inheritance.
idl -jP idl_demo bank.idlThe Java code produced by the IDL compiler will be generated within the
idl_demo
package, which will help to avoid clashes in the global Java name space.Once the IDL source file,
bank.idl
, is compiled, a number of Java source files are generated. By default, all generated files will be created in a subdirectory called java_output
. In our example, the -jP
compiler switch results in the creation of these files in an idl_demo
directory (which is a subdirectory of java_output
), in compliance with the Java convention of mapping package names to subdirectories.For each interface defined in
bank.idl
(that is, interface Account
and interface Bank
), the IDL compiler generates seven Java source files. Each source file contains a single Java type with a specific function. For example, the following types are generated for interface Account
:It is essential that the programmer understands the IDL to Java mapping, and thus understands the Java types generated by the IDL compiler. These correspond directly to the interfaces defined in the IDL source. A description of the IDL to Java mapping was presented in Chapter 5, "IDL to Java Mapping".
The Holder
types generated by the IDL compiler are not required in our first example, as the IDL definition includes no operations which pass Account
or Bank
objects as inout
or out
parameters. In section 6.9, we will examine a modified version of this IDL definition, in order to illustrate the use of these Holder
types.
6.2 A Client Program
From the point of view of the client, the functionality provided by the banking service is defined by the IDL interface definitions. A typical client program locates a remote object, obtains a reference (binds) to the object and then invokes operations on the object.
// Java // In file Client.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; public class Client { public static void main (String args[]) { _BankRef bRef = null; _AccountRef aRef = null; float f = (float) 0.0; try { // Bind to any Bank object // in the BankSrv server. bRef = Bank._bind (":BankSrv"); // Obtain a new bank account. aRef = bRef.newAccount ("Joe"); } catch (SystemException se) { System.out.println ( "Unexpected exception on bind"); System.out.println (se.toString ()); } try { // Invoke operations on Account. aRef.makeDeposit ((float)56.90); f = aRef.get_balance(); System.out.println ("Current balance is " + f); } catch (SystemException se) { System.out.println ( "Unexpected exception" + " on makeDeposit or balance"); System.out.println (se.toString ()); } }The Java class
Bank
is generated by the IDL compiler. The static method Bank._bind()
requests OrbixWeb to search for an object offering the Bank
IDL interface. The IDL compiler generates three overloaded _bind()
methods for each IDL interface. In the case of the Bank
interface, these methods are defined as follows:
// Java // Automatically generated // in file Bank.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.CompletionStatus; public class Bank extends IE.Iona.Orbix2.CORBA.BaseObject implements idl_demo._BankRef { ... public static final idl_demo._BankRef _bind() throws IE.Iona.Orbix2.CORBA.SystemException { ... } public static final idl_demo._BankRef _bind(String markerServer) throws IE.Iona.Orbix2.CORBA.SystemException { ... } public static final idl_demo._BankRef _bind(String markerServer, String host) throws IE.Iona.Orbix2.CORBA.SystemException { ... } ... }Detailed information on the parameters to
_bind()
is provided in Chapter 7, "Publishing Object References in Servers".
6.2.1 Object Location
The client does not specify a host at which to contact the server. As a result, OrbixWeb will make an implicit call to the default locator in order to find a host on which the required server has been registered. Chapter 24, "Locators", describes the functionality of the OrbixWeb locator mechanism.
The OrbixWeb _bind()
methods provide two alternatives to the default locator when attempting to locate a host on which a given server resides: the first is to override the default locator with a user-defined locator implementation (as described in Chapter 24, "Locators"); the second is to locate the server host in advance of a call to _bind()
and then specify the known host name to the _bind()
method (as described in Chapter 7, "Publishing Object References in Servers").
The parameter
markerServer
allows the object marker and server name to be specified in the _bind()
call. In our example, no object marker is specified, so OrbixWeb is free to select any available object which matches the remaining location parameters. The markerServer
value ":BankSrv
" instructs OrbixWeb to search for the required object in the BankSrv
server.6.2.2 Binding
Although OrbixWeb supports collocation of client and server in a single address space, in our example the client and server applications are distributed. Consequently, the call to _bind()
in our client will construct a proxy for the specified object. The _bind()
method returns a reference to the proxy object of type _BankRef
. The Java methods of this reference type define the client's view of the Bank
IDL interface._bind()
call will not create a proxy for the specified object: if a proxy for the object already exists in the client address space, this existing proxy will be returned, and if a system exception is thrown during the _bind()
call then the return value will be undefined._bind()
is not always required before communicating with a particular object: if a call to another object returns a reference to a remote object, then this will result in the creation of a proxy for it. For example, operation newAccount()
returns a reference to an Account
object.
6.2.3 Remote Invocations
The proxy object reference returned by _bind()
provides access to remote Bank
operations via the Java methods defined on interface _BankRef
. The client can invoke these operations by simply calling the equivalent Java methods on the proxy object. The proxy is responsible for forwarding the invocation requests to the target server implementation object and returning results to the client._AccountRef
and _BankRef
are generated by the IDL compiler. These interfaces define the Java client view of the IDL Account
and Bank
interfaces._AccountRef
is as follows:
// Java // Automatically generated // in file _AccountRef.java. package idl_demo; public interface _AccountRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException; public void makeDeposit(float f) throws IE.Iona.Orbix2.CORBA.SystemException; public void makeWithdrawal(float f) throws IE.Iona.Orbix2.CORBA.SystemException; }The code for
_BankRef
is:
// Java // Automatically generated // in file _BankRef.java. package idl_demo; public interface _BankRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public idl_demo._AccountRef newAccount( String name) throws IE.Iona.Orbix2.CORBA.SystemException; public void deleteAccount( idl_demo._AccountRef a) throws IE.Iona.Orbix2.CORBA.SystemException; }Both
Ref
types inherit from the Java interface _ObjectRef
. This is an OrbixWeb interface which defines functionality common to all IDL object reference types. Information on this extra functionality can be found in Part II, "Class and Interface Reference" of the OrbixWeb Reference Guide.
6.3 The Server: Implementing Interfaces
To implement an interface, a Java programmer must provide a Java class (in OrbixWeb terminology, an implementation class) which has a method definition for each of the operations and attributes of the interface. An implementation class must provide (at least) the operations defined in the IDL interface which it is declared to implement.
_<IDL interface name>OperationsFor example, the Java interface
_AccountOperations
defines the methods which must by provided by an implementation class for IDL interface Account
. Interface _AccountOperations
is generated by the IDL compiler as follows:
// Java // Automatically generated // in file _AccountOperations.java. package idl_demo; public interface _AccountOperations { public float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException; public void makeDeposit(float f) throws IE.Iona.Orbix2.CORBA.SystemException; public void makeWithdrawal(float f) throws IE.Iona.Orbix2.CORBA.SystemException; }OrbixWeb supports two mechanisms for relating an implementation class to its IDL interface: the BOAImpl approach and the TIE approach. These will be discussed in turn in section 6.3.1 and section 6.3.2. Most server programmers use one of these approaches exclusively, but there is no difficulty mixing them in the same server.
The choice of implementation method in an OrbixWeb server does not affect the coding of client applications.
6.3.1 BOAImpl Approach
For each IDL interface, OrbixWeb generates an abstract Java class, using the string _boaimpl_
appended with the name of the interface. For example, it generates the class _boaimpl_Account
for the IDL interface Account
. To indicate that a Java class implements a given IDL interface, that class should inherit from the corresponding BOAImpl-class. This approach is termed the BOAImpl approach.Operations
interface; for example class _boaimpl_Account
implements the Java interface _AccountOperations
. In this way, an implementation class which inherits and implements the abstract methods of a BOAImpl-class must implement the operations of the corresponding IDL interface.Account
IDL interface. The OrbixWeb IDL compiler produces the Java interface _AccountOperations
and the Java classes Account
and AccountBOAImpl
. The programmer defines a new class, class AccountImplementation
, to implement the operations and attributes defined in the IDL interface. In addition to having methods that correspond to IDL operations and attributes, class AccountImplementation
can have user defined constructors and additional members.
![]() |
In this chapter and throughout this guide, we use the convention that interface
A
is implemented by class AImplementation
. This naming scheme does not have to be adhered toindeed some applications may need to implement interface A
a number of times.6.3.2 TIE Approach
In the second approach, the programmer can implement the IDL operations and attributes in a class that does not inherit from the automatically generated BOAImpl-class. Instead, the programmer uses an automatically generated Java class to tie together the implementation class and the IDL interface. The second approach is termed the TIE approach. (For a comparison of the BOAImpl and TIE approaches, see section 6.8.)
To support the TIE approach, the IDL compiler generates a Java TIE-class for each IDL interface, using the string
_tie_
appended with the name of the interface. An object which implements the IDL interface can be passed as a parameter to the constructor for the TIE class. To tie a Java implementation object to an IDL interface, the programmer creates a TIE object for the interface and passes an implementation object to the TIE constructor._tie_Account
for the IDL interface type Account
. The programmer defines a new class, class AccountImplementation
, to implement the operations and attributes defined in the IDL interface. This class need not inherit from any automatically generated class, but it must implement the Java interface _AccountOperations
. The programmer instantiates an object of type _tie_Account
, passing an object of type AccountImplementation
to the constructor. A TIE object will be created which will delegate incoming operation invocations to the methods of the programmer's AccountImplementation
object.
![]() |
6.4 The Server: Coding the Implementation Classes
In this section, we show a very simple implementation of the banking application illustrating both the BOAImpl and TIE approaches. These will be discussed in turn with separate examples of each, although both approaches can be mixed in the same server. We have ignored any error checkingfor example placing the account into "the red"which would be necessary in a full banking application.
BankImplementation
implements the Bank
interface.
AccountImplementation
implements the Account
interface.6.4.1 The BOAImpl Approach
We indicate that a class implements a specific IDL interface by inheriting from the corresponding BOAImpl-class generated by the IDL compiler. Class AccountImplementation
could be written as follows:
// Java // In file AccountImplementation.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; class AccountImplementation extends idl_demo._boaimpl_Account { protected String m_name; protected float m_balance; protected AccountImplementation m_next; public AccountImplementation() throws SystemException { super (); m_name = ""; m_balance = 0; m_next = null; } public AccountImplementation (float initialBalance, String name) throws SystemException { super (); m_name = name; m_balance = initialBalance; m_next = null; } public String name () { return m_name; } public AccountImplementation next () { return m_next; } public float get_balance() { return m_balance; } public void makeDeposit (float f) { m_balance +=f; } public void makeWithdrawal(float f) { m_balance -=f; } }The code for class
BankImplementation
is outlined below:
// Java // In file BankImplementation.java. package idl_demo; import IE.Iona.Orbix2.CORBA.SystemException; import java.util.Vector; class BankImplementation extends idl_demo._boaimpl_Bank { protected Vector AccList; public BankImplementation () throws SystemException { super (); AccList = new Vector (); } public void record(String name, AccountImplementation p) { // Details shown later. } public idl_demo._AccountRef newAccount(String name) throws SystemException { // Details shown later. } public void deleteAccount (idl_demo._AccountRef p) { // Details shown later. } }Classes
AccountImplementation
and BankImplementation
redefine each of the abstract methods inherited from their respective BOAImpl classes; they may add constructors, methods and member variables.The accounts managed by a bank are stored in a list of type
java.util.Vector
. This allows a BankImplementation
object to manage existing accounts.
BankImplementation.newAccount()
, we will need to construct a new AccountImplementation
object. The method newAccount()
corresponds to an IDL operation, and its return value is of type _AccountRef
:
// Java // In class BankImplementation public idl_demo._AccountRef newAccount(String name) throws SystemException { idl_demo._AccountRef acc = null; // Ensure that we do not already have an Account // for the given name, and if we are happy that // the name is okay, then: if (happyToProceed) { try { acc = new AccountImplementation (0, name); } catch (SystemException se) { // Details omitted. } record (name, acc); return acc; } else { // Details omitted. } }Each BOAImpl-class generated by the IDL compiler can raise an OrbixWeb system exception in the class constructor. The class
AccountImplementation
inherits from _boaimpl_Account
, so it is therefore necessary to enclose the construction of a new AccountImplementation
object in a Java try
statement, in order to catch possible system exceptions.The method
record()
simply adds the new AccountImplementation
object to the list of existing accounts:
// Java // In class BankImplementation. public void record (String name, accountImplementation p) { AccList.addElement (p); }The method
deleteAccount()
corresponds to an IDL operation, and it simply removes a specified account from the list of AccountImplementation
objects:
// Java // In class BankImplementation. public void deleteAccount (idl_demo._AccountRef p) { AccList.removeElement (p); }In the code shown above, we have chosen to ignore the possibility of making the server objects persistent. This can be done by storing the account and bank data in files or in a database.
Operations
interface which was generated by the IDL compiler from the IDL interface definition. We notify OrbixWeb that this class implements that IDL interface by creating an object of the TIE-class, which was also generated by the IDL compiler.The code for class
AccountImplementation
can be outlined as follows:
// Java // In file AccountImplementation.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; class AccountImplementation implements idl_demo._AccountOperations { protected String m_name; protected float m_balance; protected accountImplementation m_next; public AccountImplementation() { // Details omitted. } public AccountImplementation (float initialBalance, String name) { // Details omitted. } // Accessor methods and // operation implementation methods // as before. }A
_tie_Account
object could be instantiated in the following way:
// Java package idl_demo; ... _AccountRef accImpl = null; try { accImpl = new _tie_Account (new AccountImplementation ()); } catch (SystemException se) { ... }The TIE approach does not place an inheritance requirement on an implementation class. This leaves the implementation programmer free to choose the inheritance hierarchy of the implementation class, without restriction. In this way, the TIE approach can be very useful when using a pre-existing Java class as an implementation class for an IDL interface.
BankImplementation
, could now be rewritten as follows:
// Java // In file BankImplementation.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; import java.util.Vector; class BankImplementation implements idl_demo._BankOperations { Vector AccList; public bankImplementation () { AccList = new Vector (); } public void record (String name, idl_demo._AccountRef p) { AccList.addElement (p); } public idl_demo._AccountRef newAccount (String name) throws SystemException { AccountImplementation accImpl = new AccountImplementation (0, name); _AccountRef acc; try { acc = new _tie_Account (accImpl); } catch (SystemException se) { // Details omitted. } record (name, acc); return acc; } public void deleteAccount (idl_demo._AccountRef p) { AccList.removeElement(p); } }Note that the method
newAccount()
returns an object which implements Java interface _AccountRef
. This IDL generated type defines the client view of the IDL interface Account
. An object of type _tie_Account
can be returned as type _AccountRef
, as class _tie_Account
inherits from the IDL generated class Account
, which in turn implements Java interface _AccountRef
.
main()
method of a banking application class, using both the BOAImpl and the TIE approaches.
main()
method for a typical server class shows the creation of a Bank
object. It takes the following form:
// Java // In file BankServer.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; public class BankServer { public static void main (String args[]){ // Declare BankImplementation object. BankImplementation bankImpl = null; // Instantiate BankImplementation object. try { bankImpl = new BankImplementation (); } catch (SystemException se) { // Details omitted. } try { // Wait for incoming requests. _CORBA.Orbix.impl_is_ready ("BankSrv"); } catch (SystemException se) { // Details omitted. } } };The code instantiates a single
BankImplementation
object which will handle incoming requests for clients through the IDL Bank
interface. The BankImplementation
object is created using a default constructor (that is, a constructor with no parameters). As BOAImpl-class constructors can raise OrbixWeb system exceptions, error handling code must surround the object creation.Having created a
BankImplementation
object, the server calls impl_is_ready()
on the _CORBA.Orbix
object (defined within the IE.Iona.Orbix2
package) to indicate that it has completed initialisation and is ready to receive operation requests on its objects.
main()
method is similar in the TIE approach. The most significant difference is that the server creates a TIE
object as well as a BankImplementation
object:
// Java // In file BankServer.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; public class BankServer { public static void main (String args[]){ // Instantiate BankImplementation object. BankImplementation bankImpl = new BankImplementation (); // Declare TIE object. _BankRef bankRef; try { bankRef = new _tie_Bank (bankImpl); } catch (SystemException se) { // Details omitted. } try { // Wait for incoming requests. _CORBA.Orbix.impl_is_ready ("BankSrv"); } catch (SystemException se) { // Details omitted. } } };The
BankImplementation
object is created using a default constructor. Unlike the BOAImpl example, the default constructor cannot raise an OrbixWeb system exception. However, it is important to note that the default constructor for type _tie_Bank
can raise an exception.
_CORBA.Orbix.impl_is_ready()
to indicate that it has completed its initialisation and is ready to receive operation requests on its objects. _CORBA.Orbix
is a static object (of class BOA
or, optionally, ORB
), which is used to communicate directly with OrbixWeb, to determine or change its settings.The
impl_is_ready()
method normally does not return immediately: it blocks the server until an event occurs, handles the event, and re-blocks the server to await another event.The method
impl_is_ready()
is actually declared four overloaded methods, as follows:
// Java // In package IE.Iona.Orbix2.CORBA, // in class BOA. public void impl_is_ready () throws SystemException; public void impl_is_ready (String serverName) throws SystemException; public void impl_is_ready (int timeout) throws SystemException; public void impl_is_ready (String serverName, int timeout) throws SystemException;When a server is launched by the OrbixWeb daemon process,
orbixd
, the server name will already be known to OrbixWeb and therefore does not need to be passed to impl_is_ready()
(however, if it is passed, it must be correct). However, when a server is launched manually, the server name must be communicated to OrbixWeb, and the normal way to do this is as the first parameter to impl_is_ready()
. To allow a server to be launched either automatically or manually, it is recommended, therefore, that the serverName
parameter be specified.By default, servers must be registered with OrbixWeb, using the
putit
command. Therefore, if an unknown server name is passed to impl_is_ready()
, the call will be rejected. However, the OrbixWeb daemon (orbixd
) can be configured to allow unregistered servers to be run manually (see Chapter 3, "OrbixWeb Configuration" of the OrbixWeb Reference Guide).
serverName
parameter is the name of a server as registered in the Implementation Repository (using putit
). It need not be the name of a class or interface (and it would normally be confusing to make it so). If specified, it should be exactly the server name registered in the Implementation Repository.
impl_is_ready()
method returns only when a timeout occurs or an exception occurs while waiting for or processing an event. The timeout
parameter indicates the number of milliseconds to wait between events: a timeout will occur if OrbixWeb has to wait longer than the specified timeout for the next event. A timeout of zero indicates that impl_is_ready()
should time out and return immediately without checking if there is any pending event. A timeout does not cause impl_is_ready()
to raise an exception.Note that a server can time out either because it has no clients for the timeout duration, or because none of its clients uses it for that period.2
The default timeout can be passed explicitly as
_CORBA.IT_DEFAULT_TIMEOUT
. An infinite timeout can be specified by passing _CORBA.IT_INFINITE_TIMEOUT
.6.5.4 Construction and Markers
The name of an OrbixWeb object includes its server's name, its interface, and a unique name within that server and interface. Bank
object given a name for it, we could assign a meaningful marker name to each Bank
object, and then allow clients to specify one of these marker names when calling the Bank._bind()
method. Chapter 7, "Publishing Object References in Servers" shows how to do this.
The best way for a client to obtain an object reference for a particular
Account
object is probably for the Bank
to provide an IDL operation that takes the Account
holder's name or the Account
's number as a parameter and returns an Account
object reference.6.6 Registration and Activation
The last step in developing and installing our bank application is to register the BankSrv
server. putit
command, which takes the following simplified form:
putit [putit switches] -java serverName
<
class name> <class path>
[command-line-args-for-server]
For example, our BankSrv
server might be registered as follows:
putit BankSrv -java idl_demo.BankServer /usr/users/classes:/joe/banker/classesThe class
idl_demo.BankServer
will then be registered as the implementation code of the server called BankSrv
at the current host. The putit
command does not cause the indicated server class to be interpreted: the Java interpreter can be explicitly invoked on the class, or the OrbixWeb daemon will cause the class to be interpreted in response to an incoming operation invocation.Further information on the
putit
command is given in Chapter 11, "Registration and Activation of Servers".
6.7 Execution Trace
Let us now consider the events that occur as our BankSrv
server and our client are run. The TIE approach will be used to show the initial trace, and then the BOAImpl approach will be discussed.BankSrv
" is registered in the Implementation Repository. orbixd
will launch the server by invoking the java interpreter on the specified class. The server application creates a new TIE object (of type _tie_Bank
) for an object of class BankImplementation
, and waits on _CORBA.Orbix.impl_is_ready()
:
// Java // In file BankServer.java. ... public class BankServer { public static void main (String args[]){ BankImplementation bankImpl = new BankImplementation (); _BankRef bankRef; try { bankRef = new _tie_Bank (bankImpl); } catch (SystemException se) { // Details omitted. } try { // Wait for incoming requests. _CORBA.Orbix.impl_is_ready ("BankSrv"); } ... } };The state of the server, at the time of the
impl_is_ready()
call, is shown in Figure 6.3. The server is now waiting for incoming requests. If impl_is_ready()
times out, the server will terminate.
![]() |
Now let us consider the client: it first binds to any
Bank
object, using _bind()
, for example:
// Java // In file Client.java. package idl_demo; ... public class Client { public static void main (String args[]) { _BankRef bRef = null; ... try { // Bind to any Bank object // in BankSrv server. bRef = Bank._bind (":BankSrv"); } catch (SystemException se) { // Details omitted. } ... } }No object name (marker) is specified, so OrbixWeb will choose any
Bank
object within the chosen server (BankSrv
). When the Bank._bind()
call is made, the OrbixWeb daemon will launch an appropriate process by invoking the Java interpreter on the BankServer
class (if a process is not already running).We will assume that the
Bank._bind()
call will bind to our newly created _tie_Bank
object. The result of the binding is an automatically generated proxy object in the client, which acts as a "stand-in" for the remote BankImplementation
object in the server. The object reference bRef
within the client is now a remote object reference as shown in Figure 6.4.
![]() |
The client programmer will not be aware of the TIE object (nevertheless, all remote operation invocations on our
BankImplementation
object will go via the TIE).
// Java // In file Client.java. // In class Client. ... try { // Obtain a new bank account. aRef = bRef.newAccount ("Joe"); // Invoke operations on Account. aRef.makeDeposit ((float)56.90); f = aRef.balance(); System.out.println ("Current balance is " + f); } catch (SystemException se) { // Details omitted. } ...When the
bRef.newAccount()
call is made, the method BankImplementation.newAccount()
is called (via the TIE) within the bank server. This generates a new AccountImplementation
object and associated TIE object. The TIE object is added to the BankImplementation
object's list of existing Account
s. Finally, newAccount()
returns the Account
reference back to the client. At the client side, a new proxy will be created for the
Account
object, and this will be referenced by the aRef
variable; see Figure 6.5.
![]() |
Using the BOAImpl approach, the final diagram would be as shown in Figure 6.6.
![]() |
6.8 Comparison of the TIE and BOAImpl Approaches
As can be seen from the example outlined in this chapter, the TIE and BOAImpl approaches to interface implementation impose similar overheads on the implementation programmer. However, there are two significant differences which may affect the programmer's choice of implementation strategy:
The creation of a TIE object for each implementation object may be a significant decision factor in applications where a large number of implementation objects are likely to be created and tight restrictions on the usage of virtual memory exist. In addition, the delegation of client invocations by TIE objects implicitly involves an additional Java method invocation for each incoming request.
Of course, it is not necessary to choose one approach exclusively, as both can be freely mixed within the same server.
In section 6.8.1 and section 6.8.2 we will examine two important aspects IDL interface implementation: the ability to provide different implementations of the same interface, and the ability to implement different interfaces with a single implementation class.
6.8.1 Providing Different Implementations of the Same Interface
Both BOAImpl and TIE approaches allow a programmer to provide a number of different implementations of the same IDL interface, that is, to provide more than one implementation class for a given IDL interface. This is an important feature, especially in a large heterogeneous distributed system. An object can then be created as an instance of any one of the implementation classes; and client programmers need not be aware of which one is chosen.6.8.2 Providing Different Interfaces to the Same Implementation
Using the TIE approach, it is possible to have a Java implementation class which implements more than one IDL interface. This class must implement the generated Java Operations
interfaces for all of the IDL interfaces it supports, and must therefore implement all of the operations defined in those IDL interfaces. This common class is simply instantiated and passed to the constructor of any TIE objects created for a supported IDL interface.6.9 An Example of Using Holder Classes
Recall the definition of operation newAccount()
(from interface Bank
) in the IDL definition for the banking application:
// IDL Account newAccount(in string name);In order to illustrate the use of
Holder
types, we will modify this definition as follows:
// IDL void newAccount (in string name, out Account acc);The IDL compiler maps this operation to a method of Java interface
_BankRef
as follows:
// Java // In package idl_demo.Bank, // in class Ref. public void newAccount(String name, idl_demo._AccountHolder acc) throws IE.Iona.Orbix2.CORBA.SystemException;The
out
parameter of type Account
maps to an OrbixWeb Holder
class, idl_demo._AccountHolder
, which is generated by the IDL compiler. The source code for this class appears as follows:
// Java // In file Holder.java. package idl_demo.Account; public class Holder { public idl_demo._AccountRef value; public Holder() {} public Holder(idl_demo._AccountRef value) { ... } }This
Holder
class simply stores a value
member variable of type Account
, which may be modified during the operation invocation. Our client application could now be coded as follows:
// Java // In file Client.java. package idl_demo; import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.SystemException; public class Client { public static void main (String args[]) { _BankRef bRef = null; _AccountRef aRef = null; _AccountHolder aHolder = new _AccountHolder (); float f = (float) 0.0; try { // Bind to any Bank object // in BankSrv server. bRef = Bank._bind (":BankSrv"); // Obtain a new bank account. bRef.newAccount ("Joe", aHolder); } catch (SystemException se) { System.out.println ( "Unexpected exception on bind"); System.out.println (se.toString ()); } // Retrieve value from Holder object. aRef = aHolder.value; try { // Invoke operations on Account. aRef.makeDeposit ((float)56.90); f = aRef.get_balance(); System.out.println ("Current balance is " + f); } catch (SystemException se) { System.out.println ( "Unexpected exception" + " on makeDeposit or balance"); System.out.println (se.toString ()); } }In the server, the implementation of method
newAccount()
will receive the Holder
object for type Account
and may manipulate the value field as required. For example, in this case the newAccount()
method might simply instantiate a new Account
implementation object as follows:
// Java // In class BankImplementation. public void newAccount (String name,idl_demo._AccountHolder acc) { AccountImplementation accImpl = new AccountImplementation (0, name); acc.value = new _tie_Account (accImpl); ... }In general,
Holder
classes are required for inout
or out
parameters where the Java parameter type cannot be passed by reference or where the Java parameter value may change type during the operation invocation. In our example, the out
parameter is of type Account
, so the out
parameter value could (conceptually) change type if the type of the object is a derived type of Account
.Note that if the
Account
parameter were labelled inout
in the IDL definition, the value
member of the Holder
class would need to be instantiated before calling the newAccount()
operation.For more information on
Holder
types, see section 5.21.1 "Holder Classes" in Chapter 5, "IDL to Java Mapping".
setNoHangup()
, defined in class BOA
.