Docs‎ > ‎CA Live API Creator‎ > ‎Rules‎ > ‎

Logic Events

Event Firing

Events fire at pre-determined times during logic execution, depending on the Event Type. This section describes how these interact with other logic. For important background, please see Logic Execution.

  • Early Events

Early Events fire before your logic executes. The row data has not been subjected to formulas and other derivations. You can change the row, and the changes will naturally be subjected to validations, other chained logic, and saved.

  • Events

These events fire after row logic is completed. The row data reflects all derivation results.
You may alter the row, but you must use logicContext.save() to ensure that required logic is executed.

  • Commit Events

These events fire after all row logic is complete, for all the rows in the transaction. The rows reflect all the logic processing.
You may not change the rows at this point.

Event Background: Rules vs. Events

Events are a complement to the other, declarative forms of rules.  Effective use of API Creator requires a good understanding of when to use rules vs. events:
  • Spreadsheet-like Rules should be your first choice, since they will dramatically reduce the amount of code you need to write.  See the example below.

  • Events provide the unlimited flexibility to need to address issues not addressed by rules.
Using rules requires you transition to "think spreadsheet".  It's important to understand this before you build your events, as explained in the sub-section below.


Think Spreadsheet

Here's a common example - let's assume you need a sum (or count) of child rows for a parent, e.g., a sum of unpaid order amounts.  Events are a very familiar concept, so experienced programmers will instantly envision the following code, perhaps as part of the Use Case "Add Order", to adjust sums and counts:

Define Order event MaintainCount as
    if (logicContext.initialVerb == 'INSERT' && row.isPaid == false) {  
// row is the order
        customer = row.customer;                                        // parent accessor
        customer.balance += row.amountTotal;
        logicContext.update(customer);
    }

Don't do it!

Looks pretty easy (nice to have the role accessors, persistence).  But looks are deceiving.

Because shortly, you'll need to consider other Use Cases:
  1. Delete Order: you'll need to decrement the count - if the order isPaid
  2. Change Order.isPaid: you'll watch for such a change, and if you detect it, adjust the sum by amountTotal
  3. Change Order.amountTotal: you'll watch for such a change, and if you detect it, adjust the sum by the difference
  4. Reassign Order: often overlooked - you will need to reduce the old customers' balance, increment the new one, only if the order isPaid
By the time you are done with all these cases, you will have well over a page of code.  And it just gets more complicated if the qualification condition or summed field (amountTotal) is itself derived, perhaps from still another table.

All you really need to do is define a sum or count, and all of the boilerplate code to address the cases above is handled - automatically, without error.  Sums and counts operate just like spreadsheets:

  Spreadsheet   Reactive Logic Notes
 User Define cell formula

Cell A =
    Sum(ColumnB)
 Define Database column

Customer.balance =
      sum(orders.amountTotal where paid = false)
    
 System Watch for changes
  • ColumnB changes
  • ColumnB new rows
  • ColumnB deleted rows
 Watch for changes
  • amountTotal changes
  • paid changes
  • Foreign Key changes (Orders.CustomerName)
  • Inserted Orders
  • Deleted Orders
 
  Reacts to changes
  • Adjust CellA
 Reacts to changes
  • Adjust Customer.balance (SQL and transaction management)
 




Using Events

Events are JavaScript code business logic, providing access to external / re-usable functions.  This is, of course, server-side JavaScript (via Rhino).

You can supply JavaScript table event handlers.  The Logic Engine invokes these on every update, providing key contextual information including:
  • row - this object has attributes for every column, so you can refer to a Order's row.amount_total.  It also provides role accessors, so you can refer to an Orders' row.customer.balance, or obtain a collection of row.lineitems (a collection of lineitem rows).  Rows also provide persistence to read/alter data.

  • oldRow - attributes for the pre-updated version of the row, so you can detect changes.

  • LogicContext - provides many services, such verb (insert, update or delete), services to read and write data (including logic enforcement), create new objects, event logging, etc.

  • logic.sys - system methods, including InsertIntoFrom (auditing and deep copy), Allocation and findWhere (collection filtering).

Events promote quality

Events are a key architectural element, providing:
  • re-use: table events are re-used over all Resources built on that table.  When Resource updates are received, they are de-aliased onto the underlying Base Table objects.

  • encapsulation: you do not need to explicitly invoke your event logic - it is automatically invoked by the system as updated requests are processed.

You can specify when the event is fired: early (before per-row logic), normal (after per-row logic), or commit (after all rows are processed).

Examples




A typical example is an auditing event.  Note the use of the current/old bean in making your logic conditional:

if (row.amount_total != oldRow.amount_total) 
    SysLogic.insertChildFrom("purchaseorder_audit", logicContext);


Like all JavaScript rules, an event always has access to the standard variables including row,  oldRow and logicContext.

Event Context

You events are passed important contextual variables, such as row, oldRow, and logicContext.  As illustrated in this example, the system pre-supplies methods, identified with SysLogic. - see System Methods.

You can also invoke JavaScript methods, including systems supplied ones.  See the reference for a list of these.

Database validation depends on your validation logic, so the system must ensure this is executed after any changes you make.  This applies to events.  So, you must touch the object as described here.


Guidelines

Be aware of the following:

Events fire only once per transaction

Update logic can be executed multiple times.  However, associated events fire only once.