skip to main content
OpenEdge Development: ADM Reference
Progress Dynamics Call Wrapper : Invoking the call wrapper using a single-entry point
 
Invoking the call wrapper using a single-entry point
Using a single-entry point to invoke the Progress Dynamics call wrapper requires more coding compared to using dynlaunch.i. However, using this method to invoke the Progress Dynamics call wrapper provides greater control of error handling and improved performance.
When you use a single-entry point, you can invoke the Progress Dynamics call wrapper using any of the single-entry-point procedures to make the appropriate call using a single RUN statement. These single-entry-point procedures act as containers that perform the tasks needed to make a dynamic call.
Note: Progress Software Corporation recommends that you use dynamic calls only in situations where signatures are unknown at run time and the number of calls is relatively small.
The following sections describe these single-entry point procedures:
*callstring.p
*callstringtt.p
*calltable.p
*calltablett.p
callstring.p
The callstring.p procedure allows you to make a Progress Dynamics call by providing a minimal list of information. The procedure then evaluates the data needed to make the call and performs all the steps necessary to invoke the call. This is advantageous because callstring.p can be run from a client procedure in a single AppServer request.
The caller can invoke procedures and functions in a remote manager by providing mnemonics that are evaluated by the callstring.p on the server. These mnemonics map to handles to procedures that are not known to the client.
The procedure invokes calls using a string containing the parameters in the following form:
 
mode datatype parameter, mode datatype parameter,…
Each token in a group is separated by a space, and when the value of a parameter token is a constant, the value is enclosed in single quotes.
Note: The following examples illustrate code for use in a Progress Dynamics environment because they use the Connection Manager.
The following code example illustrates a valid callstring.p invocation:
 
RUN callstring.p 
  ("disconnectService",             /* call to make */
   "ConnectionManager",             /* manager to use */
   "INPUT CHARACTER 'sports2000'"). /* parameter string */
The call results in a call to the disconnectService procedure in the Connection Manager in the local session and passes a single input parameter of data type character with the constant value of sports2000.
If the value of the parameter is determined from context, the constant value sports2000 can be replaced with a context variable name, as shown:
 
RUN callstring.p 
  ("disconnectService",             /* call to make */
   "ConnectionManager",             /* manager to use */
   "INPUT CHARACTER cDBName").      /* parameter string */
In this sample, cDBName is the name of a property or parameter that was previously set using setPropertyList or setSessionParam.
callstringtt.p
The callstringtt.p procedure is similar to callstring.p, except that it allows you to pass up to 64 temp-tables that function as parameters to the invokeCall procedure.
In addition to the behavior provided by callstring.p, callstringtt.p also allows the caller to provide a mapping between the 64 temp-tables being passed and the appropriate parameter to the call.
The code in Example A–1 illustrates an example procedure that you might need to call in a server-side procedure.
 
Example A–1: Example server-side procedure 
/* customerbl.p */
. . .
 
PROCEDURE obtainCustomerData:
  DEFINE INPUT PARAMETER phCustomerTempTable AS HANDLE     NO-UNDO.
  DEFINE INPUT PARAMETER pcSessionID         AS CHARACTER  NO-UNDO.
  DEFINE INPUT PARAMETER phOrderBuffer       AS HANDLE     NO-UNDO.
 
  /* Process the customer temp-table and order buffer */
 
END.
The code in Example A–2 illustrates making a call to the obtainCustomerData procedure. In this example, the procedure passes the handle to the temp-table as the first parameter and the buffer handle for the order temp-table as the second parameter.
 
