Docs‎ > ‎Quick Reference‎ > ‎

LogicContext object

When writing a rule in JavaScript, you can assume that there is an object named logicContext, which has the following properties and behaviors.

For detailed API documentation, see LogicContextI in API Docs.

Logic context makes visible key aspects of Logic Execution.

verb

The verb tells you what the current logic iteration is trying to do: insert, update, or delete. This is distinct from the initial verb (see below) because the current logic iteration may have been kicked off by a rule.

For instance, an inserted row (such as an Order) might be updated later in the transaction by Item logic. For the Order, the verb is INSERT initially, then UPDATE as the Items are processed. But initialVerb remains INSERT.

if (logicContext.verb == 'UPDATE')
    log.debug('We are updating');

Initial verb

Indicates the verb initially executed on this row. Consider inserting an Order and several Items. The item logic updates the Order, but the Order can determine that it was initially inserted in this transaction. For example, you might want to bypass auditing logic when an Order is inserted.

if (logicContext.initialVerb == 'INSERT')
    log.debug('This started as an Insert transaction');

Logic Nest Level

(For advanced users) Before using this property, ensure you understand complex nested logic. It indicates the depth of the nesting at the present moment.

if (logicContext.logicNestLevel > 0)  // Do something only at the top level of nesting
    return;

Use Case Name

You can make debugging easier by creating a rule that sets the setUseCaseName method. The given name appears in the logs, which can be helpful in understanding the flow of a transaction.

logicContext.setUseCaseName('Insert log record');

User properties

User properties are only set for the duration of the transaction: as soon as the transaction ends, all user properties disappear. The next transaction, even for the same API key, does not see these values.

