6 Using Triggers

This chapter describes how to use the trigger functionality in Oracle Enterprise Data Quality. This document describes where triggers are installed, how to call them, and how you can use them.

This chapter contains the following topics:

6.1 Overview of the Triggers Functionality

Triggers in Oracle Enterprise Data Quality are scripts (JavaScript or Groovy) that can be called at various trigger points in the EDQ system. There are two types of triggers: predefined triggers and custom triggers.

6.1.1 About Predefined Triggers

Predefined triggers are included with the EDQ installation. They are visible in the Director user interface and can be used in a job configuration to start the job, shut down web services, send email notifications, and run another job from within a job. Director users can set these triggers to run at the following trigger points: the start of a job, the end of a job, or both. You can learn more about predefined triggers in the Director online help system.

6.1.2 About Custom Triggers

Custom triggers can be written by someone skilled in Javascript or Groovy to extend the functionality of EDQ to achieve specific workflow objectives. You can use custom triggers to perform tasks such as:

  • sending an email message

  • sending a JMS message

  • calling a web service

  • writing a file

  • sending a text message

You can run custom triggers at any of the following predefined trigger points:

  • Before running a job phase

  • After running a job phase

  • On making a match decision

  • On making a transition in Case Management

  • When a job completes

Each of these trigger point has a unique path and a set of defined arguments that are passed to the trigger through a special API. For more information, see Section 6.6, "Understanding EDQ Trigger Points."

Custom triggers are described in the rest of this document.

6.2 Required Skills to Use Triggers

Knowledge of Javascript or Groovy is required to create and deploy custom triggers in EDQ.

6.3 Storing Triggers

Custom triggers must be stored in the triggers subdirectory of the EDQ config (configuration) directory. New or updated triggers are loaded automatically without requiring a system restart.

6.4 Configuring Triggers Using the Script Trigger API

You can use the functions of the script API to create your triggers. These functions are defined in the trigger code. Although the examples in this document are JavaScript, the same API is available in Groovy.

The following are descriptions of each function in this API.

getPath()

Returns a string that defines the path that the trigger will handle. Each trigger point has a unique path. Any trigger that matches a given path is executed when the trigger point is reached. For more information about trigger points, see Section 6.6, "Understanding EDQ Trigger Points."

This function is a regular expression. For example, the path /log/com\.datanomic\..* would match any logging path where the logger name contains the string datanomic (in other words, any logger defined in EDQ, the word "datanomic" being another name for EDQ).

run(path, id, env, arg1, arg2 ...)

Executes the trigger. For more information about what is returned by the trigger API for each of these variables, see Section 6.6, "Understanding EDQ Trigger Points."

path

The path of the trigger, for example /runtime/engine/interval/end.

id

The trigger ID. The ID is set when the trigger is configured in the Director user interface. The ID is null for simple triggers.

env

The trigger environment in the form of one or more key/value pairs, for example env.project = project name. The env input is specific to the trigger point. These values are exposed as properties of the env object in the script. Most trigger points will pass in the associated EDQ project ID and project name.

arg

Extra arguments that are specific to the trigger point. For example, the Interval end trigger point returns the following: Task context object, process options, interval number (>= 1), execution statistics.

filter(path, env)

(Optional function) Filters out the trigger before it can be executed. Use this filter to avoid the overhead of executing a trigger that will not be needed. Return true to enable the trigger or false to disable it.

path

The path of the trigger.

env

The trigger environment in the form of one or more key/value pairs. The env input is specific to the trigger point. These values are exposed as properties of the env object in the script. Most trigger points will pass in the associated EDQ project ID and project name. In the following example, the trigger is enabled only if the associated project is named "My project."

function filter(path, env) {
  return env.project == 'My project';
}
getLevel()

(Optional function) Returns the maximum level the trigger will accept. For example, the following statement allows the trigger to accept all levels, regardless of other settings in the trigger system. For more information about setting levels, see Section 6.8, "Setting Trigger Levels."

function getLevel() {
  return Level.SEVERE;
}
getTriggerNames(path, env)

(Optional function) Returns an array of TriggerName objects for display in the Director user interface. For more information, see Section 6.10, "Exposing Triggers in a Job Configuration." Getting trigger names and exposing them in the Director interface is only possible with the job configuration screen.

6.5 Extending the Configuration of Triggers Using Properties Files