Example A–2: Making a call to the obtainCustomerData procedure 
RUN adm2/callstringtt.p
  ("obtainCustomerData",         /* call to make */
   "customerbl.p",               /* procedure to use */
   "INPUT HANDLE 'T:01', INPUT CHARACTER cSessionID, 
      INPUT HANDLE 'B:02'",      /* parameter list */
   "",                           /* tables to skip */
   INPUT-OUTPUT TABLE ttCust,
   INPUT-OUTPUT TABLE ttOrder,
   INPUT-OUTPUT TABLE-HANDLE hTT03,
   INPUT-OUTPUT TABLE-HANDLE hTT04, 
   INPUT-OUTPUT TABLE-HANDLE hTT05,
   INPUT-OUTPUT TABLE-HANDLE hTT06, 
   INPUT-OUTPUT TABLE-HANDLE hTT07,
   INPUT-OUTPUT TABLE-HANDLE hTT08, 
   INPUT-OUTPUT TABLE-HANDLE hTT09,
   INPUT-OUTPUT TABLE-HANDLE hTT10, 
   ...
   INPUT-OUTPUT TABLE-HANDLE hTT64
   ).
Note: Example A–2 illustrates code for use in a non-Progress Dynamics environment because it uses a procedure file.
You must specify each TABLE-HANDLE you want to pass in a remote call. As a result, to make a remote call to the AppServer, you must specify all 64 TABLE-HANDLEs. To do this efficiently, you can specify the TABLE-HANDLE parameters using the include file callttparam.i located in the src/adm2/ directory. Before using this include file, you must define an array of handles with an extent of 64.
To do this, you could modify the code in Example A–2 as follows:
 
DEFINE VARIABLE hTT AS HANDLE EXTENT 64 NO-UNDO.
 
RUN adm2/callstringtt.p
  ("obtainCustomerData",         /* call to make */
   "customerbl.p",               /* procedure to use */
   "INPUT HANDLE 'T:01', INPUT CHARACTER cSessionID, 
      INPUT HANDLE 'B:02'",      /* parameter list */
   "",                           /* tables to skip */
   {src/adm2/callttparam.i &ARRAYFIELD = "hTT"
     &T01 = "TABLE ttCust" &T02 = "TABLE ttOrder"} 
  ).
The syntax highlighted in bold in the Example A–2 modified code deserves some additional explanation:
 
"INPUT HANDLE 'T:01', INPUT CHARACTER cSessionID, INPUT HANDLE 'B:02'"
The first and third parameters in the string correspond to the first and second temp-tables being passed as indicated by the 01 and 02 values after the colon. Note that the T: or B: that precedes the number indicates whether to pass a TEMP-TABLE (T) or BUFFER (B) handle to the procedure being called. As a result, the passing order of the temp-tables in the include file does not need to be the same order used by the call. The order used in the call is determined by the subscript that follows the T: or B:.
For more information, see the “Temp-table include files” section and the “Temp-table types” section.
calltable.p
The calltable.p procedure allows invocation of a call by passing in a temp-table that contains the parameter values for each parameter. The temp-table must be in one of the forms supported in the calltables.i file located in the src/adm2/ directory, or from the signature of the procedure or function being invoked.
For more information, see the “Temp-table include files” section and the “Temp-table types” section.
The code in Example A–3 illustrates using calltable.p to invoke a call.
 
Example A–3: Using calltable.p to invoke a call 
DEFINE VARIABLE hTT AS HANDLE NO-UNDO.
 
/* Include the temp-table definition */
{src/adm2/calltables.i
  &PARAM-TABLE-TYPE = "1"
  &PARAM-TABLE-NAME = "ttCallParam"}
 
/* Create the parameter values into the parameter value table */
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.iParamNo   = 1
    ttCallParam.cDataType  = "CHARACTER"
    ttCallParam.cIOMode    = "INPUT"
    ttCallParam.cCharacter = "aaa"
  .
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.iParamNo   = 2
    ttCallParam.cDataType  = "INTEGER"
    ttCallParam.cIOMode    = "INPUT-OUTPUT"
    ttCallParam.iInteger   = 12
  .
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.iParamNo   = 3
    ttCallParam.cDataType  = "HANDLE"
    ttCallParam.cIOMode    = "OUTPUT"
    ttCallParam.hHandle    = ?
  .
 