logicContext.setUserProperty('myFlag', true);
if (logicContext.getUserProperty('myFlag)
    log.debug('myFlag is true');

The value of a user property can be anything.

Important! Use the setUserProperty method with great care. This method can introduce some subtle and non-obvious dependencies between rules. Nevertheless, they can be useful in some scenarios.


Output Messages to the Log

You can output messages to the log:

log.debug('Customer balance is: ' + currentObject.balance);
logicContext.logDebug('Customer balance is: ' + currentObject.balance);

This outputs the given message to the transaction's log, using the User Logic logger. The other variations of this method, logFiner and logFinest, use a lower level of logging.


Objects: updatable

Objects are undatable. This method is distinct from the queryDatabase method.

Interact with Data

An object model is created for each base table when you connect your schema to API Creator to your database. This model is automatically updated (for example, if you change the schema) when you reload your schema.

For more information about base table resources and JavaScript object models, see Object Model.

The term "object" refers to the Java Script objects created as part of the Object Model. In the Logic Demo, Objects exist for customer, purchaseorder, and so forth.  

If you are using Multiple Databases, prefix your table name with the database name (e.g., main:Customer).

Create a New Object

You can create a new object, ready to be inserted, by using the createPersistentBean method:

var newCustomer = logicContext.createPersistentBean("Customer");
newCustomer.name = 'My new customer';
logicContext.insert(newCustomer);

Get an Object by Primary Key

You can retrieve an existing object by its primary key with the getBeanByPrimaryKey method:

var customer = logicContext.getBeanByPrimaryKey("Customer", "123");

The second argument must be a string. The argument is converted to the proper type as needed. If the primary key for the given table is a composite key, the string should contain all the values separated by a tilde (~) in the database order, with double-tilde to quote the tilde itself:

var order = logicContext.getBeanByPrimaryKey("MyTable", "456~abc");

getBeanByPrimaryKey() expects to find a valid record.  It does not return a null row when no row is found.  If you are attempting to determine whether a row actually exists, use:

var customer = logicContext.getBeanByUniqueAttributes("demo:customer", ["id"], [123]);

where the arguments are:
  • The Object Name
  • The Attributes you are selecting against
  • The Values used for the query
This returns single bean if found, null if not found, or throw an exception if not unique. Use the following API.

Get a Set of Objects

You can retrieve a set of objects using a SQL where clause with the getRowsByQuery method:

var rows = logicContext.getRowsByQuery("product",
                        "select * from product where name <> 'Drill'");

for (var i = 0; i <= rows.length; i++)
   log.debug('Found product:' + rows[i].name);

Access Related Parent/Child Data

You can also access related parent / child data by way of their relationships. Consider the following code snippet from the Bill of Materials Explosion:

The key requirement is to populate the SubItems for a kit-based Lineitem (see the database structure), by copying the ProductBillofMaterials to the subItems.  You can do this with the following explodeBillofMaterials Event rule on Lineitem:

 if (logicContext.verb == "INSERT" && row.product.count_components > 0)  {

     SysLogic.insertChildrenFrom("lineitems", row.product.components, logicContext); 

 }


The remaining logic (four rules) is to properly arrange for quantities (i.e., if you buy 2 planes, you need 8 engines).  The Bill Of Materials Explosion example is an advanced example used in the Training.

In this example:
  • row.product.count_components uses a parent accessor - given a lineitem, it access the related product, and returns the value of the attribute count_components.

  • row.product.components is a child accessor - it accesses the list of components for a lineitem's product.

Insert an Object

You can insert a new object (presumably created with createPersistentBean) using the insert method; see createPersistentBean for an example.
 
  var newPurchaseorder_audit = logicContext.createPersistentBean("purchaseorder_audit");
  newPurchaseorder_audit.amount_total = oldRow.amount_total;  // set attributes from old values
  newPurchaseorder_audit.paid = oldRow.paid;
  newPurchaseorder_audit.customer_name = oldRow.customer_name;
  newPurchaseorder_audit.order_number = oldRow.order_number;  // set the foreign key
  logicContext.insert(newPurchaseorder_audit);    

Update an Object

You can update an object in an action by following these steps:
  1. Call the touch method.
  2. Change any column in the row.
  3. Call the update method.

var customer = logicContext.getBeanByPrimaryKey("customer", "123");
logicContext.touch(customer); // IMPORTANT!
customer.name = 'Updated customer';
logicContext.update(customer);

Set up the Old Values

Touch is required to set up the old values, required for oldRow and for optimistic locking. You must invoke it:
  • If you read a row and then wish to update / delete it (see the example above)
  • In an Event, if you change the row and need to update it again (to re-run the rules on changes to the row made in the event)
Note: This does not apply to row, only to objects that you retrieve on your own.

Delete an Object

You can delete an object with the delete method:

var customer = logicContext.getBeanByPrimaryKey("customer", "123");
logicContext.delete(customer);

Retrieve Data from an Arbitrary Query

You can issue an arbitrary SQL query, within the context of the transaction, using the queryDatabase method. You can use JDBC ? syntax for parameterized queries:

// Query the database and log the results (for example) to the API Creator Logs using this method
var result = SysLogic.queryDatabase('demo', 'select * from customer where balance > ?', [10]);
for (var i = 0; i < result.length; ++i) {
    var s = '';
    for (var id in result[i]) {
          s += ', ' + id + '=' + result[i][id];
    }
    log.debug(s);
}

Interact with Data using REST

The services above use the server's database connection and jdbc for sql access.  You can also interact with data using REST:
  • You can invoke RESTful services (API Creator or others), as described here.

  • You can materialize a JSON string from your API Creator rows, as described here, perhaps as a payload to send to a remote system.
REST vs. Object access
In most cases, use the object services described above:
  • REST results do not include role accessors. They are static rows.

  • REST results are not persist-able using the (more convenient) insert, update and delete APIs noted above.

  • REST results always trigger database access. In many cases, object accessors find the desired data in memory, and you are assured of seeing other updates in the current transaction.

rowToJSON

If you are logging, you can print rows to the log using normal logging:

log.debug("Here is my row: " + row);

You can also convert a row to a JSON structure with appropriate datatypes that can be passed to other persistent document storage systems, like this:

log.debug("JSON for object is : " + logicContext.rowToJSON(row));

The console output is:

{
"location_ident": 1,
"amount": 1.06,
"budget_date": null,
"ident": 9,
"city_ident": 1
}