This report memorializes the actions and resolutions of issues decided by the Java 2.4 Revision Task Force.
The members of the RTF were:
Mary Leland (HP) [ mleland@fpk.hp.com ]
Colm Caffery(IONA) [ ccaffrey@iona.com ]
Jeff Mischkinsky (INPRISE), Chair [ jeffm@inprise.com ]
Simon Nash (IBM) [nash@hursley.ibm.com ]
David Heisser (Sun) [dheisser@eng.sun.com ]
Chris Jacobi(Xerox) [jacobi@parc.xerox.com ] resigned after
Vote 1
The Task force was chartered on Sep. 18, 1998. The Task Force considered all of the 18 issues that were outstanding as of close of business March 5, 1999, well after the closing comment date of Jan 8, 1999. The Task Force concluded its work on March 19, 1999.
Of the 18 outstanding issues, 17 were successfully resolved.
Issue 1751 was deferred and left to a future RTF to consider.
The Task Force conducted almost all of its formal work via email and votes on ballots that were distributed via email and on the omg web site. The Task Force held only one formal meeting on Nov. 19, 1998. The minutes and formal actions for that meeting are available on the omg web site as document # ptc/98-11-03. The primary action with respect to issue resolution was to vote on the partial resolution of 1897.
The base document (the Java language mapping chapter) against which the Task Force started its work was OMG document # ptc/98-10-14. As work proceeded and interim drafts were produced applying the results of issue resolutions, resolutions were written against the updated draft chapter (which was made available on the OMG server in the /pub/orbrev/drafts directory. The major effect of this was to change references to the section numbers in later resolutions.
The Chair will complete editing of the base document (CORBA CORE Chapter 25) and make a review copy available as OMG document # ptc/99-03-04.
For the record, votes which passed for which resolutions of the
various issues are listed below:
98-11-19 Meeting: 1897 (except for package name)
Vote 1: 1993 2255 2256 2462 1897(package name to
be in CORBA_2_3)
Vote 2: 1750 1752 1942 2079 2228 2233 2462
defer 1751
Vote 3: 2514
Vote 4: 2551
Vote 5: 1980 proposal not passed
Vote 6: 1941 1964 2096
Vote 7: 1980
The Chair would personally like to thank the Task Force members and other significant contributors for their hard work and cooperation
Respectfully submitted,
Jeff Mischkinsky, (jeffm@inprise.com, jeff_mischkinsky@omg.org)
Java 2.4 RTF Chair
March 19, 1999
Consolidated Record of Votes
(YES means YES to All)
| Voter | Vote 1 | Vote 2 | Vote 3 | Vote 4 | Vote 5 | Vote 6 | Vote 7 |
| Mary Leland
(HP) |
YES | YES | YES | YES | ABS | YES | YES |
| Colm Caffery
(IONA) |
YES | YES | ABS | YES | YES | YES | YES |
| Jeff Mischkinsky
(INPRISE) |
YES | YES | YES | YES | YES | YES | YES |
| Simon Nash
(IBM) |
YES 1897,1993
ABS 2255, 2256 |
YES | YES | YES | NO | YES | YES |
| David Heisser
(Sun) |
YES | YES | ABS | YES | NO | YES | YES |
| Chris Jacobi
(Xerox) |
NV | Resigned |
Issues Addressed and Resolutions
Issue 1750: 2 IDL->Java
issues on the singleton ORB (01)
Issue 1751: 2 IDL->Java
issues on the singleton ORB (02)
Issue 1752: mapping of
IDL enumerations to java
Issue 1897: Evolving the
org.omg.* APIs
Issue 1941: Problem mapping
"global" types in Java mapping
Issue 1942: Need overloaded
write_Value method on OutputStream
Issue 1964: Creating TypeCodes
safely in java
Issue 1980: Updated proposal
for the OBV Java mapping
Issue 1993: create_lname
& create_lname_context
Issue 2079: Potential problem
with Java Mapping ORB init for Applet
Issue 2096: Issue with Mapping
for Constants within an interface
Issue 2228: typedefs in
IDl when generating Java code
Issue 2233: Helper "narrow"
exception clarification
Issue 2251: Java LocalStub
Issue 2255: Proposal for
persistent valuetypes
Issue 2256: PSS requiremnets
for the ObV/Java mapping
Issue 2462: BAD_PARAM issue
Issue 2514: PortableServer
Servant issue
Rationale:
This change has previously been discussed
by this RTF. It is
needed in this context because of the need
to include some Java
classes mapped from IDL enums (e.g., TCKind)
in the core JDK.
If new members are added to such an enum
later, there needs to be
a way to subclass the generated Java class
to produce a subclass
that corresponds to the new IDL (or PIDL)
enum.
2. Change the Object, ObjectImpl, and Delegate classes to
a. add new methods
org.omg.CORBA.Object
_get_interface_def()
to Object and ObjectImpl and
org.omg.CORBA.Object
get_interface_def(org.omg.CORBA.Object self)
to Delegate.
b. deprecate the existing methods
org.omg.CORBA.InterfaceDef
_get_interface()
on Object and ObjectImpl and
org.omg.CORBA.InterfaceDef
get_interface(org.omg.CORBA.Object self)
on Delegate.
Rationale:
The new methods do not refer to Interface
Repository types in their
signatures. However, at runtime they
still return the same IR objects
as the deprecated methods. Since this
signature change is a binary
incompatible change, and since Java methods
cannot be overloaded on
their return types, the new methods have
different names than the
deprecated methods. This allows an
easier path for user migration
than if the method signatures had been updated
"in place".
Removing IR types from the signatures allows
the new methods to be
included in the core JDK without also having
to include all the IR
classes in the core JDK. With likely
changes in this area in the near
future because of the Components RFP, it
is felt to be unwise to put
the IR into core in JDK 1.2.
3. Change the ORB class to
a. add a new method
public NVList create_operation_list(org.omg.CORBA.Object
oper)
b. deprecate the existing method
public NVList create_operation_list(org.omg.CORBA.OperationDef
oper)
Rationale:
The reason for this change is as for item
2 above. Since Java supports
overloading on argument types, there is
no need to change the method
name in this case.
4. Move some methods needed by Objects By Value from the ORB, InputStream
and
OutputStream classes to new subclasses (that will not
be part of the core
JDK 1.2). The names of these new classes are:
org.omg.CORBA_2_3.ORB
org.omg.CORBA_2_3.portable.InputStream
org.omg.CORBA_2_3.portable.OutputStream
and the methods affected are:
ORB.get_value_def
ORB.register_value_factory
ORB.unregister_value_factory
ORB.lookup_value_factory
InputStream.read_Value
InputStream.read_Abstract
OutputStream.write_Value
OutputStream.write_Abstract
OutputStream.start_block
OutputStream.end_block
Revised Text:
Actions taken:
August 28, 1998: received issue
Resolution: The solution is modify the mapping so as to
use an easier deal with form of a 2 class mapping,
much like C++, to add facilites that will fix the bugs that don't
allow recursive structures to be marshaled and unmarshaled, reduce the
"bloat", handle all the boxed values correctly, etc.
This proposal, coupled with the proposal to fix Issue 1981, which deals
with the "init" portion of the issue at the IDL level, fixes all the known
problems with the OBV/Java mapping.
Revised Text:
The changes are relative to version of Chapter 25 which has had Issue
1897 Evolving the org.omg.* APIs
applied to it (available as ftp://ftp.omg.org/orbrev/drafts/idljava_2_4v1.2.pdf
)
Add in section 25.4.1.4 after ObjectHolder
final public class ValueBaseHolder {
public org.omg.CORBA.portable.ValueBase value;
public ValueBaseHolder() {}
public ValueBaseHolder(org.omg.CORBA.portable.ValueBase 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(){...}
}
Replace section 25.5.1 with:
25.5.1 Generic BoxedValueHelper Interface
package org.omg.CORBA.portable;
public interface BoxedValueHelper {
java.io.Serializable read_value(InputStream is);
void write_value(OutputStream os, java.io.Serializable value);
java.lang.String get_id();
}
In 25.5.2 delete the 2nd and 5th paragraphs.
In 25.5.2 delete the specification of the "generated Java helper (value types)
In 25.5.2, in the specification of the "generated Java helper (non value types):
a. delete the "(non value types)" from the comment
b. Add the following methods to the end of the generated <typename>Helper class specification:
// for each initializer in non abstract
value type (see section 25.5.2.1)
public static <typename> <initializername>
(org.omg.CORBA.ORB orb, [<initializer arguments>]) {...}
c. Remove the paragraph following that starts with:
"For any user defined, value type ... "
Add a new section 25.5.2.1 "Value type initializer convenience functions" as follows:
For each initializer in a value type declaration, a corresponding
static convenience method is generated in the helper class for the
value type. The name of this method is the name of the initializer.
This method takes an orb instance and all the arguments
specified in the initializer argument list. The implementation of each
of these methods will locate a <typename>ValueFactory (see section
xxx) and call the identically named method on the ValueFactory passing
in the supplied arguments.
Replace all of section 25.13 Mapping for Value Type with:
25.13.1 Supporting interfaces for value types
25.13.1.1 ValueBase interface
package
org.omg.CORBA.portable;
public interface ValueBase extends IDLEntity {
String[] _truncatable_ids();
}
All values implement ValueBase either directly (for boxed primitives - see section 25.14.1), or indirectly by implementing either the StreamableValue or CustomValue interface (see below).
25.13.1.2 StreamableValue interface
package org.omg.CORBA.portable;
public interface
StreamableValue extends Streamable, ValueBase {
}
All non-boxed IDL valuetypes that are not custom marshalled,
implement this interface.
25.13.1.3 CustomMarshal interface
package org.omg.CORBA;
public interface CustomMarshal {
public
void marshal (org.omg.CORBA.DataOutputStream os);
public
void unmarshal (org.omg.CORBA.DataInputStream is);
}
Implementors of custom marshalled values implement the above
interface to provide custom marshalling.
25.13.1.4 CustomValue interface
package org.omg.CORBA.portable;
public interface CustomValue extends ValueBase,
org.omg.CORBA.CustomMarshal {
}
All custom value types generated from IDL implement this interface.
25.13.1.5 ValueFactory interface
package org.omg.CORBA.portable;
public interface ValueFactory {
java.io.Serializable
read_value(InputStream is);
}
The ValueFactory interface is the native mapping for the IDL type
CORBA::ValueFactory. The ValueFactory's
read_value() method is
called by the ORB runtime in the process of unmarshaling a
valuetype. A user must implement this method as part of
implementing
a type specific ValueFactory. In this implementation, the user
must call java.io.Serializable is.read_value(java.io.Serializable) with
a blank valuetype to use for unmarshalling. The value returned by the stream
is the same value passed in with all the data unmarshalled.
25.13.2 Basics for stateful value types
A concrete value type (i.e. one that is not declared as abstract) is
mapped to an abstract Java class with the same name, and a factory
Java interface
with the suffix "ValueFactory" appended to the value type name.
In addition, a helper
class with the suffix "Helper" appended to the value type name
and a holder
class with the suffix "Holder" appended to the value type name
shall be generated.
The specification of the generated holder class is as follows:
public final class <typename>Holder implements org.omg.CORBA.portable.Streamable
{
public <typename> value;
public <typename>Holder () {}
public <typename>Holder (final
<typename> initial) {
value = initial;
}
public void _read (final org.omg.CORBA.portable.InputStream
input) {...}
public void _write (final org.omg.CORBA.portable.OutputStream
output) {...}
public org.omg.CORBA.TypeCode _type
() {...}
}
The value type's mapped Java abstract class contains instance
variables that correspond to the
fields in the state definition in the IDL declaration. The order and
name of the
Java instance variables shall be the same as the correspondng
IDL state fields. Fields that are
identified as public in the IDL are mapped to public instance variables.
Fields
that are identified as private in the IDL are mapped to protected
instance variables in the mapped Java class.
The Java class for the value type extends either org.omg.CORBA.portable.CustomValue or org.omg.CORBA.portable.StreamableValue, depending on whether it is declared as custom in IDL or not, respectively.
The generated Java class shall provide implementation of the ValueBase interface for this value type.
The value type's generated value factory interface extends
org.omg.CORBA.portable.ValueFactory and contains one method
corresponding to each initializer declared in the IDL. The name of
the
method is the same as the name of the initializer, and the initializer
arguments are mapped in the same way as in parameters
are for IDL operations.
The implementor shall provide a factory class with implementations
for the
methods in the generated value factory interface. When
no initializers are declared in IDL, then the value type's value factory
is eliminated from the mapping and the implementor shall simply implement
org.omg.CORBA.portable.ValueFactory to provide the method body
for
read_value().
The inheritance scheme and specifics of the mapped class depend upon
the
inheritance and implementation characteristics of the value type and
are described
in the following subsections.
The mapped Java class contains abstract method definitions which correspond
to
the operations and attributes defined on the value type in IDL.
An implementor of the value type extends the generated Java class to
provide
implementation for the operations and attributes declared in the IDL,
including
those for any derived or supported value types or interfaces.
25.13.2.1 Inheritance from values
- Value types that do not inherit from other values or interfaces:
For non custom values, the generated Java class also implements the
StreamableValue interface and provides appropriate implementation
to marshal the
state of the object. For custom values, the generated class extends
CustomValue
but does not provide an implementation for the CustomMarshal
methods.
- inheritance from other stateful values
The generated Java class extends the Java class to which the inherited
value
type is mapped
- inheritance from abstract values
The generated Java class implements the Java interface to which the
inherited
abstract value is mapped(see section 25.13.3).
- supported interfaces
The Java class implements the Operations Java interface of all
the interfaces(if
any) that it supports. (Note that the operations interface for abstract
interfaces does not have the "Operations" suffix, see section 25.12.1.1).
The
implementation of the supported interfaces of the value type shall
use the tie
mechanism, to tie to the value type implementation.
25.13.3 Abstract Value Types
An abstract value type maps to a Java interface that implements ValueBase
and contains all the operations and
attributes specified in the IDL, mapped using the normal rules for
mapping operations and atttributes.
Abstract value types cannot be implemented directly. They must only be inherited by other stateful value types or abstract value types.
25.13.4 CORBA::ValueBase
CORBA::ValueBase is mapped to java.io.Serializable.
The get_value_def() operation is not mapped to any of the classes
associated
with a value type in Java. Instead it appears as an operation on the
ORB pseudo
object in Java(see "public static org.omg.CORBA.Object get_value_def(String
repId)" in section 25.19.10).
Note: This implies fixing up the referenced text in !too
25.19.10 to have the correct signature
25.13.5 Examples
In 25.13. 4 Example A
In the IDL
change init(in long w);
to: factory create(in long w);
Replace the generated Java by:
// generated Java
package ExampleA;
public abstract class WeightedBinaryTree implements org.omg.CORBA.portable.StreamableValue
{
// instance variables
protected int weight;
protected ExampleA.WeightedBinaryTree left;
protected ExampleA.WeightedBinaryTree right;
abstract public int[] preOrder ();
abstract public int[] postOrder ();
public org.omg.CORBA.TypeCode _type () {...}
public void _read (final org.omg.CORBA.portable.InputStream
_input) {
// read state information
using the wire format
...
}
public void _write (final org.omg.CORBA.portable.OutputStream
_output) {
....
}
public java.lang.String[] _truncatable_ids
() {...}
}
public final class WeightedBinaryTreeHelper {
< ed note: put all the helper methods here>
public static WeightedBinaryTree create(ORB orb,
int w) {
...
}
}
final public class WeightedBinaryTreeHolder implements org.omg.CORBA.portable.Streamable
{
...
<Note: the code for this isn't changing so just leave the old code
there>
}
public interface WeightedBinaryTreeValueFactory extends org.omg.CORBA.portable.ValueFactory
{
public ExampleA.WeightedBinaryTree create (int
w);
}
In 25.13.5 Example B
Keep the IDL and the Java mapping of the Printer interface as is.
Replace the generated Java for the WeightedBinaryTree with the following:
// generated java
package ExampleB;
public abstract class WeightedBinaryTree implements org.omg.CORBA.portable.StreamableValue,
PrinterOperations {
protected int weight;
protected ExampleB.WeightedBinaryTree
left;
protected ExampleB.WeightedBinaryTree
right;
abstract public int[] preOrder ();
abstract public int[] postOrder ();
public org.omg.CORBA.TypeCode _type
() {
...
}
public void _read (final org.omg.CORBA.portable.InputStream
_input) {
...
}
public void _write (final org.omg.CORBA.portable.OutputStream
_output) {
...
}
public java.lang.String[] _truncatable_ids
() {
...
}
}
public final class WeightedBinaryTreeHelper {
.... // helper methods...
< ed note: put all the helper methods here>
}
public final class WeightedBinaryTreeHolder {
... <note this hasn't changed, fill in old one here>
}
// user written code for default ValueFactory
public class WeightedBinaryTreeDefaultFactory implements org.omg.CORBA.portable.ValueFactory
{
public java.io.Serializable read_value
(org.omg.CORBA.portable.InputStream is) {
//user implements code
}
}
Add a new 25.13.5 Example C
// IDL
typedef sequence<unsigned long> WeightedSeq;
module ExampleC {
custom valuetype WeightedBinaryTree
{
private unsigned long weight;
private WeightedBinaryTree
left;
private WeightedBinaryTree
right;
factory create(in long w);
WeightedSeq preOrder();
WeightedSeq postOrder();
};
};
// generated Java
package ExampleC;
abstract public class WeightedBinaryTree implements org.omg.CORBA.portable.CustomValue
{...}
public final class WeightedBinaryTreeHelper {...}
public final class WeightedBinaryTreeHolder {...}
[ editing note: fill in the ... as an aid to the reader ]
25.13.6 Keep as is currently in the specification
25.13.7 ValueFactory and Marshaling
Replace second bullet in factory lookup algorithm by:
- If this is not successful and the repository id is a standard IDL
repository
id that starts with "IDL:",then extract the class name from the repository
id by
stripping of the "IDL:" header and ":<major>.<minor>" version
information
trailer and replacing all "/"s with "."s. Then attempt to load a value
factory by
appending a "DefaultFactory" suffix to the above class name.
Replace third bullet in factory lookup algorithm by:
- If this is not successful and the repository id is a standard RMI
repository
id that begins with "RMI:", then extract the class name from the repository
id
by stripping of the "RMI:" header and the ":<hashcode>:[<suid>]"
trailer and
applying all necessary conversions(see section 26.****). The ValueHandler
interface is used to read in the value, if it does not implement IDL
Entity.
Replace paragraph following the bullets by:
The IDL native type ValueFactory is mapped in Java to org.omg.CORBA.portable.ValueFactory.
In 25.14 Mapping for Value Box Type, replace the 3rd paragraph with the following:
A boxed value needs to be treated differently than regular values
in Java. Boxed values don't have factories and don't implmenent
either the StreamableValue or CustomValue interfaces,
so their
marshalling and unmarshalling is performed by a boxed value
helper object. In all cases, code can be generated to unmarshal
the boxed type. No user code is required for boxed values.
The BoxedValueHelper interface is implemented by all generated
Helper
classes for boxed valuetypes. The inherited read_value()
method is called
by the ORB runtime in the process of unmarshalling a boxed valuetype.
This is required for types that are immutable either in content (eg,
string),
or size (eg, sequences). The write_value() method call
is used for
marshalling the value box.
There are two general cases to consider. value boxes of primitive Java
types and value boxes for entities that are mapped to java classes.
In Section 25.14.1
Replace the first Java class <box_name> to be:
public class <box_name> implements ValueBase {
public <mapped_primitive_Java_type> value;
public <box_name>(<mapped_primitive_Java_type>
initial)
{ value = initial; }
private static String[] _ids = { <box_name>Helper.id()
};
public String[] _truncatable_ids()
{ return _ids; }
}
Replace the third Java class <box_name>Helper to be:
final public class <box_name>Helper implements org.omg.CORBA.portable.BoxedValueHelper
{
public <box_name> read_value(InputStream
is) {...}
public write_value(OutputStream is,
<box_name> value) {....}
public String get_id() { ... }
.... // other helper methods
}
In Section 25.14.1.1 Primitive Type example:
Replace the MyLong class by:
public class MyLong implements ValueBase {
public int value;
public MyLong(int initial) { value = initial;
}
private static String[] _ids = { MyLongHelper.id()
};
public String[] _truncatable_ids() { return _ids;
}
}
Replace MyLongHelper by:
final public class MyLongHelper implements org.omg.CORBA.portable.BoxedValueHelper
{
public MyLong read_value(InputStream
is) {...}
public write_value(OutputStream is,
MyLong value) {....}
public String get_id() { ... }
.... // other helper methods
}
Add to end of paragraph on 25.14.2
//IDL
valuetype <box_name> <IDLtype>;
final public class <box_name>Helper implements org.omg.CORBA.portable.BoxedValueHelper
{
public <IDLType> read_value(InputStream
is) {...}
public write_value(OutputStream is,
<IDLType> value) {....}
.... // other helper methods
}
final public class <box_name>Holder implements org.omg.CORBA.portable.Streamable
{
public <mapped_java_class> value;
...
}
Add a new section 25.14.3 Examples
// IDL
module A {
valuetype BoxedString string;
};
// generated Java
package A;
public final class BoxedStringHelper implements org.omg.CORBA.portable.BoxedValueHelper
{
private static final BoxedStringHelper
_instance = new BoxedStringHelper();
public static java.lang.String read
(final org.omg.CORBA.portable.InputStream _input) {
if (!(_input instanceof
org.omg.CORBA_2_3.portable.InputStream)) {
throw new org.omg.CORBA.BAD_PARAM();
}
return (java.lang.String)((org.omg.CORBA_2_3.portable.InputStream)_input).read_value(_instance);
}
public static void write (final org.omg.CORBA.portable.OutputStream
_output, final java.lang.String value) {
if (!(_output instanceof
org.omg.CORBA_2_3.portable.OutputStream)) {
throw new org.omg.CORBA.BAD_PARAM();
}
((org.omg.CORBA_2_3.portable.OutputStream)_output).write_value(value,
_instance);
}
public static void insert (org.omg.CORBA.Any any, java.lang.String
value) {...}
public static java.lang.String extract (org.omg.CORBA.Any
any) {...}
public static org.omg.CORBA.TypeCode type () {...}
public static java.lang.String id () {...}
public java.io.Serializable read_value (org.omg.CORBA.portable.InputStream
_input) {
java.lang.String result;
result = _input.read_string();
return (java.io.Serializable)result;
}
public void write_value (org.omg.CORBA.portable.OutputStream _output,
java.io.Serializable value) {
if (!(value instanceof
java.lang.String)) {
throw new org.omg.CORBA.MARSHAL();
}
java.lang.String valueType
= (java.lang.String)value;
_output.write_string(valueType);
}
public java.lang.String get_id () {
return id();
}
}
public final class BoxedStringHolder implements org.omg.CORBA.portable.Streamable {....}
Section 25.14.3.1 Example B
// IDL
struct idlStruct {
short x;
};
module A {
valuetype BoxedStruct idlStruct;
};
// generated Java
package A;
public final class BoxedStructHelper implements org.omg.CORBA.portable.BoxedValueHelper
{
private static final BoxedStructHelper
_instance = new BoxedStructHelper();
public static idlStruct read (final
org.omg.CORBA.portable.InputStream _input) {
if (!(_input instanceof org.omg.CORBA_2_3.portable.InputStream)) {
throw new org.omg.CORBA.BAD_PARAM();
}
return (idlStruct)((org.omg.CORBA_2_3.portable.InputStream)_input).read_value(_instance);
}
public static void write (final org.omg.CORBA.portable.OutputStream
_output, final idlStruct value) {
if (!(_output instanceof org.omg.CORBA_2_3.portable.OutputStream))
{
throw new
org.omg.CORBA.BAD_PARAM();
}
((org.omg.CORBA_2_3.portable.OutputStream)_output).write_value(value,
_instance);
}
public static void insert (final org.omg.CORBA.Any any, final idlStruct value) {...}
public static idlStruct extract (final org.omg.CORBA.Any any) {...}
public static org.omg.CORBA.TypeCode type () {...}
public static java.lang.String id () {...}
public java.io.Serializable read_value (final org.omg.CORBA.portable.InputStream
_input) {
final idlStruct result;
result = idlStructHelper.read(_input);
return (java.io.Serializable)result;
}
public void write_value (final org.omg.CORBA.portable.OutputStream
_output, final java.io.Serializable value) {
if (!(value instanceof
idlStruct)) {
throw new org.omg.CORBA.MARSHAL();
}
idlStruct valueType =
(idlStruct)value;
idlStructHelper.write(_output,
valueType);
}
public java.lang.String get_id () {
return id();
}
}
public final class BoxedStructHolder implements org.omg.CORBA.portable.Streamable
{
....
}
In Section 25.19.10 ORB in the definition of the org.omg.CORBA_2_3.ORB class:
Change the signature of register_value_factory to:
public org.omg.CORBA.portable.ValueFactory register_value_factory(String
id,
org.omg.CORBA.portable.ValueFactory factory);
Change the return type lookup_value_factory()
from: org.omg.CORBA.portable.ValueHelper
to: org.omg.CORBA.portable.ValueFactory
In Section 25.21.4
In the definition of the org.omg.CORBA_2_3.portable.InputStream:
Change both declarations of read_Value to read_value
In the 2nd overloaded read_Value change the parameter type
from: ValueHelper helper
to: java.lang.String rep_id
Change both declarations of read_Abstract to read_abstract_interface
Add the following new methods:
public java.io.Serializable read_value(org.omg.CORBA.portable.BoxedValueHelper
factory) {
throw new org.omg.CORBA.NO_IMPLEMENT();
}
public java.io.Serializable read_value(java.io.Serializable)
{
throw new org.omg.CORBA.NO_IMPLEMENT();
}
In the definition of the org.omg.CORBA_2_3.portable.OutputStream:
Change both declarations of write_Value to write_value
In the 2nd overloaded write_Value change the 2nd parameter type
from: ValueHelper value
to: java.lang.String rep_id
Change the declaration of write_Abstract to write_abstract_interface
Delete the start_block and end_block methods
Add the following new method:
public void write_value(java.io.Serializable value, org.omg.CORBA.portable.BoxedValueHelper
factory) {
throw new org.omg.CORBA.NO_IMPLEMENT();
}
Actions taken: Close and incorporate changes
September 18, 1998: received issue
February 26, 1999: moved from obv_rtf to java rtf
"The mapping defines a single stub which may be used for both local
and remote invocation. Local invocation provides higher performance
for collocated calls on Servants located in the same process as the
client. Local invocation is also required for certain IDL types
which
contain parameter types which cannot be marshalled remotely.
Remote
invocation is used to invoke operations on objects which are located
in
an address space separate from the client.
While a stub is using local invocation it shall provide complete
location transparency. To provide the correct semantics, compliant
programs shall comply with the parameter passing semantics defined
in
Section 25.11.2, "Parameter Passing Modes". When using local
invocation the stub shall copy all valuetypes passed to them, either
as
in parameters, or as data within in parameters, and shall pass the
resulting copies to the Servant in place of the originals. The
valuetypes shall be copied using the same deep copy semantics as would
result from GIOP marshaling and unmarshaling.
The following sections describe the characteristics of the stubs and
skeletons. The examples are based on the following IDL:"
In Section 25.21.5.1.1 "Stub Design" replace the second paragraph with
the following:
"The stub shall be named _<interface_name>Stub where <interface_name>
is
the IDL interface name this stub is implementing.
Stubs shall support both local invocation and remote invocation, except
in the following cases:
1. The stub is implementing an IDL interface which may only be
invoked
locally (e.g. PortableServer::POA).
In this case, the stub may choose
to implement only local invocation.
"
In Section 25.21.5.1.1, remove the fourth paragraph.
Replace the example in Section 25.21.5.1.3 "Stream-based Stub example"
with the following:
package Example;
public class _AnInterfaceStub extends org.omg.CORBA.portable.ObjectImpl implements AnInterface {
public java.lang.String[] _ids () {
return __ids;
}
private static java.lang.String[] __ids = {
"IDL:Example/AnInterface:1.0"
};
final public static java.lang.Class _opsClass = Example.AnInterfaceOperations.class;
public int length (java.lang.String s) throws Example.AnException
{
while(true) {
if(!this._is_local()) {
try {
org.omg.CORBA.portable.OutputStream _output = this._request("length", true);
_output.write_string(s);
org.omg.CORBA.portable.InputStream _input = this._invoke(_output);
return _input.read_long();
}
catch (org.omg.CORBA.portable.RemarshalException
_exception) {
continue;
}
catch (org.omg.CORBA.portable.ApplicationException
_exception) {
java.lang.String _exception_id = _exception.getId();
if (_exception_id.equals(Example.AnExceptionHelper.id())) {
throw Example.AnExceptionHelper.read(_exception.getInputStream());
}
throw new org.omg.CORBA.UNKNOWN("Unexpected User Exception: " + _exception_id);
}
finally {
this._releaseReply(_input);
}
}
else {
org.omg.CORBA.portable.ServantObject
_so = _servant_preinvoke("length", _opsClass);
if (_so == null)
{
continue;
}
Example.AnInterfaceOperations
_self = (Example.AnInterfaceOperations)_so.servant;
try {
return _self.length(s);
}
finally {
_servant_postinvoke(_so);
}
}
}
}
}
In Section 25.21.5.2 "Stub and Skeleton Class Hierarchy", Figure 25-1,
remove the class "_FooLocalStub".
In Section 25.21.5.3.1 "Streaming Stub APIs" replace the second paragraph
with the following:
"The method _invoke() is called to invoke an operation. The stub
provides an OutputStream that was previously returned from a
_request() call. The method _invoke() returns an
InputStream which
contains the marshalled reply. The _invoke() method may
throw only one of the following:
an ApplicationException, a RemarshalException, or a CORBA system
exception. An ApplicationException shall be thrown to indicate
the target
has raised a CORBA user exception during the invocation. The
stub may
access the InputStream of the ApplicationException to
unmarshal the
exception data. A RemarshalException shall be thrown if
the stub was
redirected to a different target object and remarshalling is
necessary, this is normally due to a GIOP object forward or locate
forward messages. In this case, the stub shall then attempt to
reinvoke the request on
behalf of the client after verifying the target is still remote by
invoking _is_local() (see section 25.21.5.3.2). If _is_local()
returns True, then an attempt to reinvoke the request
using the Local Invocation APIs shall be made. If a CORBA system
exception is thrown, then the exception shall be passed on directly
to the
user."
Rename section 25.21.5.3.2 "Local Stub APIs" to "Local Invocation APIs".
Replace the first three paragraphs with the following:
"Local invocation is supported by the following methods and classes:
The _is_local() method is provided so stubs may determine if
a
particular object is implemented by a local servant and hence local
invocation APIS may be used. The _is_local() method shall return
true
if the servant incarnating the object is located in the same process
as the stub and they both share the same ORB instance. The
_is_local() method returns false otherwise. The default behavior
of
_is_local() is to return false.
The _servant_preinvoke() method is invoked by a local stub to
obtain a
Java reference to the servant which should be used for this
request. The method takes a string containing the operation name and
a
Class object representing the expected type of the servant as
parameters and returns a ServantObject object (Note, ORB vendors may
subclass the ServantObject object to return additional request state
that may be required by their implementations). The operation name
corresponds to the operation name as it would be encoded in a GIOP
request. The expected type shall be the Class object associated with
the
operations class of the stub's interface (e.g. A stub for an interface
Foo, would pass the Class object for the FooOperations interface).
The
method shall return a null value if the servant is not local or the
servant has ceased to be local as a result of the call (i.e, due to
a
ForwardRequest from a POA ServantManager). The method shall throw
CORBA::BAD_PARAM if the servant is not of the expected
type. If a
ServantObject object is returned, then the servant field shall have
been set
to an object of the expected type (Note, the object may or may not
be
the actual servant instance). The local stub may cast the servant
field to the expected type, and then invoke the operation
directly. The ServantRequest object is valid for only one invocation,
and cannot be used for more than one invocation."
Actions taken:Close, and incorporate text.
December 10, 1998: received issue
The current definition of org.omg.PortableServer.Servant does
not
correctly implement the specification defined for Servant as
defined
by the Java mapping. In particular, it does not correctly implement
the
semantics of bullet item number one defined for _this_object().
Furthermore, the current definition of Servant hard codes certain
functionality and prevents vendors from making fixes or otherwise
changing the implementation.
To fix this problem, a delegation model for the Servant
class similar to that used by stubs is proposed in order to allow vendors
full control over the way that certain Servant operations are handled.
We believe this is necessary to correctly implement the _this_object()
method
for which a correct implementation using the currently defined public POA
APIs is somewhat problematic. The proposal also allows vendors flexibility
in the implementation of the methods way which may allow for better optimization
opporutunities.
The proposed changes have minimum impact on end user applications as
well
as minimal impact on ORB vendors (the Visibroker ORB was converted
to the new design in less than a day including time to implement _this_object()).
The only API change end users will see is the removal of the method:
void _orb(org.omg.CORBA.ORB orb);
This method does not work well with the new delegation model, and it
has been our experience that this method is rarely, if ever, used.
The only need a user ever has to set the ORB on a Servant is for the
case of implicit activation, and the prefered way is to use the
method:
org.omg.CORBA.Object _this_object(org.omg.CORBA.ORB orb);
The _this_object() method is still provided, but now sets the
delegate instead of setting a locally stored ORB variable. We believe
this method is
required and also commonly used so should remain part of the user API.
The proposal defines a new Delegate interface which is defined
in a new
package org.omg.PortableServer.portable and mirrors the design
pattern
used by the Stub classes for the Java mapping. Unlike stubs,
however,
the Servant must have a way of setting its delegate given an instance
of the ORB in order to support implicit activation via _this().
To
accomplish this our proposal includes the addition of a new method
on the ORB class:
public void set_delegate(java.lang.Object object);
This method will actually appear on org.omg.CORBA_2_3.ORB due
to the
org.omg.CORBA.ORB class being frozen in the Java 2 core.
This method
takes an object which is known to the ORB to follow the delegation
model
and sets it delegate. In this version of the proposal the only
type
that an ORB is required to support setting the delegate is
org.omg.PortableServer.Servant. However, we expect in
the future it may be possible to make use of this method to set delegates
on stubs which have been
reincarnated through Java serialization.
Note, we also chose to make the Delegate an interface rather
than an
abstract class to provide for greater flexibility in the
implementation.
This proposal as it fixes an important piece of POA functionality
and is required for correct operation of the POA.
George Scott, gscott@inprise.com
Revised Text:
In Section 25.19.10 "ORB". Add the following new method to org.omg.CORBA_2_3.ORB:
public abstract class ORB extends org.omg.CORBA.ORB {
abstract public void set_delegate(java.lang.Object
wrapper);
}
Add the following paragraph following the class definition for
org.omg.CORBA_2_3.ORB:
Add a new section: 25.19.10.1 set_delegate at the end of section 25.19.10
"The set_delegate() method supports the Java ORB portability
interfaces by providing a method for classes which support ORB portability
through
delegation to set their delegate. This is typically required
in cases
where instances of such classes were created by the application
programmer rather than the ORB runtime. The wrapper parameter
is the
instance of the object on which the ORB must set the delegate.
The
mechanism to set the delegate is specific to the class of the wrapper
instance. The set_delegate() method shall support setting
delegates on
instances of the following Java classes:
- org.omg.PortableServer.Servant
If the wrapper paramter is not an instance of a class for which the
ORB
can set the delegate, the CORBA::BAD_PARAM exception shall be thrown."
In Section 25.20.2.1 "Mapping of PortableServer::Servant", reformat the methods and group them to clarify their use as follows:
Add the comment below and group the following 5 methods
// Convenience methods for application programmer
final public org.omg.CORBA.Object _this_object() {...}
final public org.omg.CORBA.Object _this_object(ORB orb) {...}
final public org.omg.CORBA.ORB _orb() {...}
final public POA _poa() {...}
final public byte[] _object_id() {...}
Add the comment below and group the following 4 methods:
// Methods which may be overriden by the application programmer
public POA _default_POA() {...}
public boolean _is_a(String repository_id) {...}
public boolean _non_existent() {...}
public org.omg.CORBA.InterfaceDef _get_interface() {...}
Add the comment below and group the following 1 methods:
// Methods for which the skeleton or application programmer
must
// provide an implementation
abstract public String[] _all_interfaces(POA poa, byte[]
objectId);
Delete the following method:
final public void _orb(ORB orb) {...}
Replace the following paragraph which reads as "The Servant class is an abstract Java class which serves as the base classfor all POA Servant implementations." with the following 3 paragraphs:
"The Servant class is an abstract Java class which serves as the base
classfor all POA Servant implementations. It provides a number of methods
which may be invoked by the application programmer, as well as methods
which are invoked by the POA itself and may be overridden by the user
to
control aspects of Servant behavior.
With the exception of the _all_interfaces() and _this_object(ORB
orb)
methods, all methods defined on the Servant class may only be
invoked
after the Servant has been associated with an ORB instance.
Attempting to invoke the methods on a Servant which has not
been
associated with an ORB instance shall result in a CORBA::BAD_INV_ORDER
exception being raised. A Servant is associated with an
ORB instance
via one of the following means:
1. Through a call to _this_object(ORB orb) passing an
ORB instance as
parameter. The Servant will become
associated with the specified
ORB instance.
2. By explicitly activating a Servant with a POA by calling either
POA::activate_object or POA::activate_object_with_id.
Activating
a Servant in this fashion will associate
the Servant with the ORB
instance which contains the POA on which the Servant
has been activated.
3. By returning a Servant instance from a ServantManager.
The Servant
returned from PortableServer::ServantActivator::incarnate()
or
PortableServer::ServantLocator::preinvoke()
will be associated with the
ORB instance which contains the POA on which the
ServantManager is
installed.
4. By installing the Servant as a default servant on a POA.
The Servant
will become associated with the ORB instance which
contains the POA
for which the Servant is acting as a default servant.
It is not possible to associate a Servant with more than one ORB instance
at a time. Attempting to associate a Servant with more than one
ORB
instance will result in undefined behavior.
Replace Section 25.20.2.1.2 _orb with:
The _orb() method is a convenience method which returns the instance
of the
ORB which is currently associated with the Servant."
In Section 25.20.2.1.1 _this_object
Replace the fourth bullet item with the following text:
" * The _this_object(ORB orb) method first associates the Servant
with
the specified ORB instance and then invokes _this_object() as
normal."
In Section 25.21.2 "Overall Architecture" Add the following bullet
after the "Portable Delegate" bullet:
" * Portable Servant Delegate - provides the vendor specific implementation
of PortableServer::Servant"
In Section 25.21.2.1 "Portability Package" Change the first sentence
to
the following:
"The APIs needed to implement portability are found in the
org.omg.CORBA.portable and org.omg.PortableServer.portable
packages."
Add the following new sections after section 25.21.6 "Delegate":
(ORB becomes 25.21.9)
"
25.21.7 "Servant"
The Servant class is the base class for all POA-based implementations.
It delegates all functionality to the Delegate interface defined in
section 25.21.6.
package org.omg.PortableServer;
import org.omg.CORBA.ORB;
import org.omg.PortableServer.portable.Delegate;
abstract public class Servant {
private transient Delegate _delegate = null;
final public Delegate _get_delegate() {
if (_delegate == null) {
throw new org.omg.CORBA.BAD_INV_ORDER("The
Servant has not been associated with an ORB instance");
}
return _delegate;
}
final public void _set_delegate(Delegate delegate) {
_delegate = delegate;
}
final public org.omg.CORBA.Object _this_object() {
return _get_delegate().this_object(this);
}
final public org.omg.CORBA.Object _this_object(ORB orb) {
try {
((org.omg.CORBA_2_3.ORB)orb).set_delegate(this);
}
catch(ClassCastException e) {
throw new org.omg.CORBA.BAD_PARAM("POA
Servant requires an instance of org.omg.CORBA_2_3.ORB");
}
return _this_object();
}
// access to the ORB
final public ORB _orb() {
return _get_delegate().orb(this);
}
// convenience methods to the POA Current
final public POA _poa() {
return _get_delegate().poa(this);
}
final public byte[] _object_id() {
return _get_delegate().object_id(this);
}
// Methods which may be overriden by the user
public POA _default_POA() {
return _get_delegate().default_POA(this);
}
public boolean _is_a(String repository_id) {
return _get_delegate().is_a(this, repository_id);
}
public boolean _non_existent() {
return _get_delegate().non_existent(this);
}
public org.omg.CORBA.InterfaceDef _get_interface() {
return _get_delegate().get_interface(this);
}
// methods for which the user must provide an implementation
abstract public String[] _all_interfaces(POA poa, byte[]
objectId);
}
25.21.8 "Servant Delegate"
The Delegate interface provides the ORB vendor specific implementation
of
PortableServer::Servant.
package org.omg.PortableServer.portable;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.POA;
public interface Delegate {
org.omg.CORBA.ORB orb(Servant self);
org.omg.CORBA.Object this_object(Servant self);
POA poa(Servant self);
byte[] object_id(Servant self);
POA default_POA(Servant self);
boolean is_a(Servant self, String repository_id);
boolean non_existent(Servant self);
org.omg.CORBA.InterfaceDef get_interface(Servant self);
}
Rename Section 25.21.6 "Delegate" to "Stub Delegate".
Actions taken: Close, incorporate text
March 5, 1999: received issue