Skip to content

Integrations

The Integration record defines a specific integration.

Integrations are defined as a sequence of Steps. A Step is used to perform some type of action, such as:

  • sending an HTTP request
  • database insert, update, or query
  • scheduling an event
  • data aggregation

When an Integration is triggered, all Steps are evaluated, and Transactions are sequentially created to execute the Step logic. When a Transaction has been completed, a check occurs to see if there is another Step to run. If another Step is identified, a new Transaction will be created to execute the Step logic.

This will continue until the final Step of the Integration has been completed.

Data model

Field labelField nameDescription
NamenameName of the Integration.
Run synchronouslysynchronousIf true, this Integration will not be triggered automatically when the condition is matched. It can instead be triggered using the utilities for running synchronous integrations.
Applicationsys_scopeThe scope of the Integration.
ActiveactiveSpecifies if the Integration is active.
AdvancedadvancedAdvanced is used to indicate that the advanced condition should be evaluated. It also makes the advanced condition field visible on the form view.
TabletableThe table that is used to trigger the Integration.
OperationsoperationsThe operations that are used to trigger the Integration.
ConditionsconditionsThe conditions that are used to trigger the Integration.
Advanced conditionadvanced_conditionScript field that is used to configure an advanced condition.

TIP

If multiple Integrations exist on the same table, consider having the trigger in a separate scope so it can be reused for all Integrations. Otherwise, the trigger will be bound to one of the Integrations, and all other Integrations will have a dependency on the Integration that owns the trigger.

Triggers

A trigger is a piece of code that calls TransactionUtils.checkIntegrationTriggersAsync() or TransactionUtils.checkIntegrationTriggers(). Usually this code will live inside a Business Rule but it can be defined using other solutions as well. In this documentation we will use Business Rules as an example when discussing Triggers.

In more complex scenarios (such as instances using domain separation), or if you want more direct control, triggers should be created manually.

Disable the Business Rule called Manage integration triggers to stop the automatic trigger management.

All triggers are configured almost identically.

FieldValue
nameim_trigger_<operation>
collectiontable that the integration runs on.
whenmost often async_always, but can be configured for synchronous use as well.
filter_conditionsys_updated_by!=system^EQ
action_insertcreate one trigger for each operation the integration runs on. If the integration should run on insert and update, create one trigger for insert and one for update.
action_updatecreate one trigger for each operation the integration runs on. If the integration should run on insert and update, create one trigger for insert and one for update.
action_deletecreate one trigger for each operation the integration runs on. If the integration should run on insert and update, create one trigger for insert and one for update.
advancedtrue
scriptsee example below
sys_scopeselect which scope is appropriate according to your setup.
sys_domainThe domain should match the integration domain.

INFO

Creating separate Business Rules for each operation allows us to pass the name of the operation to TransactionUtils.checkIntegrationTriggersAsync() when using async Business Rules. We have to do this because current.operation is not available in async Business Rules, and the operation is used to match the trigger of the Integration.

Async trigger

js
(function executeRule(current, previous /*null when async*/) {
  const transactionUtils = x_devol_intgr_mgr.TransactionUtils;
  const transactionManager = x_devol_intgr_mgr.TransactionManager;

  transactionUtils
    .checkIntegrationTriggersAsync(current, "update")
    .integrationIds.forEach((id) => transactionManager.createTransaction(current, id, "update"));
})(current, previous);
(function executeRule(current, previous /*null when async*/) {
  const transactionUtils = x_devol_intgr_mgr.TransactionUtils;
  const transactionManager = x_devol_intgr_mgr.TransactionManager;

  transactionUtils
    .checkIntegrationTriggersAsync(current, "update")
    .integrationIds.forEach((id) => transactionManager.createTransaction(current, id, "update"));
})(current, previous);

Synchronous trigger passing initial inputs

It is possible to run the trigger synchronously, but still have the Integration execute asynchronously. This is useful when you need to get access to the fields that changed on a record when an update happened.

In this example we generate a list of the updated fields synchronously, and pass that list to the Integration that will execute asynchronously. The list of updated fields will be available in the inputs of the first Step.

js
(function executeRule(current, previous /*null when async*/) {
  const transactionUtils = x_devol_intgr_mgr.TransactionUtils;
  const transactionManager = x_devol_intgr_mgr.TransactionManager;
  const updatedFields = global.GlobalBridgeUtils.getUpdatedFields(current);

  transactionUtils
    .checkIntegrationTriggersAsync(current, "update")
    .integrationIds.forEach((id) =>
      transactionManager.createTransaction(current, id, "update", { updatedFields })
    );
})(current, previous);
(function executeRule(current, previous /*null when async*/) {
  const transactionUtils = x_devol_intgr_mgr.TransactionUtils;
  const transactionManager = x_devol_intgr_mgr.TransactionManager;
  const updatedFields = global.GlobalBridgeUtils.getUpdatedFields(current);

  transactionUtils
    .checkIntegrationTriggersAsync(current, "update")
    .integrationIds.forEach((id) =>
      transactionManager.createTransaction(current, id, "update", { updatedFields })
    );
})(current, previous);

Synchronous Integrations

Integration Manager contains a utilty that can be used when an Integration needs to run synchronously.

A common use case for this would be a Scripted REST API that needs to send synchronous responses.

js
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    // create an inbound http request that will be used as the Integration's initRecord
    var gr = new GlideRecord("x_devol_intgr_mgr_inbound_http_request");
    gr.setValue("headers", JSON.stringify(request.headers));
    gr.setValue("body", JSON.stringify(request.body.data));
    gr.setValue("query", JSON.stringify(request.queryParams));
    gr.setValue("uri", request.uri);
    gr.setValue("url", request.url);
    gr.setValue("method", "post");

    gr.insert();
    // define the configuration for the Integration
    var integrationId = "integration_sys_id_goes_here"; // replace the placeholder with the integration's sys_id 
    var operation = "insert"; // which operation to pass to the integration
    var initialInputs = {}; // this can be used to provide some initial data that will be available as inputs for the first step
    // run the integration synchronously
    var result = x_devol_intgr_mgr.TransactionManager.runIntegration(gr, integrationId, operation, initialInputs); // this will return the outputs of the last step in the integration
    response.setStatus(201);
    response.setBody(result);
})(request, response);
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    // create an inbound http request that will be used as the Integration's initRecord
    var gr = new GlideRecord("x_devol_intgr_mgr_inbound_http_request");
    gr.setValue("headers", JSON.stringify(request.headers));
    gr.setValue("body", JSON.stringify(request.body.data));
    gr.setValue("query", JSON.stringify(request.queryParams));
    gr.setValue("uri", request.uri);
    gr.setValue("url", request.url);
    gr.setValue("method", "post");

    gr.insert();
    // define the configuration for the Integration
    var integrationId = "integration_sys_id_goes_here"; // replace the placeholder with the integration's sys_id 
    var operation = "insert"; // which operation to pass to the integration
    var initialInputs = {}; // this can be used to provide some initial data that will be available as inputs for the first step
    // run the integration synchronously
    var result = x_devol_intgr_mgr.TransactionManager.runIntegration(gr, integrationId, operation, initialInputs); // this will return the outputs of the last step in the integration
    response.setStatus(201);
    response.setBody(result);
})(request, response);

Configuration

The Run synchronously field on the Integration record should be set to true, this disqualifies the Integration from getting identified by Triggers. Instead, the runIntegration method in TransactionManager will be used to target and execute the Integration, as demonstrated in the example above.