PreviousNextIndex

RUN statement

Calls an ABL procedure. This procedure can be local to or remote from the current session, external from or internal to the current procedure, and either synchronous or asynchronous. When a local or remote procedure is called synchronously, the calling procedure resumes execution only after the called procedure completes execution. When a remote procedure is called asynchronously, the calling procedure resumes execution immediately after the remote request is sent to the AppServer.

The RUN statement can also call functions or routines that reside in the Windows Dynamic Link Libraries (DLLs) or in UNIX shared libraries. The called routine must first be declared like an ABL internal procedure. The procedure declaration must be in the same file as the RUN statement.

You can also use the RUN statement to create and associate a procedure object with a Web service, and invoke a Web service operation.

Syntax

RUN 
  {     extern-proc-name 
     |  VALUE ( extern-expression ) 
     |  path-name<<member-name>> 
  } 
  [ PERSISTENT [ SET proc-handle ] ] 
  [ ON [ SERVER ] { server-handle | session-handle } 
       [ TRANSACTION DISTINCT ] 
       [ ASYNCHRONOUS  
            [ SET async-request-handle ] 
            [ EVENT-PROCEDURE event-internal-procedure 
                 [ IN procedure-context ] ] 
       ] 
  ] 
  [ ( parameter [ , parameter ] ... ) ] 
  [ argument ] ... 
  [ NO-ERROR ] 

RUN 
  { intern-proc-name | VALUE ( intern-expression) }  
  [ IN proc-handle ] 
  [ ASYNCHRONOUS 
       [ SET async-request-handle ] 
       [ EVENT-PROCEDURE event-internal-procedure 
           [ IN procedure-context ] ] 
  ] 
  [ ( parameter [ , parameter ] ... ) ] 
  [ NO-ERROR ] 

Use the following syntax to create and associate a procedure object with a Web service:

RUN portTypeName [ SET hPortType ] ON SERVER hWebService [ NO-ERROR ] . 

Use the following syntax to invoke a Web service operation:

RUN operationName IN hPortType  
  [ ASYNCHRONOUS  
    [ SET async-request-handle ]  
    [ EVENT-PROCEDURE event-internal-procedure  
      [ IN procedure-context ] ] 
  [ ( parameter [ , parameter ] ... ) ] 
  [ NO-ERROR ]. 

extern-proc-name
VALUE ( extern-expression )
path-name<<member-name>>
PERSISTENT [SET proc-handle ]
ON [SERVER] server-handle
ON [SERVER] session-handle
TRANSACTION DISTINCT
ASYNCHRONOUS [ SET async-request-handle ]
EVENT-PROCEDURE event-internal-procedure
IN procedure-context
( parameter [ , parameter ] ... )
argument
NO-ERROR (RUN statement specific behavior)
Note: See the next entry for a description of general NO-ERROR option behavior. This entry describes special cases for the RUN statement.
NO-ERROR (general behavior)
Note: See the previous entry for a description of specific RUN statement NO-ERROR option behavior. This entry describes general NO-ERROR behavior.
intern-proc-name
VALUE ( intern-expression )
IN proc-handle
portTypeName
hPortType
hWebService
operationName
Examples

The following procedure displays a simple menu. The user’s selection is stored in the selection variable. The INDEX function returns an integer value that indicates the position of the user’s selection in a string of characters ("12345"). If the value in the selection variable is not in the list of values, the INDEX function returns a 0. The VALIDATE statement ensures that the INDEX function did not return a zero. If it did, VALIDATE displays the message “Not a valid choice.”

r-run.p
DEFINE VARIABLE selection AS CHARACTER NO-UNDO FORMAT "x(1)" 
  LABEL "Enter Program Choice". 
DEFINE VARIABLE programs  AS CHARACTER NO-UNDO FORMAT "x(15)" EXTENT 5. 
/* Create the procedures custrpt.p, custedit.p, ordrpt.p, and ordedit.p.*/ 
ASSIGN 
  programs[1] = "custrpt.p" 
  programs[2] = "custedit.p" 
  programs[3] = "ordrpt.p" 
  programs[4] = "ordedit.p" 
  programs[5] = "r-exit.p". 
REPEAT: 
  FORM HEADER TODAY "MASTER MENU" AT 35 STRING(TIME,"hh:mm") to 79. 
  FORM SKIP(3) 
   "1 - Customer Listing"  AT 30 
   "2 - Customer Update" AT 30 
   "3 - Order Listing"  AT 30 
   "4 - Order Update"   AT 30 
   "5 - Quit System"    AT 30 
   selection COLON 28 AUTO-RETURN WITH SIDE-LABELS NO-BOX 1 DOWN.     
  UPDATE selection  
    VALIDATE(INDEX("12345",selection) NE 0, "Not a valid choice"). 
  HIDE ALL. 
  RUN VALUE(programs[INDEX("12345",selection)]). 
END. 

In the RUN statement, the INDEX function returns the position of the user’s selection in a character string. Suppose you chose option 2 from the menu. That option occupies the second position in the "12345" character string. Therefore, the INDEX function returns the number two (2). Using this number, the RUN statement reads, RUN VALUE(programs[2]). According to the assignments at the top of the procedure, the value of programs[2] is custedit.p. Now the RUN statement reads, RUN custedit.p, and the r-run.p procedure runs the custedit.p procedure.

The following two external procedures, r-runper.p and r-perprc.p, illustrate the PERSISTENT and IN proc-handle options of the RUN statement. The first procedure, a non-persistent control procedure, sets up a window to run and manage the second procedure as a persistent procedure.

r-runper.p 
DEFINE VARIABLE phand AS HANDLE NO-UNDO. 
DEFINE VARIABLE nhand AS HANDLE NO-UNDO. 
DEFINE VARIABLE whand AS HANDLE NO-UNDO. 
DEFINE BUTTON bStart LABEL "Start Customer Query". 
DEFINE BUTTON bRecall LABEL "Recall All Hidden Queries". 
DEFINE BUTTON bExit LABEL "Exit". 
DEFINE FRAME ControlFrame SKIP(.5) SPACE(2)  
  bStart bRecall bExit SPACE(2) SKIP(.5). 
ON CHOOSE OF bStart IN FRAME ControlFrame RUN r-perprc.p PERSISTENT. 
ON CHOOSE OF bRecall IN FRAME ControlFrame DO: 
  phand = SESSION:FIRST-PROCEDURE. 
  DO WHILE VALID-HANDLE(phand): 
    IF phand:PRIVATE-DATA = "Customer Browse" THEN 
      RUN recall-query IN phand. 
    phand = phand:NEXT-SIBLING. 
  END. 
END. 
ON CHOOSE OF bExit IN FRAME ControlFrame DO: 
  phand = SESSION:FIRST-PROCEDURE. 
  DO WHILE VALID-HANDLE(phand): 
    nhand = phand:NEXT-SIBLING. 
    IF phand:PRIVATE-DATA = "Customer Browse" THEN 
      RUN destroy-query IN phand. 
      phand = nhand. 
  END. 
  APPLY "RETURN" TO THIS-PROCEDURE. 
END. 
SESSION:SYSTEM-ALERT-BOXES = TRUE. 
CREATE WINDOW whand ASSIGN 
  TITLE            = "Customer Query Control" 
  SCROLL-BARS      = FALSE 
  MESSAGE-AREA     = FALSE 
  MAX-HEIGHT-CHARS = FRAME ControlFrame:HEIGHT-CHARS 
  MAX-WIDTH-CHARS  = FRAME ControlFrame:WIDTH-CHARS. 
CURRENT-WINDOW = whand. 
ENABLE ALL WITH FRAME ControlFrame. 
WAIT-FOR RETURN OF THIS-PROCEDURE. 

r-perprc.p
DEFINE VARIABLE custwin AS HANDLE NO-UNDO. 
DEFINE BUTTON bName    LABEL "Query on Name". 
DEFINE BUTTON bBalance LABEL "Query on Balance". 
DEFINE BUTTON bCredit  LABEL "Query on Credit". 
DEFINE BUTTON bHide    LABEL "Hide Query". 
DEFINE BUTTON bCancel  LABEL "Cancel". 
DEFINE QUERY custq FOR Customer. 
DEFINE BROWSE custb QUERY custq 
  DISPLAY Customer.Name Customer.Balance Customer.CreditLimit Customer.Phone 
    WITH 10 DOWN. 
DEFINE FRAME CustFrame custb SKIP 
    bName bBalance bCredit bHide bCancel. 
ON CHOOSE OF bName IN FRAME CustFrame DO: 
  custwin:TITLE = "Customers by Name". 
  OPEN QUERY custq FOR EACH Customer BY Customer.Name. 
END.         
ON CHOOSE OF bBalance IN FRAME CustFrame DO: 
  custwin:TITLE = "Customers by Balance". 
  OPEN QUERY custq FOR EACH Customer BY Customer.Balance DESCENDING. 
END.   
ON CHOOSE OF bCredit IN FRAME CustFrame DO: 
  custwin:TITLE = "Customers by Credit". 
  OPEN QUERY custq FOR EACH Customer BY Customer.CreditLimit DESCENDING. 
END. 
ON VALUE-CHANGED OF BROWSE custb DO: 
  IF Customer.Balance >= (Customer.CreditLimit * 0.75) THEN DO: 
    BELL. 
    MESSAGE "Evaluate" Customer.Name "for credit increase.". 
  END. 
END. 
IF THIS-PROCEDURE:PERSISTENT THEN DO: 
  THIS-PROCEDURE:PRIVATE-DATA = "Customer Browse". 
  CREATE WIDGET-POOL. 
END. 
CREATE WINDOW custwin ASSIGN 
  TITLE            = "Customer Browser" 
  SCROLL-BARS      = FALSE 
  MAX-HEIGHT-CHARS = FRAME CustFrame:HEIGHT-CHARS 
  MAX-WIDTH-CHARS  = FRAME CustFrame:WIDTH-CHARS. 
THIS-PROCEDURE:CURRENT-WINDOW = custwin. 
ENABLE ALL WITH FRAME CustFrame. 
IF THIS-PROCEDURE:PERSISTENT THEN DO: 
  ON CHOOSE OF bCancel IN FRAME CustFrame DO: 
    RUN destroy-query. 
  END. 
  ON CHOOSE OF bHide IN FRAME CustFrame DO: 
    custwin:VISIBLE = FALSE. 
  END. 
END. 
ELSE 
  WAIT-FOR CHOOSE OF bHide, bCancel IN FRAME CustFrame. 
PROCEDURE recall-query: 
  custwin:VISIBLE = TRUE. 
END PROCEDURE. 
PROCEDURE destroy-query: 
  DELETE PROCEDURE THIS-PROCEDURE NO-ERROR. 
  DELETE WIDGET-POOL. 
END PROCEDURE. 

The control procedure, r-runper.p, runs r-perprc.p each time you choose the Start Customer Query button. Each time it runs, r-perprc.p creates (instantiates) an additional context instance for the persistent procedure, including an additional window to open customer queries. When you choose the Recall All Hidden Queries button from the control window, r-runper.p calls the recall-query internal procedure in each instance of r-perprc.p to redisplay its window. Similarly, when you choose the Exit button, r-runper.p calls the destroy-query internal procedure in each instance of r-perprc.p to delete its context instance; r-runper.p then applies the RETURN event to itself to terminate by completing the WAIT-FOR statement.

The r-perprc.p procedure sets up a customer query that you can re-open three different ways: by name, by balance, or by credit. Each instance of r-perprc.p maintains a separate query for its own local customer buffer. Note that by testing and setting attributes of the THIS-PROCEDURE system handle, r-perprc.p can run either persistently or non-persistently. The basic difference is how the procedure maintains its own context. For example, when running persistently, it defines a trigger on the bCancel button to run its own deletion procedure, destroy-query, to terminate; when running non-persistently, it completes a WAIT-FOR statement with the bCancel button to terminate.

The following example shows how you might implement an asynchronous request. The procedure r-async.p runs persistently from a user-interface trigger, perhaps in response to a menu choice. This procedure, in turn, sends a request to run runReport.p on an AppServer, which provides an inventory report for the specified date.

When r-async.p returns, the user-interface trigger ends and the application returns to its WAIT-FOR state. The user continues to use the application in the normal way while the inventory report runs on the AppServer.

When runReport.p finishes running, a PROCEDURE-COMPLETE event occurs. This event causes the internal procedure reportDone to run automatically within the context of the application’s WAIT-FOR statement. Whatever the user is doing in the application, reportDone displays an alert box indicating whether or not the inventory report completed successfully and the number of lines (numLines) that were output for the report. (The bolded ABL statements indicate the code required to support asynchronous requests to run runReport.p.)

r-async.p 
DEFINE INPUT PARAMETER invDate AS DATE NO-UNDO.  
DEFINE VARIABLE sh AS HANDLE NO-UNDO. /* Server handle */ 
DEFINE VARIABLE ah AS HANDLE NO-UNDO. /* Asynchronous request handle */ 
CREATE SERVER sh. 
sh:CONNECT("-AppService Inventory -H myhost"). 
RUN runReport.p ON SERVER sh  
  ASYNCHRONOUS SET ah EVENT-PROCEDURE "reportDone" IN THIS-PROCEDURE 
  (invDate, OUTPUT numLines AS INTEGER). 
RETURN. 
PROCEDURE reportDone: 
  DEFINE INPUT PARAMETER numLines AS INTEGER. 
  IF ah:ERROR OR ah:STOP THEN 
    MESSAGE "An error occurred when running your" SKIP 
      "Inventory report for" invDate "." SKIP 
      "The error is:" ERROR-STATUS:GET-MESSAGE(1) 
      VIEW-AS ALERT-BOX. 
  ELSE 
    MESSAGE "Your Inventory report for " invDate SKIP 
      "has completed successfully." SKIP 
      numLines "report lines were generated" 
      VIEW-AS ALERT-BOX. 
  sh:DISCONNECT(). 
  DELETE OBJECT sh. 
  DELETE OBJECT THIS-PROCEDURE. /* Persistent proc no longer needed */ 
END PROCEDURE. 

Notes
See also

{ } Argument reference, { } Include file reference, APPLY statement, Asynchronous request object handle, CODEBASE-LOCATOR system handle, COMPILE statement, CREATE SERVER statement, DEFINE PARAMETER statement, DELETE PROCEDURE statement, ON statement, Parameter passing syntax, PROCEDURE statement, Procedure object handle, RUN STORED-PROCEDURE statement, THIS-PROCEDURE system handle, VALID-HANDLE function, Widget phrase


OpenEdge Release 10.2B
Copyright © 2009 Progress Software Corporation
PreviousNextIndex