Can someone please remind me what the difference is between using DELETE OBJECT on a handle and calling a method like "deleteSession". There seems to be some nuances between them and I'm trying to sort that out.
Consider a handle like so...
DEFINE VARIABLE h_Session AS HANDLE NO-UNDO. RUN jms/ptpsession.p PERSISTENT SET h_Session ("-H localhost -S 5162").
If I use either (DELETE OBJECT h_Session) or (RUN deleteSession IN h_Session) then I have a slightly different end result. In both cases the function VALID-OBJECT(h_Session) will return FALSE. That is what is expected.
However what is unexpected is that the first variation (DELETE OBJECT) will not actually close the connection to the "brokerconnect" adapter. That will be leaked and will not be recovered. Since I'm running my ABL session within the context of PASOE the stakes are quite high that I get this right. The ABL sessions are long-lived and any leaked resources are a big problem - not just for the current sessions but for others as well.
While we are on this topic, I'm hoping someone can point me to a "WidgetHandle" similar to OpenEdge.Core.WidgetHandle that would properly clean up a jms/ptpsession in the finalizer.
I found a document (*link below) that says to use deleteSession and doesn't mention DELETE OBJECT at all. So I'm guessing that approach is the most standard one. I had started getting in the habit of using the DELETE OBJECT pattern on handles, via WidgetHandle if possible. But in this case it isn't accomplishing what I need it to since the "brokerconnect" adapter is claiming that the client connection is still active (via adaptman -query -all).
The difference is that, since persistent procedure don't have a destructor, no logic is executed when you do a DELETE OBJECT. No connections are closed, no other objects are deleted. DELETE OBJECT just destroys the persistent procedure. In this case deleteSession acts as a destructor, cleaning up the "mess". But you have to call is yourself.
Bronco is right - and that's actually a great reason to wrap persistent procedures in class based objects - so that you can implement a destructor there.
Another common pattern for simulating a destructor in a PP is to use the procedures "CLOSE" event - which also needs to be actively applied.
APPLY "CLOSE" TO hProcedure.
Its too bad that DELETE OBJECT doesn't do the clean-up. According to the documentation (at https://docs.progress.com/bundle/abl-reference/page/DELETE-OBJECT-statement.html ) it sounds like the intention of that method was that it would act like a destructor for a variety of different types of things. (widget, a procedure, a server, a socket, or an instance of a class).
The docs specifically say that Deleting the object causes all allocated resources associated with the object to be returned to the system (except when otherwise noted).
To me that would be nice if this syntax did the work to deallocate resources related to jms/ptpsession. I think it is very convenient when we have a common "delete" pattern that is applied to all types of handles, and persistent procedures. It avoids the trouble of having to learn and invoke special-purpose destructor method(s) that might be associated with every possible type of handle or persistent procedure. Based on the docs, I suspect that the original vision for "DELETE OBJECT" was that it would simply "do the right thing". But the jms session handle doesn't seem to live up to that vision.
It appears that OpenEdge.Core.WidgetHandle doesn't really "know" how to properly clean up a ptpsession either. I was looking for a class wrapper that already knows about the jms messaging stuff ... so I wouldn't have to roll my own. We are currently dealing with a bug in the "brokerconnect" adapter that happens on rare occasions ... and it would be nice if I could rely on a standard destructor pattern that might clean up all our messaging resources (so tech support doesn't have to be suspicious of my custom ABL).
The docs can't be relied on to be complete and concise.
In this case they fail to refer to how old-style handle-based objects are associated with the procedure that spawned them.
The short version is that handle-based objects are *not* closely associated to a procedure by default and will outlive them unless otherwise specified. (Do not be fooled by the INSTANTIATING-PROCEDURE handle reference, that'll just go invalid while the object sticks around).
This can be controlled by using widget-pools, which are managed by the procedure(s): Define a static widget-pool in the procedure, create the handle-based objects in that widget-pool, and when the procedure gets deleted, the widget-pool goes out of scope and the contained widgets get deleted.
The long version continues with how and when implicitly created objects are allocated to existing widget-pools and what other exceptions exist.
The extended version adds an epilogue explaining how that doesn't help with performing other clean-up tasks that you might find in a class' Destructor.
Those are points that are beyond what I can tell off the top of my head.