Netscape Internet Service Broker for Java: Reference Guide, Version 1.0

[Contents] [Previous] [Next]

Chapter 2
The IDL to Java Mapping

This chapter describes ISB for Java's IDL-to-Java language mapping as implemented by the idl2java compiler. For each IDL construct there is a section that describes the corresponding Java construct, along with code samples. ISB for Java conforms with the OMG IDL/Java Language Mapping Specification. See the latest version of this specification for complete information, and especially, for information about the following:

This chapter includes the following major sections:

Names

In general, IDL names and identifiers are mapped to Java names and identifiers with no change. If a name collision might be generated in the mapped Java code, the name collision is resolved by prepending an underscore (_) to the mapped name.

In addition, because of the nature of the Java language, a single IDL construct may be mapped to several (differently named) Java constructs. The "additional" names are constructed by appending a descriptive suffix. For example, the IDL interface AccountManager is mapped to the Java interface AccountManager and additional Java classes AccountManagerHelper and AccountManagerHolder.

In those exceptional cases where the "additional" names could conflict with other mapped IDL names, the resolution rule described above is applied to the other mapped IDL names. In other words, the naming and use of required "additional" names takes precedence. For example, interfaces named fooHelper and fooHolder are mapped to _fooHelper and _fooHolder, respectively, regardless of whether an interface named foo exists. The Helper and Holder classes for interface fooHelper are named _fooHelperHelper and _fooHelperHolder.

IDL names that would normally be mapped unchanged to Java identifiers that conflict with Java reserved words will have the collision rule applied.

Reserved Names

The mapping reserves the use of several names for its own purposes. The use of any of these names for a user-defined IDL type or interface (assuming it is also a legal IDL name) will result in the mapped name having an (_) prepended. Reserved names are as follows:

Reserved Words

The use of any of these words for a user-defined IDL type or interface (assuming it is also a legal IDL name) will result in the mapped name having an (_) prepended. The reserved keywords in the Java language are as follows:

abstract

boolean

break

byte

case

catch

char

class

const

continue

default

do

double

else

extends

final

finally

float

for

goto

if

implements

import

instanceof

int

interface

long

native

new

package

private

protected

public

return

short

static

super

switch

synchronized

this

throw

throws

transient

try

void

volatile

while

Modules

The IDL module construct is mapped to a Java package and the package is given the same name as the IDL module. For all IDL types within the module that are mapped to Java classes or Java interfaces, the corresponding Java class or interface is declared inside the Java package that is generated. IDL declarations that are not enclosed in any modules are mapped into the unnamed Java global scope.

The following code example shows the Java code generated for an enumeration declared within an IDL module.

Mapping an IDL module to a Java package

/* IDL code from Example.idl: */
module Example { .... };
};
// Generated Java code:
package Example;
...
}

Global Scope

Any IDL construct declared in the global scope will be placed in a java package which is named IDL_GLOBAL. This name can be changed to a user defined one through the use of compiler options.

All the IDL examples used in this chapter are from the IDL module Example. Therefore, the generated Java declarations will all be placed inside the Java package Example.

Constants

Constants are mapped depending upon the scope in which they appear.

Constants within an Interface

Constants declared within an IDL interface are mapped to public static final fields in the corresponding Java interface.

Mapping an IDL constant within a module to a Java class.

/* IDL code from Example.idl: */
module Example
    interface Foo{
        const long aLongerOne = -321;
    };
};
// Generated Java code:
package Example;
public interface Foo {
    public static final int aLongerOne = (int) (-321L);
}

Constants NOT within an Interface

Constants declared within an IDL module are mapped to a public interface with the same name as the constant and containing a public static final field named value. This field holds the constant's value.

NOTE: The Java compiler normally inlines the value when the class is used in other Java code.
Mapping an IDL constant within a module to a Java class.

/* IDL code from Example.idl: */
module Example {
    const long aLongOne = -123;      
};
// Generated Java code:
package Example;
public interface aLongOne {
    public static final int value = (int) (-123L);
}

Basic Types