You can specify additional configuration for script triggers in properties files. Access to these properties is by means of a predefined object named config, which is available in all triggers. The base directory in EDQ for these properties files is the subdirectory config within the triggers directory. The following are useful methods for the config object.

config.getTriggerConfigFiles(base, pattern)

Returns an array of file objects whose names match a search pattern within a specified directory in the triggers/config directory.

base

The name of a directory within the triggers/config directory.

pattern

A regular expression (regex) that defines the search pattern to match.

config.loadProps(file)

Loads a specified Java properties file and return it as a JavaScript object.

file

The name of the Java properties file.

6.6 Understanding EDQ Trigger Points

This section describes the trigger points within EDQ at which you can call custom triggers.

Log Message

Called whenever a log message is generated in the system.

Component Description
Path /log/loggername
Env null
Arguments java.util.logging.LogRecord

Syslog Message

Called whenever a high-level syslog log message is generated. The source argument is a Java object that contains details of the event source. It can be converted to string for display.

Component Description
Path /syslog
Env env.event = event_name

env.source = event_source_as_string

Arguments event_name, source, message

Process start

Called when a process starts. The arguments are Java objects that contain information on the process configuration.

Component Description
Path /runtime/engine/task/start
Env env.project = project_name

env.projectID = project_ID

env.missionname = job_name

env.processname = process_name

Arguments Task_context_object, process_options

Note:

When specifying the path for starting a task, the trigger script must include addLibrary('runtime') to avoid the trigger script from throwing an error.
Process end

Called when a process stops. The arguments are Java objects that contain information on the process configuration.

Component Description
Path /runtime/engine/task/end
Env env.project = project_name

env.projectID = project_ID

env.missionname = job_name

env.processname = process_name

Arguments Task_context_object, process_options

Note:

When specifying the path for ending a task, the trigger script must include addLibrary('runtime') to avoid the trigger script from throwing an error.
Interval end

Called at the end of a normal process or at the end of each interval of a process that is run in interval mode. Returns statistics on the number of records executed, etc.

Component Description
Path /runtime/engine/interval/end
Env env.project = project_name

env.projectID = project_ID

env.missionname = job_name

env.processname = process_name

Arguments Task_context_object, process_options, interval_number (>= 1), execution_statistics

Before job phase

Called in a job configuration for 'pre phase' execution.

Component Description
Path /missions/phase/pre
Env env.project = project_name

env.projectID = project_ID

env.missionname = job_name

env.processname = process_name

Arguments None

After job phase

Called in a job configuration for 'post phase' execution.

Component Description
Path /missions/phase/post
Env env.project = project_name

env.projectID = project_ID

env.missionname = job_name

env.processname = process_name

Arguments None

On match decision

Called when EDQ must make a decision about a potential match. This is known as a relationship decision trigger. Relationship triggers can include methods that return the relationship and decision data needed to perform matching. This trigger point is specific to Match Review.

Component Description
Path /matchreview/relationship/decision/
Env env.project = project_name
Arguments A list of TriggerInfo methods. Each contains data for one relationship. See Section 6.7 for descriptions of these methods.

When a case is created

Called when a case is created where the case belongs to the respective case source.

Component Description
Path /casemanagement/create/<case source name>
Env env.sourceName = case source name

env.caseType = the type of the case or alert

env.currentState = the current state of the created case

Arguments com.datanomic.director.casemanagement.beans.CaseBean

When a case or alert has transitioned

Called after a case or alert has transitioned into the next logical state corresponding to the respective workflow.

Component Description
Path /casemanagement/transition/<workflow name>/<transition>
Env env.sourceName = case source name

env.caseType = the type of the case, 'case' or 'alert'

env.currentState = the current state of the created case

Arguments com.datanomic.director.casemanagement.beans.CaseBean,java.util.List<com.datanomic.director.casemanagement.beans.CaseHistoryBean>,comment,restrictingPermission

Where comment is entered by the user and restrictingPermission is the permission required to access the comment.


When a case or alert has been updated

Called when a case or alert is updated by a user. This includes assignment, state change, priority change, or performing any other edit.

Component Description
Path /casemanagement/update/<case source name>
Env env.sourceName = case source name

env.caseType = the type of the case, 'case' or 'alert'

env.currentState = the current state of the created case

Arguments com.datanomic.director.casemanagement.beans.CaseBean,java.util.List<com.datanomic.director.casemanagement.beans.CaseHistoryBean>,comment,restrictingPermission

