1 Context:
In this example, we will write our own ABL server logic to enhance the data fetched through an ABL datasource. We will populate the customer datasource âCommentsâ field with the number of orders, the number of shipped orders and the balance of each customer in part.
2 Step by step guide:
- For this task we will use the screen we used for the Frontend button again. Please use your copy of âTrainingDay5_OrderOverviewâ
- In your ProCode Workspace create a new folder
src/backend/Training/
- Create a new file in that folder
src/backend/Training/CustomerEventHandler.cls
- Start typing âb1-datasourceEventhandlerâ and select the template, then save your code by pressing âCTRL+ Sâ
- Navigate back to your Low-Code Workspace and go to âIntegrateâ -> âDatasourcesâ and select the button âDataset-Definitonâ in the toolbar
- Search for the âData Source Objectâ -> âCustomerDSOâ and click on âGenerate Definitionâ
- Copy the âDataset Definitionâ
- Navigate back to your Pro-Code Workspace and create a new file in your newly created folder
src/backend/Training/
and call itdsCustomer.i
and paste your copied âDataset Definitionâ in there, then press âCTRL + Sâ - Include the dsCustomer.i in the class:
CLASS Training.CustomerEventHandler
INHERITS Akioma.Swat.OERA.Dynamic.BaseServerEventHandler:
{ <YourFolder>/dsCustomer.i &ACCESS="PRIVATE" }
- Insert the term âdsDataâ in the dataset
CONSTRUCTOR CustomerEventHandler():
SUPER(DATASET dsData :HANDLE).
THIS-OBJECT:TriggerOnBeforeSave = TRUE.
THIS-OBJECT:TriggerOnAfterFetch = TRUE.
END CONSTRUCTOR.
- Write the following code for your method:
METHOD PROTECTED OVERRIDE VOID OnAfterFetch():
  DEF VAR iCount AS INT NO-UNDO.
DEF VAR iNumShipped AS INT NO-UNDO.
/* go through every CustTable record read from the DB */
FOR EACH eCustomer:
ASSIGN iCount = 0 iNumShipped = 0.
// for each fetched Customer, go through all contacts in the DB
FOR EACH sportsdb.order WHERE sportsdb.order.custNum = eCustomer.custNum NO-LOCK:
iCount = iCount + 1.
IF sportsdb.order.orderStatus = "Shipped" THEN ASSIGN iNumShipped = iNumShipped + 1.
END.
ASSIGN eCustomer.Comments = SUBSTITUTE("Customer has &2 orders, &3 shipped. Balance is $ &4", eCustomer.CustNum, STRING(iCount, "99"), STRING(iNumShipped, "99"), eCustomer.Balance).
END.Â
END METHOD.
- Now press âCTRL + Sâ and execute a âb1 trimâ in the terminal -> This will restart the âPASOEâ without loosing your current session
- Now go back to your Low-Code Workspace and navigate to âIntegrateâ -> âDatasourcesâ
- Search for the âCustomerDSOâ and open the designer for it
- Search for the attribute âServerEventHandlerâ in the âAttributesâ panel and fill in the value ->
Training.CustomerEventHandler
, then select âSaveâ - Navigate to âDesignâ -> âScreensâ and launch your screen to see the result
Full Code Example:
BLOCK-LEVEL ON ERROR UNDO, THROW.
CLASS Training.CustomerEventHandler
INHERITS Akioma.Swat.OERA.Dynamic.BaseServerEventHandler:
{ Training/dsCustomer.i &ACCESS="PRIVATE" }
CONSTRUCTOR CustomerEventHandler():
SUPER(DATASET dsData:HANDLE).
THIS-OBJECT:TriggerOnBeforeSave = TRUE.
THIS-OBJECT:TriggerOnAfterFetch = TRUE.
END CONSTRUCTOR.
METHOD PROTECTED OVERRIDE VOID OnBeforeSave():
// enter before save code here
END METHOD.
METHOD PROTECTED OVERRIDE VOID OnAfterFetch():
DEF VAR iCount AS INT NO-UNDO.
DEF VAR iNumShipped AS INT NO-UNDO.
/* go through every CustTable record read from the DB */
FOR EACH eCustomer:
ASSIGN iCount = 0 iNumShipped = 0.
// for each fetched Customer, go through all contacts in the DB
FOR EACH sportsdb.order WHERE sportsdb.order.custNum = eCustomer.custNum NO-LOCK:
iCount = iCount + 1.
IF sportsdb.order.orderStatus = "Shipped" THEN ASSIGN iNumShipped = iNumShipped + 1.
END.
ASSIGN eCustomer.Comments = SUBSTITUTE("Customer has &2 orders, &3 shipped. Balance is $ &4", eCustomer.CustNum, STRING(iCount, "99"), STRING(iNumShipped, "99"), eCustomer.Balance).
END.
END METHOD.
END CLASS.
3 Explanation:
Every time data is retrieved, our defined event handler is called and our defined logic is executed. This demonstrates how easy it is to integrate and use custom code in the backend. The message gets generated in the defined field with every fetch.