The following table shows how the defined IDL types map to basic Java types. When there is a potential mismatch between an IDL type and its mapped Java type, the EXCEPTIONS column lists the standard CORBA exception that can be raised. For the most part, exceptions are in two categories:

NOTE: The Java null may only be used to represent the null object reference. For example, a zero length string, rather than null must be used to represent the empty string. This is also true for arrays.

IDL Type Java Type Exceptions
boolean

boolean

char

char

CORBA::DATA_CONVERSION

wchar

char

octet

byte

string

java.lang.String

CORBA::MARSHAL
CORBA::DATA_CONVERSION

WString

java.lang.String

CORBA::MARSHAL

short

short

unsigned short

short

long

int

unsigned long

int

long long

long

unsigned long long

long

float

float

double

double

Boolean

The IDL type boolean is mapped to the Java type boolean. The IDL constants TRUE and FALSE are mapped to the Java constants true and false.

char and wchar

IDL characters are 8-bit quantities representing elements of a character set, while Java characters are 16-bit unsigned quantities representing Unicode characters. To enforce type safety, the Java CORBA runtime asserts range validity of all Java chars mapped from IDL chars when parameters are marshaled during method invocation. If the char falls outside the range defined by the character set, a CORBA::DATA_CONVERSION exception is thrown. The IDL wchar maps to the Java char type.

Octet

The IDL type octet, an 8-bit quantity, is mapped to the Java type byte.

String

The IDL type string is mapped to the Java type java.lang.String. Range checking for characters in the string as well as bounds checking of the string is done at marshal time.

WString

The IDL type wstring, used to represent Unicode strings, is mapped to the Java type java.lang.String. Bounds checking of the string is done at marshal time.

Integer Types

IDL short and unsigned short map to Java type short. IDL long and unsigned long map to Java's int.

NOTE: Because there is no support in Java for unsigned types, the developer is responsible for ensuring that negative integers in Java are handled correctly as large unsigned values.

Floating Point Types

The IDL floating point types float and double map to a Java class containing the corresponding data type.

Helper Classes

All user-defined IDL types have an additional "helper" Java class with the suffix Helper appended to the type name generated. Several static methods needed to manipulate the type are supplied:

For any user-defined IDL type, <typename>, the following Java code is generated for the type. In addition, both the helper class associated with an IDL interface and the helper class for a mapped IDL interface have a narrow operation defined for them.

// generated Java helper
public class <typename>Helper {
    public static void
        insert(org.omg.CORBA.Any a, <typename> t);
    public static <typename> extract(Any a);
    public static org.omg.CORBA.TypeCode type();
    public static String id();
    public static <typename> read(org.omg.CORBA.portable.InputStream istream)
    { ... };
    public static void write(org.omg.CORBA.portable.OutputStream ostream, <typename> value)
    { ... };
    // only for interface helpers
    public static <typename> narrow(org.omg.CORBA.Object obj);
}
The helper class for a mapped IDL interface has a narrow operation defined for it. The helper class for a mapped IDL enum also has a from_int operation defined for it.

Mapping of a named type to Java helper class

// IDL - named type
struct st {long f1, String f2};
// generated Java
public class stHelper {
    public static void insert(org.omg.CORBA.Any any, st s) {...}
    public static st extract(Any a) {...}
    public static org.omg.CORBA.TypeCode type() {...}
    public static String id() {...}
    public static st read(org.omg.CORBA.InputStream is) {...}
    public static void write(org.omg.CORBA.OutputStream os, st s) {...}
}
Mapping of a typedef sequence to Java helper class 

// IDL - typedef sequence
typedef sequence <long> IntSeq;
// generated Java helper
public class IntSeqHelper {
    public static void insert(org.omg.CORBA.Any any, int[] seq);
    public static int[] extract(Any a){...}
    public static org.omg.CORBA.TypeCode type(){...}
    public static String id(){...}
    public static int[] read(org.omg.CORBA.portable.InputStream is)
        {...}
    public static void write(
                            org.omg.CORBA.portable.OutputStream os,
                            int[] seq)
        {...}
}