Where comment is entered by the user and restrictingPermission is the permission required to access the comment


When a comment is added for a case or alert

Called when a comment is added for a case or alert.

Component Description
Path /casemanagement/commented/<case source name>
env.sourceName = case source name

Env

env.caseType = the type of the case, 'case' or 'alert'

env.currentState = the current state of the created case

Arguments com.datanomic.director.casemanagement.beans.CaseBean,java.util.List<com.datanomic.director.casemanagement.beans.CaseHistoryBean>,comment,restrictingPermission

Where comment is the user entered comment and restrictingPermission is the permission required to access the comment.


After a system update occurs

Called after a case or alert is updated as part of an escalation or bulk update.

Component Description
Path /casemanagement/systemupdate/<case source name>
Env env.sourceName = case source name

env.caseType = the type of the case, 'case' or 'alert'

env.currentState = the current state of the created case

Arguments com.datanomic.director.casemanagement.beans.CaseBean,java.util.List<com.datanomic.director.casemanagement.beans.CaseHistoryBean>,comment,restrictingPermission

Where comment is the user entered comment and restrictingPermission is the permission required to access the comment.


6.7 Understanding TriggerInfo Methods

This section explains each of the methods that are associated with the TriggerInfo trigger point. These methods are specific to the TriggerInfo trigger point for use in Match Review.

Table 6-1 Methods Associated with the TriggerInfo Trigger Point

Method Data Returned Description

getPreviousMatchStatus()

String

Returns the match status prior to the decision.

getPreviousRealtionshipReviewStatus()

String

Returns the relationship review status prior to the decision.

getRelationshipId()

Integer

Returns the relationship ID.

getRecordId()

Integer

Returns the ID of the first record.

getInputId()

Integer

Returns the ID of the first input.

getRelatedRecordId()

Integer

Returns the ID of the second record.

getRelatedInputId()

Integer

Returns the ID of the second input.

getReviewStatus()

String

Returns the review status of the new relationship.

getMatchStatus()

String

Returns the new match status.

getRuleName()

String

Returns the name of the rule that generated the relationship.

getCommentUser()

String

Returns the user name of the person that made the comment.

getReviewComment()

String

Returns any comment that was made.

getCommentDate()

Date

Returns the date and time that the comment was made (if comment is present).

getReviewedUser()

String

Returns the name of the user who performed the review.

getReviewDate()

Date

Returns the date and time that the review was performed.

SourceAttribute getRecordSourceAttributes()

List

Returns all the source attributes (columns) that make up the first record.

SourceAttribute getRelatedRecordSourceAttributes()

List

Returns all the source attributes (columns) that make up the second record.

getRecordAttributeValue(SourceAttribute sa)

Value

Returns the value of the given source attribute (column) of the first record.

getRelatedRecordAttributeValue(SourceAttribute sa)

Value

Returns the value of the given source attribute (column) of the second record.


6.8 Setting Trigger Levels

Every trigger point has an associated level, which is a java.util.logging.Level value. By default trigger calls with a level lower than INFO are ignored.

One way to modify the level is to create a file named levels.properties in the triggers subdirectory of the config directory. This file can contain both a default level and one or more override levels for individual paths. Example 6-1 sets the default level to FINE and sets the level for the path /runtime/engine/.* to FINER. You can define your own prefix for the pattern and level properties.

Example 6-1 Setting Trigger Levels

default = fine
runtime.pattern = /runtime/engine/.*
runtime.level   = finer

Another way to modify the level is to define a getLevel function in the trigger. See Section 6.4 for a description.

6.9 Using JMS in Triggers

To enable Java Message Service (JMS) within a trigger file, follow these steps.

  1. Load the internal JavaScript JMS library.

    addLibrary("jms");
    
  2. Load properties that define the JMS configuration. These properties are augmented with the JMS settings from the standard realtime.properties file that is shipped in the EDQ configuration directory. The default version of this file defines properties for the open-source ActiveMQ message broker that is bundled with EDQ. At minimum, the trigger should supply a value for the destination property, which names the JMS topic or queue to use.

  3. Create a JMS object.

    var jms = JMS.open(props);
    
  4. Send a text message.

    jms.send(str)
    
  5. Send a JMS map message built from a script object.

    jms.sendMap(jsobj)
    
  6. Create a text message. Properties and header values can be set on the message before transmission.

    var msg = jms.createTextMessage(str)
    
  7. Create a map message. Properties and header values can be set on the message before transmission.

    var msg = jms.createMapMessage(jsobj)
    
  8. Send a message that was created by one of the two preceding methods.

    jms.sendMessage(msg)
    

