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 chars come from the ISO 8859.1 character set, having at most 255 different values. Java chars come from the UNICODE character set, having at most 65536 different values. Therefore, IDL chars can only represent a small subset of Java chars.chars which are outside the range of IDL chars. 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 {
// For now, we omit the mapping for
// attributes and operations.
};
and the following Java class definition:
// Java
// Automatically generated
// in file Account.java.
public class Account
extends IE.Iona.Orbix2.CORBA.BaseObject
implements _AccountRef {
// This class includes implementations
// of the methods defined in _AccountRef,
// plus some additional proxy methods.
};
The Java interface derives from interface 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 Strings 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 Strings 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
strings should be aware of the difference between IDL chars and Java chars 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.typedefs 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 typedefs, 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 strings 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.structs, unions, sequences, arrays, 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.