Type compatibility between HANDLE and Progress.Lang.Object

Posted by dbeavon on 19-Oct-2018 09:31

This may be a bit of an abstract question.  Is there a way to assign a HANDLE to a Progress.Lang.Object or vice versa?  Is there any built-in boxing classes that allows one to contain the other?  

For example I'm wondering if there is some way to define a generic API that may use one or the other in the declaration, but still support both types of references in the implementation.  For example, lets say I build a generic interface with a method like so:

   METHOD PUBLIC VOID DoAction(INPUT p_Object AS Progress.Lang.Object ).

Would there be a way to send a HANDLE thru that parameter (without building my own custom boxing class)?  Or if I defined DoAction(INPUT p_Handle AS HANDLE) then could I somehow send an Object as the input ?

"HANDLES" are the legacy way that OE allows you to pass around references to system components.  It would be nice if there was some compatibility between those legacy handles and regular OO object references.  Sometimes it seems that they are two different types of memory references that live in their own separate worlds.

Any ideas would be appreciated.

Posted by Peter Judge on 19-Oct-2018 09:50

Object references and HANDLEs are not type-compatible.  
 
> Sometimes it seems that they are two different types of memory references that live in their own separate worlds
 
This is well put, and true.
 
There is an OpenEdge.Core.WidgetHandle OOABL type that you can use to wrap a handle. It has the ability to destroy the wrapped handle once the object is GC’ed or destroyed.
 
Handles aren’t automatically collected since there is a lot of code that depends on them being available until the *application* decides they’re no longer needed. You can see this intent in code that looks like
RUN foo.p PERSISTENT.
 
Notice there’s no
SET <handle-variable>
 
In 11.6.3 there were a bunch of Ccs.Common.Support OOABL  interfaces like IHandleHolder added (to support another feature). This one is implemented by the WidgetHandle type, and lets you potentially do something like
 
Obj:DoAction(NEW OpenEdge.Core.WidgetHandle(handle-in-question)).
 
 
You can see an example of how we use those in the HTTP Client’s JsonBodyWriter:Write() method.
 
 
 

All Replies

Posted by jquerijero on 19-Oct-2018 09:40

Have you tried just defining method for both in your class?

DoAction(INPUT p_Handle AS HANDLE)

DoAction(INPUT p_Object AS Progress.Lang.Object )

Posted by Peter Judge on 19-Oct-2018 09:50

Object references and HANDLEs are not type-compatible.  
 
> Sometimes it seems that they are two different types of memory references that live in their own separate worlds
 
This is well put, and true.
 
There is an OpenEdge.Core.WidgetHandle OOABL type that you can use to wrap a handle. It has the ability to destroy the wrapped handle once the object is GC’ed or destroyed.
 
Handles aren’t automatically collected since there is a lot of code that depends on them being available until the *application* decides they’re no longer needed. You can see this intent in code that looks like
RUN foo.p PERSISTENT.
 
Notice there’s no
SET <handle-variable>
 
In 11.6.3 there were a bunch of Ccs.Common.Support OOABL  interfaces like IHandleHolder added (to support another feature). This one is implemented by the WidgetHandle type, and lets you potentially do something like
 
Obj:DoAction(NEW OpenEdge.Core.WidgetHandle(handle-in-question)).
 
 
You can see an example of how we use those in the HTTP Client’s JsonBodyWriter:Write() method.
 
 
 

Posted by dbeavon on 19-Oct-2018 09:53

I know that would work but it seemed redundant, if there was some compatibility between the two.  Eg a built-in method like GET-HANDLE(p_Object) or GET-OBJECT(p_Handle).

Even a built-in boxing class would do the trick if it existed (eg NEW Progress.Lang.HandleBox(p_Handle).

Also, my question is not really about a class, it's about a generic interface that would be implemented by classes.  It would be unfortunate if all implementations had to be cluttered with the two variations of DoAction, even though 99% would be working with the p_Object and only 1% would ever care about the p_Handle.

Posted by dbeavon on 19-Oct-2018 10:03

Thanks for the reply.  Will look into your handle holder.  Sounds a lot like the boxing class that I was looking for.  Please be patient for this post, since it seems like all my stuff is going thru moderation today and is taking a while to show up in the community forums.

Posted by dbeavon on 19-Oct-2018 10:30

Thanks for pointing me to OpenEdge.Core.WidgetHandle.  It is what I was looking for.  It seems to be working thus far. No point in writing my own.

I considered having the two methods but that appeared a bit redundant since the question is about a generic interface.  It would be unfortunate if all classes that implemented the interface needed to be cluttered with the TWO variations of DoAction even though 99% of them interacted with objects and only 1% would ever care about working with HANDLES.

(Again, sorry for any delays due to forum moderation)

Posted by Peter Judge on 19-Oct-2018 10:40

Boxing would another good solution but needs language/AVM support for the syntax and some form of built-in primitive classes. The OpenEdge.Core.* types attempt to address the latter but we’d need to get support for ABL boxing into the language team’s backlog and potentially replacements and/or updates for the OpenEdge.Core types, which are written in ABL.
 
 
The way to do that from a customer perspective is either via the Community Ideas space or the CVP. To state the obvious, having customer requests for features is immensely important in getting them prioritised. 
 
 
 
 
 

Posted by Peter Judge on 19-Oct-2018 11:34

It would be nice to have an OBJECT-REF(<int64>) function similar to the WIDGET-HANDLE() function, but you can roll your own, traversing the SESSION’s FIRST-OBJECT tree. The time cost of traversal doesn’t seem excessive but obviously it’s linear and will depend on the number of objects currently instantiated.
 
There’s a static ResolveWeakReference method in the OpenEdge.Core.Session class that does this for you. In 11.7.4 there’ll also be a WeakReference class in that same package that helps a little more with weak references.
 
 
 

Posted by dbeavon on 19-Oct-2018 18:26

I had a bit of trouble with WidgetHandle in that one of our deployment environments was only running 11.3.  (We really need to get up-to-date on our technology.)  Fortunately I was able to port that stuff back into my own namespace, and it seems to be fairly compatible with OE 11.3.

I was a bit confused how the Ccs namespace is introduced into the client session.  Does that come from some pl library? Or from some deeper magic?   Using the namespace works fine for me on 11.7.3, but I can't figure out which PROPATH component is allowing those interfaces to be available.

Posted by Mike Fechner on 19-Oct-2018 23:26

The Ccs.* Namespaces where added in 11.7.2 only.

The interfaces are located in OpenEdge.BusinessLogic.pl

or here:

github.com/.../businesscomponents

or here:

community.progress.com/.../2951.ade-openedge-11-7-3-development-tools-source-code

Posted by Peter Judge on 22-Oct-2018 09:04

The Ccs.Common and Ccs.ServiceManager types are in the OpenEdge.Core.pl. The Ccs.BusinessLogic types are in the OpenEdge.BusinessLogic.pl as Mike notes.
 
Both were added in 11.7.2. All of the interfaces in the Core library should work in 11.3 – the BusinessLogic ones use native enums and so will need 11.6.0+.
 

This thread is closed