Consultor Eletrônico



Kbase 18563: Running SmartDataObject Internal Procedures on AppServer
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   3/24/2008
Status: Verified

GOAL:

Running SmartDataObject Internal Procedures on AppServer

GOAL:

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.

FACT(s) (Environment):

Progress 9.x
OpenEdge 10.x
All Supported Operating Systems

FIX:

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 receive the following error:


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 within the DB-REQUIRED-START and DB-REQUIRED-END preprocessors.

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' IN h_dcustomer, STRING(ROWID(Customer)), "").
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 (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.
DEFINE VARIABLE cCustRowid AS CHARACTER NO-UNDO.

IF DYNAMIC-FUNCTION('getASDivision') = "Client" THEN
DO:
/* running same procedure on the server side of the SDO */

RUN NameSearchProc
IN DYNAMIC-FUNCTION('getASHandle') (NameSearch).

/* fetchRowIdent must be performed on the client after get */
/* the rowid from the server side run */

DYNAMIC-FUNCTION('fetchRowIdent', RETURN-VALUE, "").
RETURN.
END.
ELSE
IF DYNAMIC-FUNCTION('getASDivision') <> "Server" THEN
DO:
{&DB-REQUIRED-START}
FIND FIRST Customer
WHERE Customer.Name BEGINS NameSearch NO-LOCK NO-ERROR.
IF AVAILABLE(Customer) THEN
ASSIGN cCustRowid = STRING(ROWID(Customer)).
DYNAMIC-FUNCTION('fetchRowIdent', cCustRowid, "").
{&DB-REQUIRED-END}
END.

. /* portion of code running on the server side of the SDO */

{&DB-REQUIRED-START}
FIND FIRST Customer
WHERE Customer.Name BEGINS NameSearch NO-LOCK NO-ERROR.
IF AVAILABLE(Customer) THEN
ASSIGN cCustRowid = STRING(ROWID(Customer)).
{&DB-REQUIRED-END}

RETURN cCustRowid.

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..