RUN adm2/calltable.p
  ("emptyProcParam",                    /* procedure to call */
   "calls.p",                           /* containing procedure file */
   INPUT TEMP-TABLE ttCallParam:HANDLE, /* handle of temp-table */
   INPUT-OUTPUT TABLE-HANDLE hTT).      /* unknown - no table handle */
After the call completes, the return values are available in output parameter records. In Example A–3, records 2 and 3 contain the output parameters from the call.
In addition, two extra records are appended to the table. The field cParamName on these fields is set to callReturnValue and errReturnValue. The callReturnValue field contains the value of the return value from the function or procedures and the errReturnValue field contains a value if an error condition occurs.
The code in Example A–4 illustrates using calltable.p with additional requirements for mappings. The difference between Example A–3 and Example A–4 is that the API is now forced to instantiate calls.p and obtain the signature to emptyProcParam to complete the mapping of values from ttCallParam to the values in the procedure. This is more expensive in terms of performance, but does however provide some options for specifying parameters.
As in Example A–3, the code in Example A–4 appends two extra records to the table after execution of the call. The field cParamName on these fields is set to callReturnValue and errReturnValue. The callReturnValue field contains the value of the return value from the function or procedure, and the errReturnValue field contains a value if an error condition occurs.
 
Example A–4: Using calltable.p to invoke a call and to instantiate calls.p 
DEFINE VARIABLE hTT AS HANDLE NO-UNDO.
 
/* Include the temp-table definition */
{src/adm2/calltables.i
  &PARAM-TABLE-TYPE = "4"
  &PARAM-TABLE-NAME = "ttCallParam"}
 
/* Create the parameter values into the parameter value table */
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.cParamName   = "pcChar"
    ttCallParam.cValue       = "aaa"
  .
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.cParamName   = "piInt"
    ttCallParam.cValue       = "12"
  .
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.cParamName   = "phHndl"
    ttCallParam.cValue       = ?
  .
 
RUN adm2/calltable.p
  ("emptyProcParam",                    /* procedure to call */
   "calls.p",                           /* containing procedure file */
   INPUT TEMP-TABLE ttCallParam:HANDLE, /* handle of temp-table */
   INPUT-OUTPUT TABLE-HANDLE hTT).      /* unknown - no table handle */
calltablett.p
The calltablett.p single-point entry call provides the functionality of calltable.p along with the ability to pass temp-tables. This is similar to using “callstringtt.p.” As with callstringtt.p, you can use the callttparam.i include file to simplify passing temp-tables. The code in Example A–5 illustrates the call done using the callstringtt.p call and calltablett.p.
 
Example A–5: Using callstringtt.p to make a call 
DEFINE VARIABLE hTT AS HANDLE EXTENT 64 NO-UNDO.
 
/* Include the temp-table definition */
{src/adm2/calltables.i
  &PARAM-TABLE-TYPE = "4"
  &PARAM-TABLE-NAME = "ttCallParam"}
 
/* Create the parameter values into the parameter value table */
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.cParamName   = "phCustomerTempTable"
    ttCallParam.cValue       = "T:01"
  .
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.cParamName   = "pcSessionID"
    ttCallParam.cValue       = cSessionID
  .
  CREATE ttCallParam.
  ASSIGN
    ttCallParam.cParamName   = "phOrderBuffer"
    ttCallParam.cValue       = "B:02"
  .
 
  hTT[01] = TEMP-TABLE ttCust:HANDLE.
  HTT[02] = TEMP-TABLE ttOrder:HANDLE
 
RUN adm2/calltablett.p
  (("obtainCustomerData",               /* call to make */
   "customerbl.p",                      /* manager to use */
   INPUT TEMP-TABLE ttCallParam:HANDLE, /* handle of temp-table */
   INPUT-OUTPUT TABLE-HANDLE hTT,       /* unknown - no table handle */
   "",                                  /* tables to skip */
   {src/adm2/callttparam.i &ARRAYFIELD = "hTT"}  
  ).