Holder Classes

Holder classes support OUT and INOUT parameter passing modes and are available for all the basic IDL data types in the org.omg.CORBA package. Holder classes are generated for all named user-defined types except those defined by typedefs. For more information about Holder classes, see "Generated Classes."

For user-defined IDL types, the holder class name is constructed by appending Holder to the mapped Java name of the type.

For the basic IDL data types, the holder class name is the Java type name (with its first letter capitalized) to which the data type is mapped with an appended Holder, for example IntHolder.

Each holder class has a a default constructor and constructor from an instance, and a public instance member, value, which is the typed value. The default constructor sets the value field to the default value for the type as defined by the Java language:

In order to support portable stubs and skeletons, Holder classes for user-defined types also implement the org.omg.CORBA.portable.Streamable interface.

The holder classes for the basic types are defined below. Note that they do not implement the Streamable interface. They are in the org.omg.CORBA package.

// Java
package org.omg.CORBA;
    final public class ShortHolder {
        public short value;
        public ShortHolder() {}
        public ShortHolder(short initial) {
            value = initial;
        }
    }
    final public class IntHolder {
        public int value;
        public IntHolder() {}
        public IntHolder(int initial) {
            value = initial;
        }
    }
    final public class LongHolder {
        public long value;
        public LongHolder() {}
        public LongHolder(long initial) {
            value = initial;
        }
    }
    final public class ByteHolder {
        public byte value;
        public ByteHolder() {}
        public ByteHolder(byte initial) {
            value = initial;
        }
    }
    final public class FloatHolder {
        public float value;
        public FloatHolder() {}
        public FloatHolder(float initial) {
            value = initial;
        }
    }
    final public class DoubleHolder {
        public double value;
        public DoubleHolder() {}
        public DoubleHolder(double initial) {
            value = initial;
        }
    }
    final public class CharHolder {
        public char value;
        public CharHolder() {}
        public CharHolder(char initial) {
            value = initial;
        }
    }
    final public class BooleanHolder {
        public boolean value;
        public BooleanHolder() {}
        public BooleanHolder(boolean initial) {
            value = initial;
        }
    }
    final public class StringHolder {
        public java.lang.String value;
        public StringHolder() {}
        public StringHolder(java.lang.String initial) {
            value = initial;
        }
    }
    final public class ObjectHolder {
        public org.omg.CORBA.Object value;
        public ObjectHolder() {}
        public ObjectHolder(org.omg.CORBA.Object initial) {
            value = initial;
        }
    }
    final public class AnyHolder {
        public Any value;
        public AnyHolder() {}
        public AnyHolder(Any initial) {
            value = initial;
        }
    }
    final public class TypeCodeHolder {
        public TypeCode value;
        public typeCodeHolder() {}
        public TypeCodeHolder(TypeCode initial) {
            value = initial;
        }
    }
    final public class PrincipalHolder {
        public Principal value;
        public PrincipalHolder() {}
        public PrincipalHolder(TypeCode initial) {
            value = initial;
        }
    }
}
The Holder class for a user defined type <foo> is shown below:

// Java
final public class <foo>Holder 
    implements org.omg.CORBA.portable.Streamable {
    public <foo> value;
    public <foo>Holder() {}
    public <foo>Holder(<foo> initial) {}
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
    }

Constructed Types

IDL constructed types include enum, struct, union, sequence and array. The types sequence and array are both mapped to the Java array type. The IDL constructed types enum, struct, and union are mapped to a Java class that implements the semantics of the IDL type. The Java class generated will have the same name as the original IDL type.

Enum

An IDL enum is mapped to a Java final class bearing the same name as the enum type. The final class declares a value method and two static data members per label, an integer conversion method, and a private constructor. An example follows:

An IDL enum mapped to a Java final class.

