Try OpenEdge Now
skip to main content
Object-oriented Programming
Programming with Class-based Objects : Instantiating and managing class-based objects : Publishing and subscribing to class events : Publishing class events
 
Publishing class events
ABL allows you to publish a class event from within the class that defines it using the Publish( ) event method. The effect is similar to publishing a named event using the PUBLISH statement, but using a syntax that is more natural for object-oriented programming, which supports strong-typing of the event and its handler signature. Because the method return type is void, you must invoke it as a statement (not in an expression).
This is the ABL syntax to publish a class event:

Syntax

[ THIS-OBJECT : |class-type-name : ]
 event-name : Publish ( [parameter[ , parameter]...] ) [ NO-ERROR ].
Thus, the Publish( ) method publishes the event specified by event-name. The class definition where you invoke Publish( ) must contain the DEFINE EVENT statement for event-name, and this statement cannot have the ABSTRACT option. If the class (abstract or non-abstract) inherits the event as abstract, you must override the event definition without the ABSTRACT option in order to publish it. Thus, you cannot invoke the Publish( ) method to publish any inherited event or any abstract event, even if you define the event as abstract in the same class definition. You only need to qualify the event name (with THIS-OBJECT for an instance event or the publishing class-type-name for a static event) if event-name is an ABL reserved keyword.
Each parameter in the list of parameters must be run-time compatible with the corresponding method parameter defined for the event. Even if the event handler that Publish( ) executes is an internal procedure, this compatibility conforms to passing parameters to methods. For more information, see the Parameter passing syntax reference entry in OpenEdge Development: ABL Reference.
When you invoke Publish( ), all event handlers subscribed to event-name execute once, and the results from any OUTPUT or INPUT-OUTPUT parameters are returned from the last of these event handlers to execute. However, when you have more than one event handler subscribed, the AVM does not guarantee the order in which they execute. So, you cannot be certain which event handler is returning the results from Publish( ). Furthermore, for any INPUT-OUTPUT parameter, or any INPUT parameter that passes a reference value (object reference or handle), each event handler that executes returns its parameter results as input to the next event handler to execute. So, you might not be certain how the results of INPUT-OUTPUT parameters, or INPUT reference parameters, are changed from one event handler to the next.
Caution: If you subscribe multiple event handlers to an event, you should ensure that these handlers are defined in such a way that their order of execution does not matter to any parameter results that you expect Publish( ) to return.
Use of the NO-ERROR option on Publish( ) supports standard ABL error handling for any event handler that raises an error, just as if you called the event handler directly. Also, if more than one event handler is subscribed to event-name, when a given event handler raises an error, the AVM stops executing event handlers beyond those that have already executed. For more information on error handling for event handlers, see Raising errors within a class event handler.
For a complete description of the Publish( ) method, see the reference entry for the Publish( ) event method in OpenEdge Development: ABL Reference.
For example, the following code fragment from the acme.myObjs.NECustObj sample class invokes a method (PublishOutputGenerated( )) provided by its super class to publish the OutputGenerated event, which has handlers subscribed to it in the sample Main class:
USING acme.myObjs.*.

CLASS acme.myObjs.NECustObj INHERITS CustObj:
  DEFINE PRIVATE TEMP-TABLE ttEmail NO-UNDO
    FIELD RecNum AS INTEGER
    FIELD Name   AS CHARACTER FORMAT "X(20)"
    FIELD Email  AS CHARACTER FORMAT "X(20)".
  ...

/* First override version of printObj for a single copy */
  METHOD PUBLIC OVERRIDE VOID printObj ( ):
    OUTPUT TO PRINTER.
    DISPLAY dtTimestamp.
    FOR EACH ttEmail:
      DISPLAY ttEmail.
    END.
    OUTPUT CLOSE.
    PublishOutputGenerated("One copy of report sent to printer").
  END METHOD.

  /* Second override version of printObj for multiple copies */
  METHOD PUBLIC OVERRIDE VOID printObj
    (INPUT piCopies AS INTEGER):
    DEFINE VARIABLE iCnt AS INTEGER.
    OUTPUT TO PRINTER.
    IF piCopies <> 0 THEN DO iCnt = 1 TO ABS(piCopies):
      DISPLAY dtTimestamp.
      FOR EACH ttEmail:
        DISPLAY ttEmail.
      END.
    END.
    OUTPUT CLOSE.
    PublishOutputGenerated(STRING(piCopies)
                           + " copies of report sent to printer").
  END METHOD.

  /* Override method to log customer information with email */
  METHOD PUBLIC OVERRIDE VOID logObj (INPUT pcFilename AS CHARACTER):
    OUTPUT TO VALUE (pcFilename).
    DISPLAY dtTimestamp.
    FOR EACH ttEmail:
      DISPLAY ttEmail.
    END.
    OUTPUT CLOSE.
    PublishOutputGenerated("One copy of report sent to "
                           + pcFilename + " file").
  END METHOD.
END CLASS.
PublishOutputGenerated( ) is a protected method that is first defined as abstract, along with the public abstract event, OutputGenerated, in the abstract base class, acme.myObjs.Common.CommonObj (see Sample classes). The derived class, acme.myObjs.CustObj, then implements these members by overriding their abstract definitions, and acme.myObjs.NECustObj inherits these implementations from CustObj, as shown in the previous fragment. The following fragment shows the member implementations in CustObj:
USING acme.myObjs.*.
USING acme.myObjs.Common.*.
USING acme.myObjs.Interfaces.*.

CLASS acme.myObjs.CustObj INHERITS CommonObj IMPLEMENTS IBusObj:
  ...
  DEFINE PUBLIC OVERRIDE EVENT OutputGenerated
    SIGNATURE VOID (pcOutputType AS CHARACTER).

  METHOD PROTECTED OVERRIDE VOID PublishOutputGenerated
    (INPUT pcOutputType AS CHARACTER):
    OutputGenerated:Publish(pcOutputType).
  END METHOD.
  ...
END CLASS.
Thus, the protected PublishOutputGenerated( ) method invokes Publish( ) on the event from within the class (CustObj) that implements it, allowing the derived class, acme.myObjs.NECustObj, to publish an event that it does not define.