Try OpenEdge Now
skip to main content
OpenEdge 11.6.3 New Information : Data Object Services : Business Entity updates : Operation-level annotation for "count" functions
 
Operation-level annotation for "count" functions
The topic, "Updating Business Entities for access by Telerik DataSources and Rollbase external objects," in the "Data Object Services" chapter of OpenEdge Development: Web Services documents how to code and annotate a Business Entity routine (in this case, a class method) that implements an Invoke operation that serves as a "count" function in the client app. This function returns the total number of records in the server result set when the JSDO dialect of the Kendo UI DataSource calls the corresponding Data Object resource Read operation to return a page of records (with server paging enabled).
This is a fragment of the sample Business Entity code in the above-mentioned topic that includes the sample ABL method for this Invoke operation:
@program FILE(name="Customer.cls", module="AppServer").
@openapi.openedge.export FILE(type="REST", executionMode="singleton", useReturnValue="false", writeDataSetBeforeImage="false").
@progress.service.resource FILE(name="Customer", URI="/Customer", schemaName="dsCustomer", schemaFile="Customer/AppServer/customer.i").

USING Progress.Lang.*.

USING OpenEdge.BusinessLogic.BusinessEntity.
USING Progress.Json.ObjectModel.*.

BLOCK-LEVEL ON ERROR UNDO, THROW.

CLASS Customer INHERITS BusinessEntity:

{"customer.i"}

. . .

@openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
@progress.service.resourceMapping(type="REST", operation="invoke",
URI="/count?filter=~{filter~}",
alias="", mediaType="application/json").
METHOD PUBLIC VOID count( INPUT filter AS CHARACTER, OUTPUT numRecs AS INTEGER):
DEFINE VARIABLE jsonParser AS ObjectModelParser NO-UNDO.
DEFINE VARIABLE jsonObject AS JsonObject NO-UNDO.
DEFINE VARIABLE ablFilter AS CHARACTER NO-UNDO.
DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO.
DEFINE VARIABLE qh AS HANDLE NO-UNDO.

IF filter BEGINS "WHERE " THEN
cWhere = filter.
ELSE IF filter BEGINS "~{" THEN
DO:
jsonParser = NEW ObjectModelParser().
jsonObject = CAST(jsonParser:Parse(filter), jsonObject).
ablFilter = jsonObject:GetCharacter("ablFilter") NO-ERROR.
cWhere = "WHERE " + ablFilter.
END.
ELSE IF filter NE "" THEN
DO:
/* Use filter as WHERE clause */
cWhere = "WHERE " + filter.
END.

CREATE QUERY qh.
qh:SET-BUFFERS(BUFFER Customer:HANDLE).
qh:QUERY-PREPARE("PRESELECT EACH Customer " + cWhere).
qh:QUERY-OPEN ().
numRecs = qh:NUM-RESULTS.

END METHOD.

END CLASS.

When you implement this "count" function routine as currently described in OpenEdge Development: Web Services, you must also inform the client app developer of the ABL routine name so they can specify it as a property of the Kendo UI DataSource.
In Release 11.6.3 and Progress Data Objects Version 4.3, you can modify the annotations for this Invoke operation in the Business Entity so that the Kendo UI DataSource on the client can identify the name of this "count" function from the Data Service Catalog without the client app developer having to specify it. You do this by annotating the ABL routine as a new Data Object Count operation type as shown in this update of the previous code fragment:
@program FILE(name="Customer.cls", module="AppServer").
@openapi.openedge.export FILE(type="REST", executionMode="singleton", useReturnValue="false", writeDataSetBeforeImage="false").
@progress.service.resource FILE(name="Customer", URI="/Customer", schemaName="dsCustomer", schemaFile="Customer/AppServer/customer.i").

USING Progress.Lang.*.

USING OpenEdge.BusinessLogic.BusinessEntity.
USING Progress.Json.ObjectModel.*.

BLOCK-LEVEL ON ERROR UNDO, THROW.

CLASS Customer INHERITS BusinessEntity:

{"customer.i"}

. . .

@openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
@progress.service.resourceMapping(type="REST", operation="count",
URI="/MyCount?filter=~{filter~}",
alias="", mediaType="application/json").
METHOD PUBLIC VOID MyCount( INPUT filter AS CHARACTER, OUTPUT numRecs AS INTEGER):
DEFINE VARIABLE jsonParser AS ObjectModelParser NO-UNDO.
DEFINE VARIABLE jsonObject AS JsonObject NO-UNDO.
DEFINE VARIABLE ablFilter AS CHARACTER NO-UNDO.
DEFINE VARIABLE cWhere AS CHARACTER NO-UNDO.
DEFINE VARIABLE qh AS HANDLE NO-UNDO.

IF filter BEGINS "WHERE " THEN
cWhere = filter.
ELSE IF filter BEGINS "~{" THEN
DO:
jsonParser = NEW ObjectModelParser().
jsonObject = CAST(jsonParser:Parse(filter), jsonObject).
ablFilter = jsonObject:GetCharacter("ablFilter") NO-ERROR.
cWhere = "WHERE " + ablFilter.
END.
ELSE IF filter NE "" THEN
DO:
/* Use filter as WHERE clause */
cWhere = "WHERE " + filter.
END.

CREATE QUERY qh.
qh:SET-BUFFERS(BUFFER Customer:HANDLE).
qh:QUERY-PREPARE("PRESELECT EACH Customer " + cWhere).
qh:QUERY-OPEN ().
numRecs = qh:NUM-RESULTS.

END METHOD.

END CLASS.

In this updated sample code fragment, the only differences are the ABL method name, MyCount, and the new operation annotation, operation="count".
Aside from automatically informing the Kendo UI DataSource on the client of the "count" function name, annotating this new Count operation works exactly like an Invoke operation—that is, you can call the Count operation function from the client app in exactly the same way as you call an Invoke operation function. However, unlike an Invoke operation, you can only annotate a single ABL routine in the Business Entity as a Count operation.
Note: Although the JSDO dialect of the Kendo UI DataSource on the client can automatically identify the name of the "count" function for a Data Object resource when you annotate the corresponding ABL routine as a Count operation of the resource, you must also inform the developer of any web app that they build using the Kendo UI Builder with access to this Data Object resource of this "count" function name. They must continue to specify this name when they define the corresponding Kendo UI Builder data source for the app (see Supporting server processing for Kendo UI Builder apps).