// Generated java
public final class <enum_name> {
    //tech pair for each label in the enum
    public static final int _<label> = <value>;
    public static final <enum_name> <label> =
        new <enum_name>(_<label>);
    public int value() {...}
    // get enum with specified value
    public static <enum_name> from_int (int value);
    //constructor
    private <enum_name>(int) {...}
}
One of the members is a public static final that has the same name as the IDL enum label. The other has an underscore(_) prepended and is intended to be used in switch statements.

The value method returns the integer value. Values are assigned sequentially starting with 0. If the enum has a label named value, there is no conflict with the value() method in Java.

There will be only one instance of an enum. Since there is only one instance, pointer equality tests will work correctly. That is, the default java.lang.Object implementation of equals and hash will automatically work correctly for an enum's singleton object. The Java class for the enum also has an additional method, fromint, which returns the enum with the specified value.

The holder class for the enum is also generated. Its name is the enum's mapped Java class name with Holder appended to it as follows:

Mapping an enum

public class <enum_name>Holder implements
        org.omg.CORBA.portable.Streamable {
    public <enum_name> value;
    public <enum_name>Holder() {}
    public <enum_name>Holder(<enum_name> initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}
// IDL
enum EnumType {a, b, c};
// generated Java
public final class EnumType {
    public static final int _a = 0;
    public static final EnumType a = new EnumType(_a);
    public static final int _b = 1;
    public static final EnumType b = new EnumType(_b);
    public static final int _c = 2;
    public static final EnumType c = new EnumType(_c);
    public int value() {...}
    public static EnumType from_int(int value) { ... };
    // constructor
    private EnumType(int) {...}
};

Struct

An IDL struct is mapped to a final Java class with the same name that provides instance variables for the fields in IDL member ordering and a constructor for all values. A null constructor is also provided that allows the structure's fields to be initialized later. The Holder class for the struct is also generated. Its name is the struct's mapped Java class name with Holder appended to it as follows:

Mapping an IDL struct to Java.

final public class <class>Holder implements
        org.omg.CORBA.portable.Streamable {
    public <class> value;
    public <class>Holder() {}
    public <class>Holder(<class> initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}
/* From Example.idl: */
struct StructType {
    long field1;
    string field2;
};
// generated Java
final public class StructType {
    // instance variables
    public int field1;
    public String field2;
    // constructors
    public StructType() {}
    public StructType(int field1, String field2)
        {...}
}
final public class StructTypeHolder
        implements org.omg.CORBA.portable.Streamable {
    public StructType value;
    public StructTypeHolder() {}
    public StructTypeHolder(StructType initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}

Union

An IDL union is given the same name as the final Java class and mapped to it; it provides the following:

If there is a name clash with the mapped union type name or any of the field names, the normal name conflict resolution rule is used: prepend an underscore for the discriminator.

The methods for setting and retrieving a union branch have the same name but differ by their signature. The constructor creates the union without initializing it. The union can be initialized using the methods provided.

The holder class for the union is also generated. Its name is the union's mapped Java class name with Holder appended to it as follows:

Mapping an IDL union to Java.

final public class <union_class>Holder
            implements org.omg.CORBA.portable.Streamable {
    public <union_class> value;
    public <union_class>Holder() {}
    public <union_class>Holder(<union_class> initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}
/* From Example.idl: */
        union UnionType switch (EnumType) {
            case first:   long win;
            case second:  short place;
            case third:
            case fourth:  octet show;
            default:      boolean other;
        };
// Generated java
final public class UnionType {
            //constructor
            public UnionType() {...}

            //discriminator accessor
            public int discriminator() { ... }

            //win
            public int    win() { ... }
            public void   win(int value) { ... }

            //place
            public short  place() { ... }
            public void   place(short value) { ... }

            //show
            public byte   show() { ... }
            public void   show(byte value) { ... }
            public void   show(int discriminator, byte value) { ... }

            //other
            public boolean  other() {...}
            public void     other(boolean value) { ... }
}
final public class UnionTypeHolder {
                    implements org.omg.CORBA.portable.Streamable {
            public UnionType value;
            public UnionTypeHolder() {}
            public UnionTypeHolder(UnionType initial) {...}
            public _void read(org.omg.CORBA.portable.InputStream is)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream os)
        {...}
    public org.omg.CORBA.TypeCode type() {...}
}

Sequence

An IDL sequence is mapped to a Java array with the same name. In the mapping, anywhere the sequence type is needed, an array of the mapped type of the sequence element is used.

The holder class for the sequence is also generated. Its name is the sequence's mapped Java class name with Holder appended to it as follows:

Mapping an IDL sequence to Java.

final public class <sequence_class>Holder {
    public <sequence_element_type>[] value;
    public <sequence_class>Holder() {};
    public <sequence_class>Holder(
                        <sequence_element_type>[] initial) {...};
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}
// IDL
sequence<long>UnboundedData;
sequence<long, 42> BoundedData;
// generated Java
final public class UnboundedDataHolder
                implements org.omg.CORBA.portable.Streamable {
    public int[] value;
    public UnboundedDataHolder() {};
    public UnboundedDataHolder(int[] initial) {...};
    public void _read(org.omg.CORBA.portable.InputStream is)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream os)
        {...}
    public org.omg.CORBA.TypeCode type() {...}
}
final public class BoundedDataHolder 
        implements org.omg.CORBA.portable.Streamable {
    public int[] value;
    public BoundedDataHolder() {};
    public BoundedDataHolder(int[] initial) {...};
    public void _read(org.omg.CORBA.portable.InputStream is)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream os)
        {...}
    public org.omg.CORBA.TypeCode type() {...}
}

Array

An IDL array is mapped the same way as an IDL bounded sequence. In the mapping, anywhere the array type is needed, an array of the mapped type of array element is used. In Java, the natural Java subscripting operator is applied to the mapped array. The length of the array can be made available in Java, by bounding the array with an IDL constant, which will be mapped as per the rules for constants.

The holder class for the array is also generated. Its name is the array's mapped Java class name with Holder appended to it as follows:

Mapping for an array

final public class <array_class>Holder
        implements org.omg.CORBA.portable.Streamable {
    public <array_element_type>[] value;
    public <array_class>Holder() {}
    public <array_class>Holder(
                        <array_element_type>[] initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}
// IDL
const long ArrayBound = 42;
long larray[ArrayBound];
// generated Java
final public class larrayHolder
                implements org.omg.CORBA.portable.Streamable {
    public int[] value;
    public larrayHolder() {}
    public larrayHolder(int[] initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream is)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream os)
        {...}
    public org.omg.CORBA.TypeCode type() {...}
}

Interfaces

IDL interfaces are mapped to public Java interfaces and given the same names. An additional "helper" Java class with the suffix Helper is appended to the interface name. The Java interface extends the mapped, base org.omg.CORBA.Object interface.

The Java interface contains the mapped operation signatures. Methods can be invoked on an object reference to this interface.

The helper class holds a static narrow method that allows an instance of org.omg.CORBA.Object to be narrowed to the object reference of a more specific type. The IDL exception CORBA::BAD_PARAM is thrown if the narrow fails.

There are no special "nil" object references. Java null can be passed freely wherever an object reference is expected.

Attributes are mapped to a pair of Java accessor and modifier methods. These methods have the same name as the IDL attribute and are overloaded. There is no modifier method for IDL readonly attributes.

The holder class for the interface is also generated. Its name is the interface's mapped Java class name with Holder appended to it as follows:

Mapping an IDL interface to Java.

final public class <interface_class>Holder
        implements org.omg.CORBA.portable.Streamable {
    public <interface_class> value;
    public <interface_class>Holder() {}
    public <interface_class>Holder(
                        <interface_class> initial) {
        value = initial;
    public void _read(org.omg.CORBA.portable.InputStream i)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream o)
        {...}
    public org.omg.CORBA.TypeCode _type() {...}
}
/* From Example.idl: */
module Example {
    interface Foo {
        long method(in long arg) raises(e);
        attribute long assignable;
        readonly attribute long nonassignable;
    }
}

// Generated java

package Example;

public interface Foo extends org.omg.CORBA.Object {
    int method(int arg) throws Example.e;
    int assignable();
    void assignable(int i);
    int nonassignable();
}

public class FooHelper {

    // ... other standard helper methods

    public static Foo narrow(org.omg.CORBA.Object obj)
        {...}
}

final public class FooHolder 
        implements org.omg.CORBA.portable.Streamable {
    public Foo value;
    public FooHolder() {}
    public FooHolder(Foo initial) {...}
    public void _read(org.omg.CORBA.portable.InputStream is)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream os)
        {...}
    public org.omg.CORBA.TypeCode type() {...}
}

Passing Parameters

IDL defines three parameter passing modes:  in, out, and inout.

The in parameters implement call-by-value semantics, so IDL in parameters are supplied by passing the actual parameter when a method is invoked. The results of IDL operations are returned as the result of the corresponding Java method.

The IDL out and inout parameters implement call-by-result and call-by-value/result semantics, so they cannot be mapped directly into the Java parameter passing mechanism. The mapping mechanism defines holder classes for all the IDL basic and user-defined types which are used to implement the parameter modes in Java. The client supplies an instance of the appropriate Java holder class that is passed by value for each IDL out or inout parameter. The contents of the holder instance, but not the instance itself, is modified by the invocation and the client uses the changed contents, if any changes were made, after the invocation returns.

IN parameter mapping to Java actual parameters.

/* From Example.idl: */
module Example {
   interface Modes {
      long operation(in long inArg, out long outArg, inout long inoutArg);
   };
};

// Generated Java:
package Example;
public interface Modes {
   int operation(int inArg, IntHolder outArg, IntHolder inoutArg);
}
In the example above, the result comes back as an ordinary result and the in parameter is an ordinary value. But for the out and inout parameters, an appropriate holder must be constructed. A typical use case might look as follows:

// user Java code
// select a target object
Example.Modes target = ...;
// get the in actual value
int inArg = 57;
// prepare to receive out
IntHolder outHolder = new IntHolder();
// set up the in side of the inout
IntHolder inoutHolder = new IntHolder(131);
// make the invocation
int result =target.operation(inArg, outHolder, inoutHolder);
// use the value of the outHolder
... outHolder.value ...
// use the value of the inoutHolder
... inoutHolder.value ...
Before the invocation, the input value of the inout parameter must be set in the holder instance that will be the actual parameter. The inout holder can be filled in either by constructing a new holder from a value, or by assigning to the value of an existing holder of the appropriate type. After the invocation, the client uses the outHolder.value to access the value of the out parameter, and the inoutHolder.value to access the output value of the inout parameter. The return result of the IDL operation is available as the result of the invocation.

Server Implementation with Inheritance

Using inheritance is the simplest way to implement a server because server objects and object references look the same, behave the same, and can be used in exactly the same contexts. If a server object happens to be in the same process as its client, method invocations are an ordinary Java function call with no transport, indirection, or delegation of any kind.

Each IDL interface is mapped to a Java skeleton abstract class that implements the Java version of the IDL interface. User defined server classes are then linked to the ORB by extending the skeleton class, as shown below.

Server implementation in Java using inheritance.

/* From Example.idl: */
module Example {
   interface Account {
   };
};

// Generated java
package Example;
abstract public class _sk_Account
   extends org.omg.CORBA.Skeleton
   implements Account { ... }


// Linking an implementation to the ORB :
class AccountImpl extends Example._sk_Account { ... }

Server Implementation with Delegation

The use of inheritance to implement a server has one drawback: The server class extends the skeleton class, so it cannot use implementation inheritance for other purposes because Java only supports single inheritance. If the server class needs to use the inheritance link for another purpose, the delegation approach must be used.

When server classes are implemented using delegation, some extra code is generated:

The Operations interface does not extend CORBA.Object and, as a result, its instances cannot be treated directly as ORB objects. Instead, they have to be stored in a Tie class instance. Storing the instance of the Operation interface in the Tie object is done through a constructor provided by the Tie class. The following code example shows an example of how delegation is used.

Server implementation in Java using delegation.

/* From Example.idl: */
module Example {
    interface Account
        float balance();
    };
};


