Replacing A Session SuperProcedure With A Class In OOABL

Progress Software has numerous references in documentation and whitepapers to the parallels between superprocedures and classes, including a fairly lengthy, if somewhat flawed example in the Getting Started: Object-Oriented Programming manual for 10.1A that shows two parallel examples, one worked using superprocedures and one worked using classes. However, what is not shown is an example in which a class replaces a superprocedure while retaining the original program structure as a set of procedures. For a local super-procedure, this substitution is simple because the class does not need to be accessible except from the procedure that instantiates it. For a session superprocedure, a different functionality is required because the internal procedures of the session superprocedure become a part of the name space of procedures that did not invoke the superprocedure.

In other object-oriented languages, one would immediately think that this requirement required a name service such as JNDI or the use of singletons. The use of a name service seems unattractive for something as “intimate” as a session superprocedure because the single-threaded nature of the Progress client seems to imply that the class would be running in a different session. However, OE10.1A does not include an implementation of singletons, so what does one do?

An example is provided in this document with accompanying sample code that illustrates a technique that addresses this problem by using the FIRST-OBJECT method of the session handle and the NEXT-SIBLING method on the object identified by the FIRST-OBJECT method to locate a previously instantiated instance of the object one desires to use in common. Before going into specifics, let us consider the example application that we desire to enhance.

For services related to this material, see my website.


AttachmentSize
ReplaceAnSPWithAClass.pdf72.39 KB
ReplaceSPWithClass.zip6.38 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

A function to return the object id

with reference to the code given, below is a function run by an SP, which is (supposed to be) the only instantiating program to the class "Test".

 
FUNCTION getObjectID RETURNS Progress.Lang.Object
   (pcIdentifier AS CHAR ):

   DEFINE VARIABLE SessionObject AS Progress.Lang.Object    NO-UNDO.
   
   ASSIGN SessionObject = SESSION:FIRST-OBJECT.
   DO WHILE VALID-OBJECT(SessionObject):
      IF SessionObject:getClass():TypeName = pcIdentifier THEN 
         RETURN SessionObject.
      ELSE
         SessionObject = SessionObject:NEXT-SIBLING.
   END.

END FUNCTION.

then programs that need the context of the class would do something like this:

 
DEFINE VAR TestClass AS CLASS MyClass.Test NO-UNDO.
TestClass = CAST(getObjectID("MyClass.Test"), "MyClass.Test").

now if only it's possible to CAST with type name on a variable.


DYNAMIC-CAST

> now if only it's possible to CAST with type name on a variable.

It is since 10.1C - DYNAMIC-CAST does what you need.


DYNAMIC-CAST

Unfortunately (?), I'm on the same version with original post.. :-(

I think I don't even need this function on 10.1C as Singletons are already supported.


Progress 10.1.C - static methods

Hi,

Your implementation of enumerating all objects of the sesssion can now be modified wiht OpenEdge 10.1.C with the help of the keyword static.

The thing is that you created a private static variable inside the class holding a valid instance of the class. Furthermore, you have to make the constructor protected to prevent undesired instantiation of this class.

Example:


class PrinterSpooler:
define private static variable clsPS as class Printerspooler.


constructor protected PrinterSpooler:
end constructor.


method public static PrinterSpooler getInstance():
if not valid-object(clsPS) then
clsPS = new PrinterSpooler().
return clsPS.
end method.
end class.

somewhere else:


define variable clsPrnSpooler as class PrinterSpooler.

clsPrnSpooler = PrinterSpooler:getInstance().

.
.
.

Maybe you could also replace the superproc-functions with static methods in a class - depends on your requirements.

Greetings
Harry


tamhas's picture

Yeah, I've been expecting to

Yeah, I've been expecting to update this based on 10.1C, but have had a hard time getting 10.1C and, even though I now have it, I don't yet have anything but the docs installed. I want to keep the discussion of the old technique, of course, for those not as far as 10.1C.