In some scenarios it is useful to invoke the rule engine directly from your custom APEX code.
Applying a business policy involves a callout to our server. Due to Salesforce restrictions, it is not possible to make a callout synchronously in all contexts (such as from a trigger) -- but the policy can still be applied asynchronously.
Contexts for invoking a business policy include:
- Synchronous invocation
Typically from a Visualforce or Lightning controller, or from a future method - Trigger
- Scheduled APEX
- Batch APEX
Each is described in more detail below
Apply a policy synchronously
Typically, this would be from a Visualforce or Lightning controller, a Queueable or a future method.
To apply a business policy to a single record, your code would look like this:
sObjectType objType =...; // Object to which your policy applies String policyName = .... ;// Name of your policy DecsOnD.PolicyInvocationContext ctxt = new DecsOnD.PolicyInvocationContext(objType, policyName); ID recordId = ...; // ID of the record to process DecsOnD.ApplyPolicyHelper helper = DecsOnD.ApplyPolicyHelper.createHelper(ctxt, recordId); // Alternatively, if you already have the record loaded, use: // sObject rec = ...; // DecsOnD.ApplyPolicyHelper helper = DecsOnD.ApplyPolicyHelper.createHelper(ctxt, rec); // NOTE: in this scenario the record must be loaded with all fields accessed by the policy // Prepare and send request to the Decisions on Demand server DecsOnD.DecisionRequest req = helper.prepareDecisionRequest(); DecsOnD.DecisionResponse response = helper.executeDecisionRequest(req); if (response.status != 'OK') { List<String> errors = response.getErrorMessages(); // Handle error or return messages. } else { List<DecsOnD.PolicyActionRecord> actionRecs = helper.prepareActions(response); List<String> msgs = helper.applyActions(actionRecs); // Optionally, create an execution record helper.createExecutionRecord(response, actionRecs); }
To apply a business policy to multiple records in one operation, use the following:
sObjectType objType =...; // Object to which your policy applies String policyName = .... ;// Name of your policy DecsOnD.PolicyInvocationContext ctxt = new DecsOnD.PolicyInvocationContext(objType, policyName); List<sObject> records = ....; // List of records -- must be loaded with all fields accessed by the policy List<DecsOnD.ApplyPolicyHelper> helpers = DecsOnD.ApplyPolicyHelper.applyPolicyBatch(ctxt, records); // Optionally, create execution records DecsOnD.ApplyPolicyHelper.createBatchExecutionRecords(helpers);
Note that this code will make a callout, so:
- It cannot be called from a trigger (see related Salesforce Knowledge Article) or test method
- It cannot be called after any DML statements (see related Salesforce Knowledge Article)
Apply a policy from a trigger
Please refer to the support article entitled How do I set up a trigger to call a business policy?
Apply a policy from a scheduled job or Batch APEX
This code shows the execute method of a simple scheduled job to apply a policy to a set of records defined by an (optional) SOQL where clause.
public void execute(SchedulableContext sc) { sObjectType objType =...; // Object to which your policy applies String policyName = .... ;// Name of your policy String whereClause = ....; // SOQL where clause selecting records to be processed boolean createExecutionRecord = ....; // whether or not to create an execution record DecsOnD.PolicyInvocationContext ctxt = new DecsOnD.PolicyInvocationContext(objType, policyName); DecsOnD.BatchExecutePolicy bep = new DecsOnD.BatchExecutePolicy(ctxt, whereClause); bep.createExecutionRecord = createExecutionRecord; ID batchId = Database.executebatch(bep); }
Notes:
- DecsOnD.BatchExecutePolicy will throw an exception if there is any failure during execution of the business rules, but some records may still have been processed successfully.
The exception message will contain details. - You can create a batch for a specific set of records using the following constructor
List<sObject> scope = ...; DecsOnD.BatchExecutePolicy bep = new DecsOnD.BatchExecutePolicy(ctxt, scope);
Batch APEX
If you are updating records in a batch, and then wish to apply a business policy to these same records, you will need to start a second batch, because it is not possible to directly apply the policy to records that have been modified in the same APEX transaction. See this Salesforce Knowledge Article for details.
To create a nested batch, use the same code as that shown above for a scheduled job, but place it in the finish method of the first batch.