Issue 2251: Java LocalStub (java-rtf) Source: (, ) Nature: Uncategorized Issue Severity: Summary: Summary: From IDL/Java specification (draft version 3.4 - August 9): The remote stub must be named _<interface_name>Stub where <interface_name> is the IDL interface name this stub is implementing. The local stub must be named _<interface_name>LocalStub where <interface_name> is the same IDL interface name. Local stubs are defined to be direct subclasses of remote stubs. and: The _is_local() method is provided so Helper classes may determine if a particular object is implemented by a local servant and if so create a local stub, rather than a remote stub. This function would typically be called from within the narrow() method of a Helper class. The _is_local() method may only return true if the servant incarnating the object is located in the same Java VM. The method may return false if the servant is not local or the ORB does not support local stubs for that particular servant. The default behavior of _is_local() is to return false. The design described in the specification seems to make it very difficult, if not impossible, to do the following: - Create a proxy that refers to some remote servant - Upon a request to the remote servant, a LocationForward is generated that refers to a colocated servant. Resolution: Merge the two stub classes together as one class with as minimal impact on the APIs and performance. Revised Text: Replace the first five paragraphs of section 25.21.5.1 "Stub/Skeleton Architecture" with the following text: "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: December 10, 1998: received issue February 26, 1999: moved from java-rtf to orb_revision June 4, 1999: closed issue Discussion: End of Annotations:===== Return-Path: Date: Thu, 10 Dec 1998 13:50:00 -0330 From: Matthew Newhook To: java-rtf@omg.org Subject: Java LocalStub Hi, From IDL/Java specification (draft version 3.4 - August 9): The remote stub must be named _Stub where is the IDL interface name this stub is implementing. The local stub must be named _LocalStub where is the same IDL interface name. Local stubs are defined to be direct subclasses of remote stubs. and: The _is_local() method is provided so Helper classes may determine if a particular object is implemented by a local servant and if so create a local stub, rather than a remote stub. This function would typically be called from within the narrow() method of a Helper class. The _is_local() method may only return true if the servant incarnating the object is located in the same Java VM. The method may return false if the servant is not local or the ORB does not support local stubs for that particular servant. The default behavior of _is_local() is to return false. The design described in the specification seems to make it very difficult, if not impossible, to do the following: - Create a proxy that refers to some remote servant - Upon a request to the remote servant, a LocationForward is generated that refers to a colocated servant. Given this scenario isn't it the case that the created proxy from narrow() is a remote stub, and not capable of local optimizations? Matthew -- Matthew Newhook E-Mail: mailto:matthew@ooc.com Software Designer WWW: http://www.ooc.com Object Oriented Concepts, Inc. Phone: (978) 439 9285 x 246 Return-Path: From: Juerg Wanner Date: Fri, 11 Dec 1998 11:05:49 +0100 (MET) To: java-rtf@omg.org Subject: Re: Java LocalStub References: Reply-To: juerg.wanner@ubs.com > The design described in the specification seems to make it very difficult, > if not impossible, to do the following: > > - Create a proxy that refers to some remote servant > - Upon a request to the remote servant, a LocationForward is generated that > refers to a colocated servant. > > Given this scenario isn't it the case that the created proxy from narrow() > is a remote stub, and not capable of local optimizations? I also think that it's bad to have code in the helper class that directly references the Stub implementation class. This should be hidden somewhere in the delegate, so that above scenarios are possible without losing portability of the helper If the delegate would have an operation like the following: org.omg.CORBA.Object createStub(org.omg.CORBA.Object self, Class c); (where c would denote the requested Operations interface) the ORB implementation could decide, how to create the proxy object. Delegate.createStub: if (implSpecificPredicate(c)) { // implementation specific creation of proxy } else { // create _Stub or _LocalStub // is contained in c.getName() } Juerg Wanner juerg.wanner@ubs.com UBS AG Postfach 8098 Zuerich Switzerland Return-Path: Date: Fri, 11 Dec 1998 14:48:42 -0500 From: Marc Laukien Organization: Object-Oriented Concepts, Inc. X-Accept-Language: en To: juerg.wanner@ubs.com CC: java-rtf@omg.org, Matthew Newhook , Michi Henning Subject: Re: Java LocalStub References: <13936.61053.131765.889263@wsc3po.flur.zuerich.ubs.ch> Hi, Juerg Wanner wrote: > > > The design described in the specification seems to make it very > difficult, > > if not impossible, to do the following: > > > > - Create a proxy that refers to some remote servant > > - Upon a request to the remote servant, a LocationForward is > generated that > > refers to a colocated servant. > > > > Given this scenario isn't it the case that the created proxy from > narrow() > > is a remote stub, and not capable of local optimizations? > > I also think that it's bad to have code in the helper class > that directly references the Stub implementation class. This should > be > hidden somewhere in the delegate, so that above scenarios are > possible > without losing portability of the helper > > If the delegate would have an operation like the following: > > org.omg.CORBA.Object createStub(org.omg.CORBA.Object self, Class > c); > (where c would denote the requested Operations interface) > > the ORB implementation could decide, how to create the proxy object. > > Delegate.createStub: > > if (implSpecificPredicate(c)) { > // implementation specific creation of proxy > } > else { > // create _Stub or _LocalStub > // is contained in c.getName() > } This is better, but it is still not sufficient. It's always possible that a servant is first remote, and later it becomes collocated, due to a location forward. In this case, the user code holds a regular stub that cannot be changed into a local stub by the ORB. I think this needs an additional level of indirection. That is, there should be only one stub, which delegates to a "real stub", for which two versions exist: A local one, and a remote one. The "real stub" can then be exchanged by the ORB, without affecting the stub for which a (Java-)reference is held by user code. What I'm basically talking about, is the bridge pattern. That is, for an interface A, instead of having: AStub ^ | ALocalStub We have: AStub <>----- AStubImpl ^ | ALocalStubImpl Cheers, Marc > > Juerg Wanner juerg.wanner@ubs.com > UBS AG > Postfach > 8098 Zuerich > Switzerland > > -- Marc Laukien Phone: (978) 439 9285 x 245 Object-Oriented Concepts, Inc. FAX: (978) 439 9286 44 Manning Rd. WWW: http://www.ooc.com Billerica, MA 01821 E-Mail: mailto:ml@ooc.com Return-Path: From: Juerg Wanner Date: Mon, 14 Dec 1998 10:16:17 +0100 (MET) To: java-rtf@omg.org Cc: ml@ooc.com Subject: Re: Java LocalStub References: Reply-To: juerg.wanner@ubs.com > > > > if (implSpecificPredicate(c)) { > > // implementation specific creation of proxy > > } > > else { > > // create _Stub or _LocalStub > > // is contained in c.getName() > > } > > This is better, but it is still not sufficient. The implementation specific part can return a stub that does delegation. Juerg Wanner juerg.wanner@ubs.com UBS AG Postfach 8098 Zuerich Switzerland Return-Path: Sender: "George Scott" Date: Mon, 14 Dec 1998 12:01:22 -0800 From: "George M. Scott" Organization: Inprise Corporation X-Accept-Language: en To: Matthew Newhook CC: java-rtf@omg.org Subject: Re: Java LocalStub References: <19981210135000.A20613@wiley242h106.roadrunner.nf.net> Matthew Newhook wrote: > > Hi, > From IDL/Java specification (draft version 3.4 - August 9): > > The remote stub must be named _Stub where > is the IDL interface name this stub is > implementing. The local stub must be named > _LocalStub > where is the same IDL interface name. Local > stubs > are defined to be direct subclasses of remote stubs. > > and: > > The _is_local() method is provided so Helper classes may determine > if a > particular object is implemented by a local servant and if so > create a > local stub, rather than a remote stub. This function would > typically > be called from within the narrow() method of a Helper class. The > _is_local() method may only return true if the servant incarnating > the > object is located in the same Java VM. The method may return false > if > the servant is not local or the ORB does not support local stubs > for > that particular servant. The default behavior of _is_local() is to > return false. > > The design described in the specification seems to make it very > difficult, > if not impossible, to do the following: > > - Create a proxy that refers to some remote servant > - Upon a request to the remote servant, a LocationForward is > generated that > refers to a colocated servant. > > Given this scenario isn't it the case that the created proxy from > narrow() > is a remote stub, and not capable of local optimizations? This is a known restriction of the local stub optimization, and please remember that it is primarily an optimization. Local stubs are only required for the correct behavior of IDL interfaces which reference native types (e.g. POA ServantManagers). For the case you are concerned about, the worst side effect will be to incur a marshalling cost for all data types passed as part of the operation. While this is not ideal, well designed Delegate and Input/OutputStream classes could nearly eliminate even this cost. The only proposed solution I've seen posted is to add yet another level of indirection to all stubs. I really don't see why we would want to introduce a performance penalty for all stubs just to handle the rare case of being forwarded to a local servant. George Return-Path: Date: Tue, 15 Dec 1998 10:51:33 -0500 From: Marc Laukien Organization: Object-Oriented Concepts, Inc. X-Accept-Language: en To: "George M. Scott" CC: Matthew Newhook , java-rtf@omg.org, Michi Henning Subject: Re: Java LocalStub References: <19981210135000.A20613@wiley242h106.roadrunner.nf.net> <36756E92.A3AC9A7D@inprise.com> Hi George, "George M. Scott" wrote: > > Matthew Newhook wrote: > > > > Hi, > > From IDL/Java specification (draft version 3.4 - August 9): > > > > The remote stub must be named _Stub where > > is the IDL interface name this stub is > > implementing. The local stub must be named > _LocalStub > > where is the same IDL interface name. Local > stubs > > are defined to be direct subclasses of remote stubs. > > > > and: > > > > The _is_local() method is provided so Helper classes may > determine if a > > particular object is implemented by a local servant and if so > create a > > local stub, rather than a remote stub. This function would > typically > > be called from within the narrow() method of a Helper > class. The > > _is_local() method may only return true if the servant > incarnating the > > object is located in the same Java VM. The method may return > false if > > the servant is not local or the ORB does not support local stubs > for > > that particular servant. The default behavior of _is_local() is > to > > return false. > > > > The design described in the specification seems to make it very > difficult, > > if not impossible, to do the following: > > > > - Create a proxy that refers to some remote servant > > - Upon a request to the remote servant, a LocationForward is > generated that > > refers to a colocated servant. > > > > Given this scenario isn't it the case that the created proxy from > narrow() > > is a remote stub, and not capable of local optimizations? > > This is a known restriction of the local stub optimization, and > please remember > that it is primarily an optimization. Local stubs are only required > for the correct > behavior of IDL interfaces which reference native types (e.g. POA > ServantManagers). I don't think that the local stubs fit the needs of locality constrained objects, like the POA servant manager. Why should stubs for locality constrained objects inherit from regular remote stubs? For locality constrained objects, you will never need the marshaling code of the remote stubs from which the local stubs inherit. > For the case you are concerned about, the worst side effect will be to incur a > marshalling cost for all data types passed as part of the operation. While this > is not ideal, well designed Delegate and Input/OutputStream classes could nearly > eliminate even this cost. > > The only proposed solution I've seen posted is to add yet another level of > indirection to all stubs. I really don't see why we would want to introduce > a performance penalty for all stubs just to handle the rare case of being > forwarded to a local servant. I doubt that this indirection will have any measurable impact. On the other hand, routing local calls through the Input/Output Stream classes will definitely slow down things. What about the following scenario: A servant is initially local, therefore a local stub is created. Later, the servant becomes remote. That means that the local stub must also be capable of sending requests remotely. So why should an application ever want to create a remote stub, if a local stub must also be able to do remote calls? And why should there then be two classes, if the most derived one has to fulfill both local and remote requirements? Cheers, Marc > > George -- Marc Laukien Phone: (978) 439 9285 x 245 Object-Oriented Concepts, Inc. FAX: (978) 439 9286 44 Manning Rd. WWW: http://www.ooc.com Billerica, MA 01821 E-Mail: mailto:ml@ooc.com Sender: "George Scott" Date: Thu, 04 Mar 1999 21:03:50 -0800 From: "George M. Scott" Organization: Inprise Corporation X-Accept-Language: en To: java-rtf@omg.org Subject: Issue 2251: Local stubs Below is a proposal for issue 2251: Local stubs. Issue: 2251 Source: Object-Oriented Concepts (Mr. Matthew Newhook, matthew@ooc.com) Summary: From IDL/Java specification (draft version 3.4 - August 9): The remote stub must be named _Stub where is the IDL interface name this stub is implementing. The local stub must be named _LocalStub where is the same IDL interface name. Local stubs are defined to be direct subclasses of remote stubs. and: The _is_local() method is provided so Helper classes may determine if a particular object is implemented by a local servant and if so create a local stub, rather than a remote stub. This function would typically be called from within the narrow() method of a Helper class. The _is_local() method may only return true if the servant incarnating the object is located in the same Java VM. The method may return false if the servant is not local or the ORB does not support local stubs for that particular servant. The default behavior of _is_local() is to return false. The design described in the specification seems to make it very difficult, if not impossible, to do the following: - Create a proxy that refers to some remote servant - Upon a request to the remote servant, a LocationForward is generated that refers to a colocated servant. ========================================================================== There are two known issues with the current local stub design. 1. It is difficult to support forwarding between local and remote servants given the current local stub specification 2. Since local/remote stubs are defined in two separate classes, which class should be specified in calls to org.omg.CORBA.portable.InputStream.read_Object(Class c); This proposal attempts to merge the two classes together as one class with minimal API impact and minimal impact on performance. Proposal ======== For each Java interface, a single stub is generated. The stub name is _Stub where interface_name corresponds to the IDL interface name. The generated stub is capable of invoking remote as well as local implementations. Local implementations are invoked differently from remote implementations. A stub may determine whether an implementatino is local or remote by invoking the is_local() operation on org.omg.CORBA.portable.ObjectImpl. Below is a sample IDL interface and sample generated stub: // IDL module Foo { interface A { void foo(); }; }; // Java package Foo; public class _AStub extends org.omg.CORBA.portable.ObjectImpl implements A { public java.lang.String[] _ids() { return __ids; } private static java.lang.String[] __ids = { "IDL:Foo/A:1.0" }; final public static java.lang.Class _opsClass = Foo.AOperations.class; public void foo() { while (true) { if (!this._is_local()) { org.omg.CORBA.portable.OutputStream _output = null; org.omg.CORBA.portable.InputStream _input = null; try { _output = this._request("foo", true); _input = this._invoke(_output); return ; } catch (org.omg.CORBA.portable.RemarshalException _exception) { continue; } catch (org.omg.CORBA.portable.ApplicationException _exception) { java.lang.String _exception_id = _exception.getId(); throw new org.omg.CORBA.UNKNOWN("Unexpected User Exception: " + _exception_id); } finally { this._releaseReply(_input); } } else { org.omg.CORBA.portable.ServantObject _so = _servant_preinvoke("foo", _opsClass); if (_so == null) { continue; } Foo.AOperations _self = (Foo.AOperations)_so.servant; try { _self.foo(); } finally { _servant_postinvoke(_so); } } } } } A couple of additional points: 1. _is_local may only return true if _servant_previnoke is going to return a non-null value, and it must return false if _servant_previnoke will return null. 2. Likewise, _servant_previnoke must return a non-null value if _is_local returned true, and vice versa. 3. Stubs for interfaces which are locality constrained may omit the check for is_local and only include the code for local invocations (e.g. the stub for org.omg.PortableServer.POA can only include the local code, since the remote will never be invoked.) 4. When the stub is forwarded from a remote reference to a local reference or vice versa, the value of is_local() should be flipped accordingly. If there are multiple threads accessing the same stub and/or delegate it is possible for one thread to receive and process a locate forward message, after another thread has called is_local(). In this case the Delegate can throw a RemarsahlException or return null from _servant_preinvoke() indicating that the value of _is_local() may have changed since it was last called. If there is general agreement on this approach I will write up a more concrete proposal. George Date: Tue, 09 Mar 1999 16:10:25 -0500 From: Marc Laukien Organization: Object-Oriented Concepts, Inc. X-Accept-Language: en To: "George M. Scott" CC: java-rtf@omg.org Subject: Re: Issue 2251: Local stubs References: <36DF65B6.A1EBF9D7@inprise.com> Hi George, > [...] > For each Java interface, a single stub is generated. The stub name > is _Stub where interface_name corresponds to the > IDL interface name. The generated stub is capable of invoking > remote > as well as local implementations. Local implementations are invoked > differently from remote implementations. A stub may determine > whether > an implementatino is local or remote by invoking the is_local() > operation > on org.omg.CORBA.portable.ObjectImpl. > [...] > If there is general agreement on this approach I will write up a > more > concrete proposal. I like your proposal. I need a little bit more time to think about it, but at first glance, it looks good. Cheers, Marc -- Marc Laukien Phone: (978) 439 9285 x 245 Object-Oriented Concepts, Inc. FAX: (978) 439 9286 44 Manning Rd. WWW: http://www.ooc.com Billerica, MA 01821 E-Mail: mailto:ml@ooc.com Date: Sat, 13 Mar 1999 14:09:44 +0000 From: Simon Nash Organization: IBM X-Accept-Language: en To: "George M. Scott" CC: java-rtf@omg.org Subject: Re: Issue 2251: Local stubs References: <36DF65B6.A1EBF9D7@inprise.com> George, Sorry for the confusion. I had intended to send this but I found it in my "Drafts" folder. See my comments below. "George M. Scott" wrote: > > Below is a proposal for issue 2251: Local stubs. > > Issue: 2251 > Source: Object-Oriented Concepts (Mr. Matthew Newhook, > matthew@ooc.com) > Summary: From IDL/Java specification (draft version 3.4 - August 9): > The remote stub must be named _Stub where is the IDL interface name > this stub is implementing. The local stub must be named _LocalStub > where is the same IDL interface name. Local stubs are defined to be > direct subclasses of remote stubs. and: The _is_local() method is > provided so Helper classes may determine if a particular object is > implemented by a local servant and if so create a local stub, rather > than a remote stub. This function would typically be called from > within the narrow() method of a Helper class. The _is_local() method > may only return true if the servant incarnating the object is > located > in the same Java VM. The method may return false if the servant is > not > local or the ORB does not support local stubs for that particular > servant. The default behavior of _is_local() is to return false. The > design described in the specification seems to make it very > difficult, > if not impossible, to do the following: - Create a proxy that refers > to some remote servant - Upon a request to the remote servant, a > LocationForward is generated that refers to a colocated servant. > > > ========================================================================== > > There are two known issues with the current local stub design. > > 1. It is difficult to support forwarding between local and remote > servants > given the current local stub specification > > 2. Since local/remote stubs are defined in two separate classes, > which > class should be specified in calls to > org.omg.CORBA.portable.InputStream.read_Object(Class c); > > This proposal attempts to merge the two classes together as one > class > with minimal API impact and minimal impact on performance. > > Proposal > ======== > > For each Java interface, a single stub is generated. The stub name > is _Stub where interface_name corresponds to the > IDL interface name. The generated stub is capable of invoking > remote > as well as local implementations. Local implementations are invoked > differently from remote implementations. A stub may determine > whether > an implementatino is local or remote by invoking the is_local() > operation > on org.omg.CORBA.portable.ObjectImpl. > > Below is a sample IDL interface and sample generated stub: > > // IDL > module Foo { > interface A { > void foo(); > }; > }; > > // Java > package Foo; > > public class _AStub extends org.omg.CORBA.portable.ObjectImpl > implements A { > > public java.lang.String[] _ids() { > return __ids; > } > > private static java.lang.String[] __ids = { > "IDL:Foo/A:1.0" > }; > > final public static java.lang.Class _opsClass = > Foo.AOperations.class; > > public void foo() { > while (true) { > if (!this._is_local()) { > org.omg.CORBA.portable.OutputStream _output = null; > org.omg.CORBA.portable.InputStream _input = null; > try { > _output = this._request("foo", true); > _input = this._invoke(_output); > return ; > } > catch (org.omg.CORBA.portable.RemarshalException _exception) > { > continue; > } > catch (org.omg.CORBA.portable.ApplicationException > _exception) { > java.lang.String _exception_id = _exception.getId(); > throw new org.omg.CORBA.UNKNOWN("Unexpected User > Exception: " + _exception_id); > } > finally { > this._releaseReply(_input); > } > } > else { > org.omg.CORBA.portable.ServantObject _so = > _servant_preinvoke("foo", _opsClass); > if (_so == null) { > continue; > } > Foo.AOperations _self = (Foo.AOperations)_so.servant; > try { > _self.foo(); > } > finally { > _servant_postinvoke(_so); > } > } > } > } > > } > > A couple of additional points: > > 1. _is_local may only return true if _servant_previnoke is going to > return > a non-null value, and it must return false if _servant_previnoke > will return null. > > 2. Likewise, _servant_previnoke must return a non-null value if > _is_local > returned true, and vice versa. > This seems to contradict the code, which tests for this "impossible" combination in the "if (_so == null)" line after the call to > preinvoke. Is this to cater for the case described in 4 below? > 3. Stubs for interfaces which are locality constrained may omit the check > for is_local and only include the code for local invocations (e.g. > the stub for org.omg.PortableServer.POA can only include the local > code, since the remote will never be invoked.) > > 4. When the stub is forwarded from a remote reference to a local reference > or vice versa, the value of is_local() should be flipped accordingly. > If there are multiple threads accessing the same stub and/or delegate > it is possible for one thread to receive and process a locate forward > message, after another thread has called is_local(). In this case > the Delegate can throw a RemarsahlException or return null from > _servant_preinvoke() indicating that the value of _is_local() may have > changed since it was last called. > This won't work if the flip happens after _servant_preinvoke has completed. Does this matter? Is it OK to continue with a local invocation in one thread when is_local has already been flipped to remote in another thread? Should there be some locking to prevent this? > If there is general agreement on this approach I will write up a more > concrete proposal. > I support the change to a single stub class. This is a simpler approach as well as solving the issues George listed. Simon -- Simon C Nash, Technology Architect, IBM Java Technology Centre Tel. +44-1962-815156 Fax +44-1962-818999 Hursley, England Internet: nash@hursley.ibm.com Lotus Notes: Simon Nash@ibmgb Date: Sun, 14 Mar 1999 13:16:32 +0000 From: Simon Nash Organization: IBM X-Accept-Language: en To: "George M. Scott" , java-rtf@omg.org Subject: Re: Issue 2251: Local stubs References: <36DF65B6.A1EBF9D7@inprise.com> <36EA71A8.F68DECBE@hursley.ibm.com> George, > public void foo() { > while (true) { > if (!this._is_local()) { > org.omg.CORBA.portable.OutputStream _output = null; > org.omg.CORBA.portable.InputStream _input = null; > try { > _output = this._request("foo", true); > _input = this._invoke(_output); > return ; > } > catch (org.omg.CORBA.portable.RemarshalException _exception) > { > continue; > } > catch (org.omg.CORBA.portable.ApplicationException > _exception) { > java.lang.String _exception_id = _exception.getId(); > throw new org.omg.CORBA.UNKNOWN("Unexpected User > Exception: " + _exception_id); > } > finally { > this._releaseReply(_input); > } > } > else { > org.omg.CORBA.portable.ServantObject _so = > _servant_preinvoke("foo", _opsClass); > if (_so == null) { > continue; > } > Foo.AOperations _self = (Foo.AOperations)_so.servant; > try { > _self.foo(); > } > finally { > _servant_postinvoke(_so); > } > } > } > } > It looks to me as though this method will loop if the local path is > taken. Don't you need a break or return in this path? Simon -- Simon C Nash, Technology Architect, IBM Java Technology Centre Tel. +44-1962-815156 Fax +44-1962-818999 Hursley, England Internet: nash@hursley.ibm.com Lotus Notes: Simon Nash@ibmgb Date: Mon, 15 Mar 1999 00:00:15 -0800 From: "George Scott" Organization: Inprise Corporation X-Accept-Language: en To: java-rtf@omg.org CC: jeffm@inprise.com, gscott@inprise.com Subject: issue 2251 - Java local stubs proposal Here is the formal proposal for issue 2251 "local stubs". The concept is unchanged from my proposal last week. The text below is the proposed changes to the specification. We would like to vote on this proposal for inclusion as part of the IDL/Java 2.4 RTF. George Proposal ======== Replace the first four paragraphs of section 25.21.5.1 "Stub/Skeleton Architecture" with the following text: "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 cotain paramter types which cannot be marshalled remotely. Remote invocation is used to invoke operations on object which are located in an address space separate from the client. While a stub is using local invocation it must provides complete location transparency. To provide the correct semantics, compliant programs must 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 name _Stub where 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 "Stub Design" 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 by a _request() call. The method _invoke() returns an InputStream which contains the marshalled reply. The _invoke() method may throw either an ApplicationException, a RemarshalException, or a CORBA system exception. An ApplicationException is thrown to indicate the target has thrown a CORBA user exception during the invocation. The stub may access the InputStream of the ApplicationException to unmarshal the exception data. A RemarshalException is 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. The stub should 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 a CORBA system exception is thrown, then the exception is 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 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 is 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 has 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." Date: Mon, 15 Mar 1999 11:30:29 +0000 From: Simon Nash Organization: IBM X-Accept-Language: en To: George Scott CC: java-rtf@omg.org, jeffm@inprise.com Subject: Re: issue 2251 - Java local stubs proposal References: <36ECBE0F.68E5925B@inprise.com> George, Looks good. A few minor nits - see comments below. Simon George Scott wrote: > > Here is the formal proposal for issue 2251 "local stubs". The > concept is > unchanged from my proposal last week. The text below is the > proposed > changes to the specification. > > We would like to vote on this proposal for inclusion as part of the > IDL/Java 2.4 RTF. > > George > > Proposal > ======== > > Replace the first four paragraphs of section 25.21.5.1 > "Stub/Skeleton > I think it's the first five paragraphs. > Architecture" with the following text: > > "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 > cotain paramter types which cannot be marshalled remotely. Remote > 2 typos: contain and parameter > invocation is used to invoke operations on object which are located in > Typo: objects > an address space separate from the client. > > While a stub is using local invocation it must provides complete > Typo: provide > location transparency. To provide the correct semantics, compliant > programs must 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 name _Stub where > is > Typo: named > 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 "Stub Design" 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(); > Typo: change "return =" to "return" > } > 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 by a > _request() call. The method _invoke() returns an InputStream which > contains the marshalled reply. The _invoke() method may throw > either > an ApplicationException, a RemarshalException, or a CORBA system > exception. An ApplicationException is thrown to indicate the target > has thrown a CORBA user exception during the invocation. The stub > may > access the InputStream of the ApplicationException to unmarshal the > exception data. A RemarshalException is 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. The stub should 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). > The wording here is unfortunate. It says nothing about what should > happen in this case if _is_local() returns true. I presume it attempts a > local call, but this should be stated explicitly. > If a CORBA system > exception is thrown, then the exception is 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 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 is 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 has 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." -- Simon C Nash, Technology Architect, IBM Java Technology Centre Tel. +44-1962-815156 Fax +44-1962-818999 Hursley, England Internet: nash@hursley.ibm.com Lotus Notes: Simon Nash@ibmgb X-Sender: jmischkinsky@mail.inprise.com Date: Mon, 15 Mar 1999 04:12:54 -0800 To: Simon Nash , George Scott From: "Jeff Mischkinsky" Subject: Re: issue 2251 - Java local stubs proposal Cc: java-rtf@omg.org References: <36ECBE0F.68E5925B@inprise.com> At 03:30 AM 3/15/99 , Simon Nash wrote: >George, >Looks good. A few minor nits - see comments below. I've incorporated the suggestions, done some minor editing (mostly adding a bunch of shalls), and modified the is_local language referred to below. Read all about it in Vote 4. jeff > > Simon > >George Scott wrote: >> >> Here is the formal proposal for issue 2251 "local stubs". The concept is >> unchanged from my proposal last week. The text below is the proposed >> changes to the specification. >> >> We would like to vote on this proposal for inclusion as part of the >> IDL/Java 2.4 RTF. >> >> George >> >> Proposal >> ======== >> >> Replace the first four paragraphs of section 25.21.5.1 "Stub/Skeleton >> >I think it's the first five paragraphs. > >> Architecture" with the following text: >> >> "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 >> cotain paramter types which cannot be marshalled remotely. Remote >> >2 typos: contain and parameter > >> invocation is used to invoke operations on object which are located in >> >Typo: objects > >> an address space separate from the client. >> >> While a stub is using local invocation it must provides complete >> >Typo: provide > >> location transparency. To provide the correct semantics, compliant >> programs must 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 name _Stub where is >> >Typo: named > >> 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 "Stub Design" 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(); >> >Typo: change "return =" to "return" > >> } >> 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 by a >> _request() call. The method _invoke() returns an InputStream which >> contains the marshalled reply. The _invoke() method may throw either >> an ApplicationException, a RemarshalException, or a CORBA system >> exception. An ApplicationException is thrown to indicate the target >> has thrown a CORBA user exception during the invocation. The stub may >> access the InputStream of the ApplicationException to unmarshal the >> exception data. A RemarshalException is 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. The stub should 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). >> >The wording here is unfortunate. It says nothing about what should happen >in this case if _is_local() returns true. I presume it attempts a local >call, but this should be stated explicitly. >> If a CORBA system >> exception is thrown, then the exception is 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 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 is 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 has 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." > >-- >Simon C Nash, Technology Architect, IBM Java Technology Centre >Tel. +44-1962-815156 Fax +44-1962-818999 Hursley, England >Internet: nash@hursley.ibm.com Lotus Notes: Simon Nash@ibmgb ****** NOTE NEW PHONE NUMBER ***** Jeff Mischkinsky email: jeffm@inprise.com Senior Software Architect jeffm@visigenic.com INPRISE Corporation voice: +1(650)358-3049 951 Mariner's Island Blvd. fax:: +1(650)286-2475 San Mateo, CA 94404 web: http://www.inprise.com