// Generated java
package Example;
public interface AccountOperations {
    public float balance();
};


package Example;
// Generated java
public class _tie_Account extends _sk_Account {
private AccountOperations delegate;
    public _tie_Account(AccountOperations d) { ... }
    public _tie_Account(AccountOperations d, String name) { ... }
    public float balance() {
        return delegate.balance();
    }
}


// Linking an implementation to the ORB :
class AccountImpl implements Example.AccountOperations extends Whatever { ...}
...
Example.Account a_server = new Example._tie_Account(new AccountImpl());
...

Interface Scope

Java does not allow declarations to be nested within an interface scope nor does it allow packages and interfaces to have the same name. Accordingly, interface scope is mapped to a package with the same name with an underscore suffix.

Mapping for Certain Nested Types

IDL allows type declarations nested within interfaces. Java does not allow classes to be nested within interfaces. Hence those IDL types that map to Java classes and that are declared within the scope of an interface must appear in a special "scope" package when mapped to Java.

IDL interfaces that contain these type declarations generate a scope package to contain the mapped Java class declarations. The scope package name is constructed by appending Package to the IDL type name.

Mapping for certain nested types

// IDL
module Example {
    interface Foo {
        exception e1 {};
    };
}

// generated Java
package Example.FooPackage;
final public class e1 extends org.omg.CORBA.UserException {...}