6.10 Exposing Triggers in a Job Configuration

Triggers are selected for use in a job when configuring a job phase in Director. They can be set to run before or after a job phase. To make triggers available for selection on the configuration screen, each trigger must be able to return a list of names. This allows one trigger to perform multiple tasks as needed.

A trigger name has the following components:

  • an internal ID that is passed to the trigger run function. See Section 6.4 for a description of this function.

  • a visible label

  • a group name

Trigger names with the same group are shown as a single node in the job configuration screen.

To create a new trigger name:

var n1 = new TriggerName(id, label)
n1.group = "My group";

To return trigger names from a trigger:

To return trigger names, use the getTriggerNames function as shown in this example.

function getTriggerNames(path, env) {
  var n1 = new TriggerName(id1, label1);
  var n2 = new TriggerName(id2, label2);
  ...
  n1.group = "My group";
  n2.group = "My group";
  ...
  return [n1, n2 ...]
}

See Section 6.4 for more information about getTriggerNames.

6.11 Trigger Examples

The following are examples of how you can use custom triggers.

Note:

The examples in this document are JavaScript, but the same API is available in Groovy.
Example 1   Use a Trigger to Send Log Messages Via JMS

In this example, the logging library imports a logging object that can be used to format and output the message. The JMS properties file is loaded from triggers/config/jms/jms.properties in the EDQ configuration directory.

// Test trigger for task running with JMS
addLibrary("logging");
addLibrary("jms");
 
function getPath() {
  return "/log/com\.datanomic\..*";
}
function run(path, id, env, logrecord) {
 
  var pfiles = config.getTriggerConfigFiles("jms", 
                           "jms\\.properties");
 
  if (pfiles.length > 0) {
    var props = config.loadProps(pfiles[0]);
 
    var jms = JMS.open(props);
    var msg = logging.format(logrecord);
    var len = msg.length;

// Remove trailing newlines
 
    while (len > 0) {
      var c = msg.charAt(len - 1);
 
      if (c != '\n' && c != '\r') {
        break;
      }
 
      len--;
    }

    jms.send(msg.substring(0, len));
    jms.close();
  }
}
Example 2   Use a Trigger to Send Syslog Messages Via JMS

In this example, the special id directive on the first line (#! id : syslog) defines the internal ID of the trigger. If there is more than one trigger definition with the same ID, the later one replaces the former one. In a standard EDQ install, there is a predefined syslog trigger that logs messages through the standard logging API. Adding the id directive in this example causes the JMS syslog trigger to replace the predefined trigger.

#! id : syslog
 
// Test trigger for task running with JMS
 
addLibrary("logging");
addLibrary("jms");
 
function getPath() {
  return "/syslog";
}
 
function getLevel() {
  return Level.SEVERE;
}

function run(path, id, env, level, event, source, message) {
 
  var pfiles = config.getTriggerConfigFiles("jms", 
                "jms\\.properties");
  var props  = null;
 
  if (pfiles.length == 0) {
    logger.log(Level.WARNING, "syslogger called but no properties");
  } else {
 
    props = config.loadProps(pfiles[0]);
 
    var jms    = JMS.open(props);
    var xml    = <syslog level={level}><source>{source}</source><message>{message}</message></syslog>
 
    logger.log(Level.INFO, "xml = {0}", xml.toXMLString());
    jms.send(xml.toXMLString());
    jms.close();
  }
}
Example 3   Use a Trigger for Mission Phase Notification

In this example, a couple of trigger names are defined and are exposed to the job configuration screen. The trigger writes a log message in this example, but it could also be configured to send JMS notifications.

// Test trigger for misssion phase notification
 
addLibrary("logging");
 
function getPath() {
  return "/missions/phase/.*";
}
 
function run(path, id, env) {
 logger.log(Level.INFO, "phase called with path {0} and id {1}", path, id);
}

function getTriggerNames(path, env) {
  var n1 = new TriggerName("logme", "logme2");
  n1.group = "logmegroup";
 
  var n2 = new TriggerName("n2", "n2");
  n2.group = "logmegroup";
  return [n1, n2];
}