module
maps to a Java package
of the same name.
interface
maps to a Java interface named _<type>Ref
where <type>
is the IDL interface name. A Java class is also generated, with the same name as the IDL interface, which implements CORBA client functionality for the interface.
interface
maps to two additional Java classes: an abstract Java class which supports the BOAImpl
approach to implementing IDL interfaces and a fully implemented Java class which supports the TIE
approach.
Ellipses (...) are used in examples to stand for declarations and code which are not relevant to the current discussion.
_
' as follows:
_<keyword>
(for example, new
would map to _new
). An IDL identifier cannot begin with an underscore.
Bank
is defined inside the module IDLDemo
, then the Java Ref
interface for Bank
is scoped as IDLDemo._BankRef
.Similarly, anything defined inside an interface is scoped first by the module name (if any), and then by a package named
_<type>
, where <type>
is the interface name. Therefore, if Bank
in the above example defines a structure called Details
, then the corresponding class is scoped as IDLDemo._Bank.Details
.Anything that is not defined inside either a module or an interface goes into the default (global) package. The only exception to this is the case of globally defined constants, which are discussed in section 5.10. This mapping creates the potential for name collisions with other globally defined Java types, so it is advisable to avoid the generation of global Java definitions whenever possible.
To help alleviate this problem, the
-jP
option was added to the IDL compiler. The -jP
option specifies a package prefix that is added to generated types. This makes it possible to use globally defined IDL types within a package scope. 5.4 The CORBA Module
The objects and data types pre-defined in CORBA are logically defined within an IDL module called CORBA
. Therefore, in IDL the type Object
, for example, is scoped as CORBA::Object
. OrbixWeb maps the CORBA module to Java in order to provide a corresponding scoping for Java types.CORBA
module is defined within the package IE.Iona.Orbix2
. Within this scope, the CORBA
module is defined in two sections:
_CORBA
class, in which CORBA constants defined at the highest level of scope within the CORBA
module are implemented.
CORBA
package, which implements the CORBA
namespace for all other subcomponents of the module.
CORBA
namespace are referenced within the IE.Iona.Orbix2._CORBA
scope; all other elements of the CORBA
module are referenced within the IE.Iona.Orbix2.CORBA
scope.For full details of the contents of the
IE.Iona.Orbix2
package, see Part II, "Class and Interface Reference" of the OrbixWeb Reference Guide.
5.5 Mapping for Basic Data Types
The IDL basic data types have the mappings shown in Table 5.1.
IDL
|
JAVA
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
any | IE.Iona.Orbix2.CORBA.Any |
Java does not support unsigned data types, therefore all
unsigned
IDL types are simply mapped to signed Java types. Note that the IDL unsigned
short
type maps to Java int
, in order to avoid value wrapping. Consequently, when transmitting unsigned
short
values, it is the responsibility of the application programmer not to transmit Java int
values greater than the upper limit on the IDL unsigned
short
type (216-1
).int
is a 32 bit quantity whereas a long
is a 64 bit quantity. Therefore the IDL long
type, which is specified as a 32 bit integer, is mapped to the Java int
type, rather than the Java long
type.char
type to the Java char
type requires special consideration. IDL char
s come from the ISO 8859.1 character set, having at most 255 different values. Java char
s come from the UNICODE character set, having at most 65536 different values. Therefore, IDL char
s can only represent a small subset of Java char
s.char
s which are outside the range of IDL char
s. However, when a Java char
is passed as a parameter to an IDL operation, only the low order 8 bits are preserved during transmission.any
is described in full in Chapter 18, "Type any".
5.6 Mapping for Interfaces
OrbixWeb maps IDL interfaces to a set of Java types which support client development and a set of types which support server implementation. We will examine each of these mappings in turn.5.6.1 Client Mapping
IDL supports multiple inheritance of interfaces. Java also supports multiple inheritance of interfaces, but does not support multiple inheritance of classes. For this reason, IDL interfaces are mapped to Java interfaces, from the point of view of client applications.
// IDL interface Account { readonly attribute float balance; void makeDeposit(in float sum); void makeWithdrawal(in float sum, out float newBalance); };This produces the following Java interface definition:
// Java // Automatically generated // in file _AccountRef.java. public interface _AccountRef extends IE.Iona.Orbix2.CORBA._ObjectRef {and the following Java class definition:// For now, we omit the mapping for
// attributes and operations.
};
// Java // Automatically generated // in file Account.java. public class Account extends IE.Iona.Orbix2.CORBA.BaseObject implements _AccountRef {The Java interface derives from interface// This class includes implementations
// of the methods defined in _AccountRef, // plus some additional proxy methods.};
IE.Iona.Orbix2.CORBA._ObjectRef
which defines the developer's view of functionality common to all OrbixWeb objects; the Java class derives from class IE.Iona.Orbix2.CORBA.BaseObject
, which implements the _ObjectRef
interface.The generated class also has static class methods for
_narrow()
and _bind()
. The _narrow()
method takes an _ObjectRef
type as an argument, and returns an object reference of the same type as the class. The _bind()
method may be used to create a proxy for an object which implements the IDL interface.A client wishing to use the IDL interface should bind an object of the Java class type to the target implementation object in the server, assigning the result to the Java interface type. For example, a client could bind to an
Account
implementation object by calling the _bind()
static method on the Java Account
class as follows:
// Java _AccountRef aRef; aRef = Account._bind ();This returns a proxy object which can be accessed via the methods defined in the
_AccountRef
interface.The IDL compiler also generates a
Holder
class for each IDL interface type, within a package (where the package name is that of the IDL interface). For example, the above IDL definition results in the generation of the following Holder
class:
// Java // Automatically generated // in file _AccountHolder.java. public class _AccountHolder { public _AccountRef value; public _AccountHolder() {} public _AccountHolder(_AccountRef value) { this.value = value; } }This Java class is required for passing the IDL interface type as an
inout
or out
parameter to IDL operations. section 5.21 provides full details of the mapping for operation parameter values.
5.6.2 Server Implementation Mapping
OrbixWeb supports two approaches to the implementation of IDL interfaces in Java applications: the BOAImpl approach and the TIE approach. In this section we will discuss the Java types generated to enable each implementation method.
_<IDL interface name>OperationsFor example, given the IDL definition of type
Account
, the IDL compiler generates the Java interface _AccountOperations
as follows:
// Java // Automatically generated // in file _AccountOperations.java. public interface _AccountOperations { public float get_balance () throws IE.Iona.Orbix2.CORBA.SystemException; public void makeDeposit (float sum) throws IE.Iona.Orbix2.CORBA.SystemException; public void makeWithdrawal (float sum, IE.Iona.Orbix2.CORBA.FloatHolder newBalance) throws IE.Iona.Orbix2.CORBA.SystemException; }The relationship of this Java interface to a programmer's implementation class is dependent on the implementation approach.
_boaimpl_
. For example, the compiler generates class _boaimpl_Account
from the definition of interface Account
.The generated BOAImpl-class implements the IDL generated
Operations
interface. The implementation methods defined by this interface are redefined as abstract methods of the BOAImpl-class. To implement an IDL interface using the BOAImpl approach, the programmer must create a Java class which extends the corresponding BOAImpl-class and implements the abstract methods.For example, given the IDL definition for interface
Account
, the compiler generates the abstract class _boaimpl_Account
as follows:
// Java // Automatically generated // in file _boaimpl_Account.java. public abstract class _boaimpl_Account extends Account implements _AccountOperations { public _boaimpl_Account() throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } public _boaimpl_Account(String markerName) throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } public abstract float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException; public abstract void makeDeposit(float sum) throws IE.Iona.Orbix2.CORBA.SystemException; public abstract void makeWithdrawal(float sum, IE.Iona.Orbix2.CORBA.FloatHolder newBalance) throws IE.Iona.Orbix2.CORBA.SystemException; ... }A sample class which implements the IDL interface
Account
could be outlined as follows:
// Java // In file AccountImplementation.java. ... class AccountImplementation extends _boaimpl_Account { AccountImplementation () throws IE.Iona.Orbix2.CORBA.SystemException { } public float balance() throws IE.Iona.Orbix2.CORBA.SystemException { // Implementation details omitted. } public void makeDeposit(float sum) throws IE.Iona.Orbix2.CORBA.SystemException { // Implementation details omitted. } public void makeWithdrawal(float sum, IE.Iona.Orbix2.CORBA.FloatHolder newBalance) throws IE.Iona.Orbix2.CORBA.SystemException { // Implementation details omitted. } }Note that the BOAImpl-class constructor can throw OrbixWeb system exceptions, so the implementation class constructor must include a Java
throws
clause for such exceptions.Once the IDL interface has been implemented using the BOAImpl approach, the server application should simply instantiate one or more objects of the implementation class. These objects will then be capable of handling client requests through the IDL interface in question.
_tie_
. For example, the compiler generates class _tie_Account
from the definition of interface Account
:
// Java // Automatically generated // in file _tie_Account.java. ... public class _tie_Account extends Account { private _AccountOperations m_impl; public _tie_Account (_AccountOperations impl) throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } public _tie_Account (_AccountOperations impl, String markerName) throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } public float get_balance () throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } public void makeDeposit (float sum) throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } public void makeWithdrawal(float sum, IE.Iona.Orbix2.CORBA.FloatHolder newBalance) throws IE.Iona.Orbix2.CORBA.SystemException { // Details omitted. } ... }The TIE-class does not implement the Java
Operations
interface generated by the IDL compiler. When implementing an IDL interface using the TIE method, the programmer's Java implementation class must directly implement the Operations
interface. However, the implementation class is not required to inherit from any other Java class.For example, the class
AccountImplementation
could be outlined using the TIE approach as follows:
// Java // In file AccountImplementation.java ... class AccountImplementation implements _AccountOperations { AccountImplementation () { } public float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException { // Implementation details omitted. } public void makeDeposit(float sum) throws IE.Iona.Orbix2.CORBA.SystemException { // Implementation details omitted. } public void makeWithdrawal(float sum, IE.Iona.Orbix2.CORBA.FloatHolder newBalance) throws IE.Iona.Orbix2.CORBA.SystemException { // Implementation details omitted. } }When the programmer has created an implementation class which implements the required
Operations
interface, the server application should instantiate one or more objects of this type. For each implementation object, the server should also instantiate an object of the corresponding TIE-class, passing the implementation object as a parameter to the TIE constructor. Each TIE object stores a reference to a single implementation object. Client operation invocations through the IDL interface are routed to the appropriate TIE object which then delegates the call to the appropriate method in its implementation object.
The mapping for each read-write attribute produces two methods: one to get the attribute's value and the other to set it. The name of the get method is formed by appending the string
get_
with the attribute name; the set method by appending the string set_
with the attribute name. A readonly
attribute is mapped to a single method, which gets the value.Consider the following IDL interface:
// IDL interface Account { readonly attribute float balance; attribute long accountNumber; void makeDeposit(in float sum); };The following code illustrates the mapping:
// Java // Automatically generated // in file _AccountRef.java. public interface _AccountRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException; public int get_accountNumber() throws IE.Iona.Orbix2.CORBA.SystemException; public void set_accountNumber(int value) throws IE.Iona.Orbix2.CORBA.SystemException; public void makeDeposit(float sum) throws IE.Iona.Orbix2.CORBA.SystemException; }Operation return values and
in
parameters following the general mapping rules for the appropriate IDL type. However, as Java does not support the passing of method parameters by reference, inout
and out
parameter passing modes often require a more complex mapping.To return simple types by reference, a Java class instance must be passed instead of the primitive type itself. OrbixWeb provides
Holder
classes for the following Java basic types: short
, int
, char
, boolean
, byte
, double
and float
. These Holder
classes are defined in the IE.Iona.Orbix2.CORBA package and are named ShortHolder
, IntHolder
, CharHolder
, and so on.For example, if we add the following operation to the interface
Account
:
void makeWithdrawal(in float sum, out float newBalance);the following code would be generated for this operation:
public void makeWithdrawal(float sum, IE.Iona.Orbix2.CORBA.FloatHolder newBalance) throws IE.Iona.Orbix2.CORBA.SystemException;where the class
FloatHolder
is defined as follows:
// Java // Automatically generated // in file FloatHolder.java. package IE.Iona.Orbix2.CORBA; public class FloatHolder implements IE.Iona.Orbix2.CORBA.IDLCloneable { public float value; FloatHolder () { } FloatHolder (float value) { this.value = value; } public Object clone () { ... } public boolean equals (java.lang.Object _obj) { ... } }
Holder
classes are also required when passing String
s or object references as inout
or out
parameters. The mapping for operation parameters is described in full in section 5.21.
The mapping to Java for
oneway
operations is the same as it is for normal operations; however, the IDL compiler will ensure that these operations do not have any inout
or out
parameters, that they have a void
return type and that they do not raise user-defined exceptions (oneway
operations may however raise system exceptions). This is in accordance with the restrictions on oneway
operations prescribed in the CORBA specification.raises
clause on an operation maps directly to a throws
clause on the equivalent Java method. The mapping for user defined exceptions is described in section 5.18.
The mapping for IDL context
clauses is described in section 5.19.
5.8 Object References
When an interface type is used in IDL, this denotes an object reference. For example, consider the IDL operation newAccount()
, defined as follows:
// IDL interface Account; interface Bank { Account newAccount(in string name); };The return type of
newAccount()
is an object reference. An object reference maps to an interface named _<type>Ref
, where <type>
is the name of the IDL interface type. The Ref
interface allows IDL operations to be invoked on the object reference with normal Java method invocation syntax. For example, the newAccount()
operation could be invoked as follows:
// Java ... _BankRef bRef; _AccountRef aRef; ... bRef = Bank._bind (); aRef = bRef.newAccount ("Chris"); aRef.makeDeposit ((float) 10.0); ...The server implementation of operation
newAccount()
will create an Account
implementation object, store a reference to this object, and return the object reference to the client. For example, using the BOAImpl approach and an implementation class named AccountImplementation
, this could be done as follows:
// Java // In file BankImplementation.java. ... public class BankImplementation extends _boaimpl_Bank { protected _AccountRef m_accObjRef; ... public BankImplementation () throws IE.Iona.Orbix2.CORBA.SystemException { m_accObjRef = null; ... } public _AccountRef newAccount (String name) throws IE.Iona.Orbix2.CORBA.SystemException { _AccountRef aRef; try { aRef = new AccountImplementation (0, name); } ... m_accObjRef = aRef; return aRef; } ... }Similarly, the TIE approach could be used as follows:
// Java // In file BankImplementation.java. ... public class BankImplementation implements _BankOperations { protected _AccountRef m_accObjRef; ... public BankImplementation () { m_accObjRef = null; ... } publiic _AccountRef newAccount (String name) throws IE.Iona.Orbix2.CORBA.SystemException { _AccountRef aRef = new _tie_Account (new AccountImplementation (0, name)); m_accObjRef = aRef; return aRef; } ... }If the operation
newAccount()
returned the Account
object reference as an inout
or out
parameter value, then the generated class _AccountHolder
would need to be passed to the newAccount()
Java method. _AccountHolder
is a class which can contain an _AccountRef
object reference value. The use of Holder
classes is documented in full in section 5.21.1.
5.9 Inheritance
This section describes the mapping for interfaces that inherit from other interfaces. Additional details of this mapping are provided in Chapter 13, "Inheritance".
IDL interfaces support both single and multiple inheritance. On the client side, the OrbixWeb IDL compiler maps IDL interfaces to Java interfaces, which also support single and multiple inheritance, and generates Java classes which implement proxy functionality for these interfaces. Inherited interfaces in IDL are mapped to extended interfaces in Java; the inheritance hierarchy of the Java interfaces matches that of the original IDL interfaces.
// IDL interface Account { readonly attribute float balance; attribute long accountNumber; void makeDeposit(in float sum); }; interface CheckingAccount : Account { void setOverdraftLimit(in float limit); };The corresponding Java interface for type
CheckingAccount
is:
// Java // Automatically generated // in file _CheckingAccountRef.java. public interface _CheckingAccountRef extends _AccountRef, IE.Iona.Orbix2.CORBA._ObjectRef { public void setOverdraftLimit(float limit) throws IE.Iona.Orbix2.CORBA.SystemException; }The corresponding Java class implements all methods for both
Account
and CheckingAccount
. The generated class looks like this:
// Java // Automatically generated // in file CheckingAccount.java. import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.CompletionStatus; public class CheckingAccount extends IE.Iona.Orbix2.CORBA.BaseObject implements _CheckingAccountRef { public void setOverdraftLimit(float limit) throws IE.Iona.Orbix2.CORBA.SystemException { ... } public float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException { ... } public int get_accountNumber() throws IE.Iona.Orbix2.CORBA.SystemException { ... } public void set_accountNumber(int value) throws IE.Iona.Orbix2.CORBA.SystemException { ... }; public void makeDeposit(float sum) throws IE.Iona.Orbix2.CORBA.SystemException { ... } ... }As expected, code written in Java to use the
CheckingAccount
interface can call the inherited makeDeposit()
function:
// Java _CheckingAccountRef checkingAc; // Code for binding checkingAc: (omitted here) ... checkingAc.makeDeposit(90.97);Naturally, assignments from a derived to a base class object reference are allowed, for example:
// Java _AccountRef ac = checkingAc;Normal or cast assignments in the opposite directionfrom a base class object reference to a derived class object referenceare not generally allowed. The
_narrow()
method can be used to bypass this restriction where it is safe to do so, as described in section 5.9.1.
On the server side, the IDL compiler generates a Java
Operations
interface for each IDL interface. The generated Java interface defines the minimum set of implementation methods required for the IDL interface. The inheritance hierarchy of generated Operations
interfaces matches that of the original IDL interfaces.Operations
interface for its corresponding IDL type and redefines each of the interface methods as abstract methodsincluding all methods defined in interfaces from which the Operations
interface inherits.Account
and CheckingAccount
, a CheckingAccount
implementation class will appear as follows:
// Java // In file CheckingAccountImplementation.java. ... public class CheckingAccountImplementation extends _boaimpl_CheckingAccount { public CheckingAccountImplementation () throws IE.Iona.Orbix2.CORBA.SystemException { } public float get_balance() throws IE.Iona.Orbix2.CORBA.SystemException { ... } public int get_accountNumber() throws IE.Iona.Orbix2.CORBA.SystemException { ... } public void set_accountNumber(int value) throws IE.Iona.Orbix2.CORBA.SystemException { ... }; public void makeDeposit(float sum) throws IE.Iona.Orbix2.CORBA.SystemException { ... } public void setOverdraftLimit (float limit) throws IE.Iona.Orbix2.CORBA.SystemException { ... } }Using the TIE approach, the implementation class should implement the generated
Operations
interface for the relevant IDL type. The implementation class must implement each method defined in the Operations
interface and all interfaces from which it inherits. However, this may be achieved using an inheritance hierarchy of implementation classes, as the TIE approach, unlike the BOAImpl approach, imposes no implicit inheritance requirements on such classes.For example, if the IDL type
Account
is implemented by class AccountImplementation
, using the TIE approach, then IDL interface CheckingAccount
might be implemented by type CheckingAccountImplementation
as follows:
// Java // In file CheckingAccountImplementation.java. ... public class CheckingAccountImplementation extends AccountImplementation, implements _CheckingAccountOperations { public CheckingAccountImplementation () { } public void setOverdraftLimit (float limit) throws IE.Iona.Orbix2.CORBA.SystemException { ... } }
CheckingAccount
example above, if the programmer knows that a reference of type _AccountRef
actually references an object which implements interface CheckingAccount
, then it is legal to narrow the object reference to a CheckingAccount
reference. To narrow an object reference, the _narrow()
method (which is defined as a static
method in each IDL generated Java class) should be used:
// Java // Automatically generated // in file CheckingAccount.java. public class CheckingAccount extends IE.Iona.Orbix2.CORBA.BaseObject implements _CheckingAccountRef { ... public static final _CheckingAccountRef _narrow(IE.Iona.Orbix2.CORBA._ObjectRef src) throws IE.Iona.Orbix2.CORBA.SystemException { ... } ... }It can be called as follows:
// Java _AccountRef aRef; // Here, aRef is set to reference a // CheckingAccount (code omitted). _CheckingAccountRef caRef; // Narrow aRef to be a CheckingAccount. caRef = CheckingAccount._narrow(aRef);If the parameter passed to
T._narrow()
is not of class T
or one of its derived classes, T._narrow()
raises the IE.Iona.Orbix2.CORBA.BAD_PARAM
exception and returns null
.
For a global, file level IDL constant such as:
// IDL // in file constdef.idl. const short MaxLen = 4;OrbixWeb generates a Java class in which an equivalent Java constant is defined. The class name is generated using the following convention:
_<idl file prefix>IDL
The constant is then mapped to a public static final
member of this class. For example, MaxLen
in the above IDL definition maps to:
// Java // in file _constdefIDL.java. public class _constdefIDL { public static final short MaxLen = 4; }A Java class is also generated when an IDL constant is defined within a module. In this case, the class name is generated using the convention:
_<module name>
The constant is then mapped to a public static final
member of this class. Consider the following example:
// IDL module ConstDef { const short MaxLen = 4; };This maps to:
// Java // Automatically generated // in file _ConstDef.java. public class _ConstDef { public static final short MaxLen = 4; }An IDL constant defined in an interface simply maps to a
public static final
member of the generated Java class for the IDL interface. For example, the following IDL:
// IDL interface ConstDefIntf { const short MaxLen = 4; };maps to the following Java class:
// Java // Automatically generated // in file ConstDefIntf.java. ... public class ConstDefIntf extends IE.Iona.Orbix2.CORBA.BaseObject implements _ConstDefIntfRef { public static final short MaxLen = 4; ... }Programmers can then access the constant by scoping with the Java class name, for example:
// Java short len = ConstDefIntf.MaxLen;
enum
maps to a Java class containing static class variables for each element in the enumeration. These variables are initialised to sequential values, starting at zero.Individual enumeration values map to Java type
int
. Therefore, to use an IDL enum
in Java, a developer could declare an int
and initialise it using one of the values from the generated enumeration class. Legal values for an enum
operation parameter are enforced when an operation is invoked.Consider the following IDL definition:
// IDL enum Colour { blue, green };This maps to:
// Java // Automatically generated // in file Colour.java. public class Colour { public static final int blue = 0; public static final int green = 1; }
String
. As Java String
s are fundamentally unbounded, OrbixWeb checks the range of String
parameter values passed as bounded strings to IDL operations. If the actual string length is greater than the bound value, then the string is truncated during marshalling to the maximum allowable length. This truncation has no effect on the sender's copy of the string.IDL string parameters defined as
inout
or out
map to Java method parameters of type StringHolder
. This Holder
class contains a Java String
value, which can be updated during the operation invocation:
// Java package IE.Iona.Orbix2.CORBA; public class StringHolder implements IE.Iona.Orbix2.CORBA.IDLCloneable { public String value; StringHolder () { } StringHolder (String value) { this.value = value; } public Object clone () { ... } public boolean equals (java.lang.Object _obj) { ... } }Consider the following IDL definition:
// IDL interface Customer { void setCustomerName (in string name); void getCustomerName (out string name); };This maps to the following Java interface:
// Java // Automatically generated // in file _CustomerRef.java. public interface _CustomerRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public void setCustomerName(String name) throws IE.Iona.Orbix2.CORBA.SystemException; public void getCustomerName( IE.Iona.Orbix2.CORBA.StringHolder name) throws IE.Iona.Orbix2.CORBA.SystemException; }A client application could invoke the IDL operations as follows:
// Java _CustomerRef cRef; String inName = "Chris"; String outName; StringHolder outNameHolder; // Here, cRef is set to reference a // Customer (code omitted). cRef.setCustomerName (inName); cRef.getCustomerName (outNameHolder); outName = outNameHolder.value;The server programmer receives the
StringHolder
variable as a parameter to the implementation method and simply assigns the required string to the value
field.OrbixWeb programmers who wish to use IDL
string
s should be aware of the difference between IDL char
s and Java char
s as outlined in section 5.5.
5.13 Mapping for Typedefs
Java has no language construct that is equivalent to the IDL typedef
statement. However, the same effect as typedef
can be achieved by declaring a new Java type as a subclass of the original type. Of course, this works only if the original type can be subclassed.typedef
s for simple types do not map directly to Java. Instead, the original type is substituted for the new type everywhere the new type is encountered. In this particular case, IDL string
counts as a simple type (since the Java type String
is a final
class), while IDL any
does not.typedef
for a complex type generates a class that extends the class of the original type. It contains no methods or variables of its own.typedef
on an IDL interface:
// IDL struct CustomerDetails { string Name; string Address; }; typedef CustomerDetails BankCustomer;The
CustomerDetails
structure maps to a Java class as described in section 5.14. The typedef
statement results in an additional Java class as follows:
// Java // Automatically generated // in file BankCustomer.java. import CustomerDetails; public class BankCustomer extends CustomerDetails { public BankCustomer () { super(); } public BankCustomer (String name, String address) { super(name, address); } }
struct
maps to a Java class containing one instance variable for each field in the structure. There are two constructors for each structure class: the first takes no arguments and initialises all fields in the structure to null or zero; the other takes the fields in the structure as arguments, and initialises the structure.All IDL parameters (
in
, out
and inout
) and return values of a given struct
type map to the Java class for that structure.For example, the structure
Time
in the following example:
// IDL interface Clock { struct Time { short hour; short minute; short second; }; void updateTime (in Time current); void currentTime (out Time current); };maps to:
// Java // Automatically generated // in file Clock/Time.java. package Clock; import IE.Iona.Orbix2._CORBA; public class Time implements IE.Iona.Orbix2.CORBA.IDLCloneable, IE.Iona.Orbix2.CORBA.Marshalable { public short hour; public short minute; public short second; public Time () { } public Time (short hour, short minute, short second) { ... } ... }while the
Time
operation parameters map directly as follows:
// Java // Automatically generated // in file _ClockRef.java. public interface _ClockRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public void updateTime(_Clock.Time current) throws IE.Iona.Orbix2.CORBA.SystemException; public void getCurrentTime(_Clock.Time current) throws IE.Iona.Orbix2.CORBA.SystemException; }
// IDL interface Account; interface CurrentAccount : Account; interface DepositAccount : Account; union AccountType switch (short) { case 1: CurrentAccount curAcc; case 2: DepositAccount depAcc; default: Account genAcc; };IDL discriminated unions map to a Java class. The class provides modifier methods which allow the discriminator and value to be set simultaneously. It also provides accessor methods which allow the discriminator to be queried and the value to be retrieved.
The above IDL definition maps to:
// Java // Automatically generated // in file AccountType.java. import IE.Iona.Orbix2._CORBA; import IE.Iona.Orbix2.CORBA.CompletionStatus; import CurrentAccount; import DepositAccount; import Account; public class AccountType implements IE.Iona.Orbix2.CORBA.IDLCloneable, IE.Iona.Orbix2.CORBA.Marshalable { private short discriminator; private Object value; public AccountType() { } public short discriminator() { return discriminator; } public boolean is_curAcc() { ... } public _CurrentAccountRef curAcc() throws IE.Iona.Orbix2.CORBA.BAD_OPERATION { ... } public void curAcc(_CurrentAccountRef value, short discriminator) throws IE.Iona.Orbix2.CORBA.BAD_PARAM { ... } // Also includes similar methods for // depAcc and genAcc fields (omitted here). }The
discriminator
and value
member variables of the Java class are labelled private
in order to prevent either being modified independently of the other. In order to set the union to a given value, the programmer must invoke one of the three generated set methods: curAcc()
, depAcc()
, or genAcc()
. For example, the following code sample assigns a
DepositAccount
value:
// Java _DepositAccountRef depRef; AccountType accType = new AccountType; ... accType.depAcc (depRef, (short)2);The accessor methods can then be used to retrieve the union value. This is illustrated below:
// Java _CurrentAccountRef curRef; _DepositAccountRef depRef; _AccountRef accRef; AccountType accType; ... switch (accType.discriminator ()) { case 1: curRef = accType.curAcc (); break; case 2: depRef = accType.depAcc (); break; default: accRef = accType.genAcc (); }IDL parameters of a discriminated union type map directly to the corresponding Java class.
The actual length of the Java array used as a parameter should be at least as long as the length specified in the IDL file. If it is shorter, then the values of elements for which space has not been allocated will be undefined. If it is longer, then the extra elements will be ignored.
As a simple example, the following IDL definition:
// IDL typedef short BankCode[3]; interface Branch { attribute string location; attribute BankCode code; };maps to:
// Java // Automatically generated // in file _BranchRef.java. public interface _BranchRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public String get_location() throws IE.Iona.Orbix2.CORBA.SystemException; public void set_location(String value) throws IE.Iona.Orbix2.CORBA.SystemException; public short[] get_code() throws IE.Iona.Orbix2.CORBA.SystemException; public void set_code(short[] value) throws IE.Iona.Orbix2.CORBA.SystemException; }
sequence
maps to a Java class, using the following naming convention for the class:
_sequence_<element type>
This generated class contains two instance variables (buffer
and length
) and an ensureCapacity()
method. If the sequence has been the source of an IDL typedef
statement, the new type defined in the typedef
is mapped to a derived class of the sequence class, as described in section 5.13.
The member variable
buffer
is a Java array of elements which are of the same type as the IDL sequence elements. The default constructor assigns this array to null
. An alternative constructor is provided which allows the programmer to specify a size to which the array is initialised.length
can be assigned by the programmer to indicate the current length of the array stored in buffer
(which may be less than the actual size of the allocated array). If length is set to any value less than zero or greater than the actual size of the buffer
array, then OrbixWeb will assume the length to be equal to the actual size of the array.ensureCapacity()
method takes an int
parameter value, which indicates the minimum array size required by the programmer. If the actual buffer size is less than the required minimum, ensureCapacity()
reallocates the buffer
array appropriately and copies any existing elements into the new array. The new buffer is guaranteed to be at least as long as the requested size, but for efficiency reasons the buffer will often be made larger than the requested size. ensureCapacity()
resizes a buffer array, the length
field is not set. Therefore it is necessary to set the length
field explicitly if that is the desired behaviour.
// IDL struct CustomerDetails { string Name; string Address; }; typedef sequence<CustomerDetails> UnboundedSeq; typedef sequence<CustomerDetails, 5> BoundedSeq;Given this example, the IDL compiler produces a Java class which maps all sequence of
CustomerDetails
declarations (bounded or unbounded):
// Java // Automatically generated // in file _sequence_CustomerDetails.java. import IE.Iona.Orbix2._CORBA; import CustomerDetails; public class _sequence_CustomerDetails implements IE.Iona.Orbix2.CORBA.IDLCloneable, IE.Iona.Orbix2.CORBA.Marshalable { public CustomerDetails buffer[]; public int length; public _sequence_CustomerDetails() { ... } public _sequence_CustomerDetails(int len) { ... } public void ensureCapacity(int min) { ... } ... }Derived classes of this sequence class are generated for the
UnboundedSeq
and BoundedSeq
types in accordance with the IDL to Java mapping for typedef
s, as described in section 5.13.
Bounded IDL sequence types map to Java classes which contain implicitly unbounded array buffers. When a Java sequence class is passed to an operation which takes a bounded sequence as a parameter, OrbixWeb explicitly checks the length of the sequence. If the length is greater than the bound specified in the IDL definition, the transmitted sequence will be truncated to the maximum legal length for that sequence type. However, this truncation does not affect the sender's copy of the sequence.
5.18 Mapping for Exception Types
An IDL exception type is mapped to a Java class that derives from the OrbixWeb class UserException
, which in turn derives from the class CORBAException
(where both these classes are defined in the IE.Iona.Orbix2.CORBA
package). The class CORBAException
derives from java.lang.Exception
, which allows classes for IDL exceptions to be thrown as normal Java exceptions.
// IDL exception Reject { string reason; short s; };is mapped to:
// Java // Automatically generated // in file Reject.java. import IE.Iona.Orbix2._CORBA; public class Reject extends IE.Iona.Orbix2.CORBA.UserException implements IE.Iona.Orbix2.CORBA.IDLCloneable, IE.Iona.Orbix2.CORBA.Marshalable { public String reason; public short s; public Reject() { ... } public Reject(String reason, short s) { ... } ... }This mapping defines a default constructor and a constructor with one parameter for each exception member; this second constructor initialises each exception member to the given value. In this example, this constructor has two parameters, one for each of the fields
reason
and s
defined in the exception. The default constructor performs no explicit member initialisation.Now consider an interface with an operation that can raise a
Reject
IDL exception:
// IDL interface Bank { exception Reject { ... }; Account newAccount () raises (Reject); };An OrbixWeb server can raise a
Bank::Reject
exception by passing the Java type Bank.Reject
to a Java throw()
statement:
// Java // In implementation class for type Bank. ... public _AccountRef newAccount () throws _Bank.Reject, IE.Iona.Orbix2.CORBA.SystemException { ... throw new _Bank.Reject ("Some reason", (short) 0); } ...An OrbixWeb client can test for such an exception when invoking the
newAccount()
operation as follows:
// Java _BankRef bRef; _AccountRef aRef; ... try { aRef = bRef.newAccount (); } catch (_Bank.Reject rejectEx) { system.out.println ("newAccount() failed"); system.out.println ("reason for failure = " + rejectEx.reason); ... }OrbixWeb exception handling is described in detail in Chapter 12, "Exception Handling".
5.19 Context Arguments
An IDL operation can specify that it is to be provided with the client's mapping for particular identifiers (properties): it does this by listing these identifiers following the operation declaration in a context
clause. An IDL operation that specifies a context clause is mapped to a Java method which takes an extra input parameter of type Context
(scoped within package IE.Iona.Orbix2.CORBA
), at the end of the parameter list. For example:
// IDL interface Calculator { long subtract (in long x, in long y) context ("accuracy", "base"); };maps to:
// Java // Automatically generated // in file _CalculatorRef.java. public interface _CalculatorRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public int subtract(int x, int y, IE.Iona.Orbix2.CORBA.Context _c) throws IE.Iona.Orbix2.CORBA.SystemException; }A client can optionally maintain one or more
Context
objects, which provide a mapping from identifiers (string names) to string values. A Context
object contains a list of properties; each property consists of a name and a string value associated with that name and can be passed to a method that takes a Context
parameter.Contexts can be arranged in a hierarchy by specifying parent-child relationships among them. Then, a child passed to an operation also includes the identifiers of its parent(s). The called operation can decide whether to use just the context actually passed, or the hierarchy above it.
The manipulation of
Context
objects is illustrated in full in Chapter 15, "Contexts", while the definition of the API to class Context
can be found in Appendix A, "IDL Reference" in the OrbixWeb Reference Guide.
5.20 Common Mapping for Pseudo Types
As described in Chapter 4, the CORBA standard defines a number of so-called pseudo interfacesthat is, interfaces defined (for convenience) in IDL but whose implementations do not strictly follow the normal mapping for interfaces. An instance of a pseudo interface is termed a pseudo-object. In OrbixWeb, a pseudo-object is a serverless object, which does not inherit from class BaseObject
and is not registered with an OrbixWeb server. OrbixWeb does not create proxies for pseudo-objects.
The following CORBA pseudo interfaces are implemented in OrbixWeb:
NamedValue
, NVList
, Request
, Context
, TypeCode
and ORB
.Ref
types. Also, the mapping to Holder
types for pseudo IDL interfaces does not match that for other IDL interfaces: a Holder
type for a pseudo IDL interface is named <type>Holder
where <type>
is the interface name. The following pseudo types have no equivalent Holder
type: NamedValue
, TypeCode
and ORB
.5.20.1 Creating Pseudo-Objects
For most pseudo object types, the CORBA specification defines an operation to create a pseudo-object. For example, the pseudo interface ORB
defines the operations create_list()
and create_operation_list()
to create an NVList
(an NVList
describes the arguments of an IDL operation).IT_create()
methods in the corresponding Java class. These methods provide an OrbixWeb specific means to create and obtain a pseudo-object reference. An overloaded version of IT_create()
is provided which corresponds to each constructor defined on the class. It is recommended that IT_create()
should be used in preference to Java operator new
but only where there is no (suitable) alternative way to obtain a pseudo-object reference.5.21 Mapping for Parameters and Return Values
When writing OrbixWeb applications, it is necessary to be aware of the IDL to Java mapping for IDL types and the corresponding mapping for parameters and return values of those types. In particular, the mapping for an operation argument may depend on whether it is an in
parameter, an out
parameter, an inout
parameter, or a return value. This section provides a description of the mappings for IDL parameters and return values.in
parameters always map directly to the corresponding Java type. This mapping is possible because these parameters are always passed by value, and Java supports by value passing of all types. Similarly, IDL return values always map directly to the corresponding Java type.inout
and out
parameters need to be passed by reference, as they may be modified during an operation invocation. This poses no problem for the IDL to Java mapping in cases where Java supports by reference parameter passing for the Java type and the actual parameter type is guaranteed not to change during the operation. However, these criteria do not hold for all types generated by the OrbixWeb IDL to Java mapping. In cases where either requirement is not satisfied, OrbixWeb defines an additional Holder
type which facilitates the passing of inout
and out
parameters.struct
, union
, sequence
, any
and array types map to Java classes or arrays and these types never implicitly change (at the parameter type level) during IDL operation invocations. Consequently, inout
and out
parameters for these types follow the direct IDL to Java mapping rules.any
) and the IDL string
type map to Java types which cannot be passed by reference. For this reason, inout
and out
parameters of these types require Holder
classes. inout
and out
object reference parameters also require Holder
classes. This requirement is due to the fact that, although object references map to Java interfaces, the actual type of an object reference parameter may change (to a subtype) during an operation invocation. Holder
classes in detail.5.21.1 Holder Classes
To allow IDL basic types (except type any
), IDL string
s and IDL object reference types to be passed as inout
and out
parameters to IDL operations, OrbixWeb implements Holder
classes for these types.Holder
class as shown in Table 5.2.
JAVA Type
|
HOLDER CLASS
|
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Java package IE.Iona.Orbix2.CORBA; public class IntHolder { public int value; public IntHolder (int _value) { value = _value; }; }The
Holder
class simply stores an int
value as a member variable, which can be initialised by the constructor and accessed directly. The Holder
class is passed by reference to method invocations and so facilitates the modification of an int
, which would not be possible if the int
were passed directly.
Holder
classes for IDL object reference types are generated during compilation of the IDL definition. These classes are required to allow the actual type of an object reference inout
or out
parameter to change (to a subtype) during an operation call. A Holder
class for an IDL interface type is named _<type>Holder
where <type>
is the name of the IDL interface. For example, given an IDL interface Account
, the following Holder
class will be generated:
// Java public class _AccountHolder { public _AccountRef value; public _AccountHolder (_AccountRef _value) { value = _value; }; }In order to invoke an operation which requires a
Holder
class as a parameter, a client programmer simply creates a variable of the Holder
type, passes this variable as an operation parameter, and retrieves the value member variable to obtain the required operation result. For example, the following IDL definition:
// IDL interface Customer { void setCustomerName (in string name); void getCustomerName (out string name); };maps to:
// Java // Automatically generated // in file _CustomerRef.java. public interface _CustomerRef extends IE.Iona.Orbix2.CORBA._ObjectRef { public void setCustomerName(String name) throws IE.Iona.Orbix2.CORBA.SystemException; public void getCustomerName( IE.Iona.Orbix2.CORBA.StringHolder name) throws IE.Iona.Orbix2.CORBA.SystemException; }A programmer who wishes to retrieve a string from the
getCustomerName()
operation should pass a StringHolder
as an operation parameter as follows:
// Java import IE.Iona.Orbix2.CORBA; ... _CustomerRef cRef; StringHolder outStr = new StringHolder (); ... cRef.getCustomerName (outStr); system.out.println ("customer name = " + outStr.value); ...Of course, the retrieved value can be copied or manipulated as required.
A server programmer simply receives the instantiated
Holder
type and manipulates the value
field as required. For example, the implementation of operation getCustomerName()
might return a String
value as follows:
// Java // In implementation class for type Customer. public void getCustomerName (IE.Iona.Orbix2.CORBA.StringHolder name) throws IE.Iona.Orbix2.CORBA.SystemException { name.value = "Chris"; }
5.21.3 Memory Allocation Issues
Java provides automatic garbage collection, which greatly simplifies the memory management issues associated with the OrbixWeb IDL to Java mapping in comparison with, for example, the Orbix IDL to C++ mapping. However, an OrbixWeb programmer should understand where memory needs to be allocated for IDL operation parameters. any
) and the IDL type string
, in parameters and return values are passed by value. inout
and out
parameters of these types are passed as Holder
classes. An instantiation of the Holder
type must be passed to the operation, which may then modify the value
member.struct
s, union
s, sequence
s, array
s, and type any
, in
parameters are passed by reference and not modified. Return values need not be pre-allocated. Return types are automatically allocated and are then given to the caller to manage. out
and inout
parameters require the caller to pre-allocate the value and this is modified in place.in
parameters and return values obey similar rules to IDL struct
in
parameters and return values. However, object reference inout
and out
parameters are passed as Holder
types. An instantiation of the Holder
type must be passed to the operation, which may then modify the value
member.