Kbase P15804: Running ADM2 SmartDataObject Internal Procedures on AppServer.
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  1/25/2005 |
|
Status: Unverified
GOAL:
Running ADM2 SmartDataObject Internal Procedures on AppServer.
GOAL:
Running and ADM2 SDO procedure split across the Appserver boundary.
FIX:
This solution discusses how to write an internal procedure in a SmartDataObject (SDO) that can be run from a client object, and that invokes database required code in itself on the server side of the object.
When an SDO is run split between a client and an AppServer, internal procedures within that SDO must be written with consideration to where and how they run. The code might need to run on the client side or server side of the SDO based on whether or not it contains code that requires a database connection. The code might have to be run from other objects on the client.
When an SDO runs on an AppServer from a 4GL client that does not have a database connection, the SDO proxy (_cl.r) is running on the client. There is a database required setting for internal procedures of DB-AWARE (SDOs are DB-AWARE) objects that can be set when code in the internal procedure requires a database connection. This setting excludes this code from compilation of an SDO proxy. If you run this internal procedure from a client object, you will receive an error similar to the following:
procedure dcustomer_cl.w has no entry point for NameSearchProc. (6456)
In order to have the code in this internal procedure available to call from other client objects without the caller needing to know anything special about the procedure, you can write the internal procedure without setting database required. You can include the code that requires a database connection with DB-REQUIRED-START and DB-REQUIRED-END preprocessors surrounding it.
In this way, the procedure itself is in both the client and server sides of the SDO but the code that requires a database connection is not included in the compile of the client proxy.
The following example is a SmartWindow that contains a Customer SDO and a fill-in for Customer Name to allow the user to enter a name that is used to reposition to the first Customer in the SDO that begins with the entered Name criteria. If the SDO was not running on an AppServer, or if the client were to always have a database connection, this functionality could be accomplished within the SmartWindow with the following code:
FIND FIRST Customer WHERE Customer.Name BEGINS
cSrchName:SCREEN-VALUE NO-LOCK NO-ERROR.
IF AVAILABLE Customer THEN
DYNAMIC-FUNCTION('fetchRowIdent':U IN h_dcustomer,
INPUT STRING(ROWID(Customer)), INPUT "").
If the SDO runs an AppServer from a 4GL client that does not have a database connection, the following steps can be taken:
1) Run the procedure in the SDO from the SmartWindow:
RUN NameSearchProc IN h_dcustomer (INPUT cSrchName:SCREEN-VALUE)
2) Write an internal procedure in the SDO that is not database required with the following code:
DEFINE INPUT PARAMETER NameSearch AS CHARACTER NO-UNDO.
DEFINE VARIABLE cCustRowid AS CHARACTER NO-UNDO.
IF DYNAMIC-FUNCTION('getASDivision':U) = "Client" THEN
DO:
/* This code runs in the SDO client proxy when the SDO is split across
the Appserver. The code has to call itself on the server side part of
the SDO */
RUN NameSearchProc IN DYNAMIC-FUNCTION('getASHandle':U)
(INPUT NameSearch).
/* Reposition browse */
DYNAMIC-FUNCTION('fetchRowIdent':U, INPUT RETURN-VALUE, INPUT "").
RETURN.
END.
ELSE
DO:
/* If this is the server side SDO (getASDivision = "Server") OR the
SDO is running fully on the client (getASDivision = ""), access
the database */
{&DB-REQUIRED-START}
FIND FIRST customer WHERE
customer.NAME BEGINS NameSearch NO-LOCK NO-ERROR.
IF AVAILABLE customer THEN
cCustRowid = STRING(ROWID(customer)).
DYNAMIC-FUNCTION('fetchRowIdent':u, INPUT cCustRowid, INPUT "").
{&DB-REQUIRED-END}
IF DYNAMIC-FUNCTION('getASDivision':U) = "server" THEN
RETURN cCustRowid. /* If server side return rowid */
ELSE
/* If SDO fully on client reposition browse */
DYNAMIC-FUNCTION('fetchRowIdent':u,
INPUT cCustRowid, INPUT "").
END.
END .PROCEDURE.
This code runs itself on the AppServer if it is running on the client side of the SDO. The server side portion of the internal procedure runs the section of code that requires a database connection to find the customer and returns the ROWID to the client side portion of the procedure. This then invokes fetchRowIdent with the ROWID passed back to it to reposition to the correct record.
There is also a section of code in the procedure that runs if the code is not split between the client and an AppServer. This also requires a database to find the record and then it invokes fetchRowIdent..