Mapping for Typedef

Java does not have a typedef construct.

IDL types that are mapped to simple Java types may not be subclassed in Java. Hence any typedefs that are type declarations for simple types are mapped to the original (mapped type) everywhere the typedef type appears. For simple types, Helper classes are generated for all typedefs.

Typedefs for non arrays and sequences are "unwound" to their original type until a simple IDL type or user-defined IDL type (of the non typedef variety) is encountered.

Holder classes are generated for sequence and array typedefs.

// IDL
struct EmpName {
    string firstName;
    string lastName;
};
typedef EmpName EmpRec;

// generated Java
   // regular struct mapping for EmpName
   // regular helper class mapping for EmpRec

final public class EmpName {
    ...
}

public class EmpRecHelper {
    ...
}

Mapping for Exceptions

IDL exceptions are mapped very similarly to structs. They are mapped to a Java class that provides instance variables for the fields of the exception and constructors.

CORBA system exceptions are unchecked exceptions. They inherit (indirectly) from java.lang.RuntimeException.

User-defined exceptions are checked exceptions. They inherit (indirectly) from java.lang.Exception.

User-defined Exceptions

User-defined exceptions are mapped to Java classes that extend org.omg.CORBA.UserException and are otherwise mapped just like the IDL struct type, including the generation of Helper and Holder classes.

If the exception is not defined within a nested IDL scope (essentially within an interface), its Java class name is defined within a special scope. Otherwise, its Java class name is defined within the scope of the Java package that corresponds to the exception's enclosing IDL module.

Mapping User-defined Exceptions

// IDL
module Example {
    exception ex1 {string reason;}
}

// Generated Java

package Example;

final public class ex1 extends org.omg.CORBA.UserException {
    public String reason;         // instance
    public ex1() {...}            // default constructor
    public ex1(String r) {...}    // constructor
}

final public class ex1Holder
                implements org.omg.CORBA.portable.Streamable {
    public ex1 value;
    public ex1Holder() {}
    public ex1Holder(ex1 initial) { ... }
    public void _read(org.omg.CORBA.portable.InputStream is)
        {...}
    public void _write(org.omg.CORBA.portable.OutputStream os)
        {...}
    public org.omg.CORBA.TypeCode type() {...}
}


[Contents] [Previous] [Next]

Last Updated: 02/04/98 14:19:16


Copyright © 1997 Netscape Communications Corporation

Any sample code included above is provided for your use on an "AS IS" basis, under the Netscape License Agreement - Terms of Use