Select Attachments Poll Processor

The Poll Processor contains the logic that will be applied when polling a remote system for data.

The Poll Processor is a configuration record which contains the logic that will be applied when polling a remote system for data. There are three main scripts which are used to setup, execute and process the Poll Requests. The scripts given here are examples of how you might configure your Poll. The details of yours may differ depending on your requirements.

This Select Attachments Poll Processor will pull back a list of the relevant attachment records. Each record it identifies will be passed on to its child - Get Attachment Poll Processor.

New Poll Processor

In Unifi Integration Designer, navigate to & open < Your Integration > (created following the Outbound Incident Guide).

Click the 'Poll Processors' icon & then New.

The fields to be configured for the New Poll Processor modal are as follows:

Your New Poll Processor modal should look like this:

'Parent' - Once we have created its Parent Poll Processor, we can then select it here. We have not scripted any business logic to run from the value in this field. It is given for documentary purposes only.

Submit and view to further configure the Poll Processor.

Setup Script

The Setup Script is the first script to run (it runs at the point in time the Poll Request is created). It is used to build the environment for the poll and define what it will do. We will use it to setup the URL that will be called.

Navigate to Scripts > Setup Script.

The initial Poll Processor fields to be configured are as follows:

The code in the Setup script field should look like this:

// Configure the new Poll Request record
(function (poll_request, poller, params) {

    var gdt = new GlideDateTime();
    gdt.addSeconds(-1800);

    var conn = poller.getIntegration().getActiveConnection();
    var user = conn.getBasicAuthUser();
    var time = params.attachment_hwm || (gdt+'');

    var query = [
        'table_sys_id=' + params.ext_ref,
        'sys_created_by!=' + user,
        'sys_created_on>' + time,
        'ORDERBYsys_created_on'
    ];

    var uri_query = query.map(function(c) { return encodeURIComponent(c); }).join('%5E');

    poll_request.endpoint_url += '/attachment?sysparm_query=' + uri_query + '&sysparm_limit=10';

})(poll_request, poller, params);

Setup script: The parameters for which data to return are contained in the endpoint url.

query: Instead of querying all the attachments on the remote instance, we deliberately limit the query to those where the table_sys_id (target record) is the sys_id of a bonded Incident (passed in from the Response script of its Parent Poll Processor), that haven't been updated by the Authentication user (our system) and that were updated either since the last update time (if one exists), or in the last 30 minutes.

Endpoint URL: The value used in the poll_request.endpoint_url was initially generated using the ServiceNow REST API Explorer, substituting a variable in for the uri query. This value is appended to the existing endpoint url in the active connection before being added to the Poll Request.

(We have also chosen to limit the number of records returned to 10.)

Your Setup Script form should look like this:

Navigate to Request Script.

Request Script

The Request Script is used to reach into the remote system and execute the request. We will use the ServiceNow RESTMessageV2() web service to make a REST call to the URL defined in the Setup Script.

The next Poll Processor field to be configured is as follows:

The code in the Request script field should look like this:

// Process the request e.g. by executing a web service and returning the response
(function(poll_request, poller, connection, params) {

    var rm = new sn_ws.RESTMessageV2();
    rm.setEndpoint(poll_request.endpoint_url);
    rm.setHttpMethod('GET');
    rm.setRequestHeader('Accept', 'application/json');
    rm.setRequestHeader('Content-type', 'application/json');
    rm.setBasicAuth(connection.getBasicAuthUser(), connection.getBasicAuthPassword());

    // rm.setRequestBody(JSON.stringify(body));
    var resp = rm.execute();

    answer = resp.getBody() + '';

})(poll_request, poller, connection, params);

Request script: This script uses the ServiceNow RESTMessageV2() web service to make a REST call to the endpoint url created in the Setup script. It returns the body of the request as the answer which it passes to the Response script

Your Request Script form should look like this:

Navigate to Response Script.

Response Script

The Response Script is used to process the information returned from the remote system. We will use it to build an attachment object to pass this data to the next Poll Processor.

The last Poll Processor field to be configured is as follows:

The code in the Response script field should look like this:

// Process the response returned by the request script
// The 'answer' variable from the request script is passed in here as the 'response' parameter 
(function (poll_request, poller, response, params) {

    // DataStore name constants
    // Storage of time based High Water Marker
    var ATTACHMENT_HWM = 'attachment_hwm';

    var body = JSON.parse(response);

    // Nothing to do if no results were returned
    if ( body.result.length == 0 ) {
        poll_request.response_status = 'No Attachments returned\n\n' + JSON.stringify(body,null,2);
        return;
    }

/*

       {
            "size_bytes": "2330",
            "file_name": "MPFD-!--1539262705666--!",
            "sys_mod_count": "0",
            "average_image_color": "",
            "image_width": "",
            "sys_updated_on": "2018-10-11 12:58:26",
            "sys_tags": "",
            "table_name": "incident",
            "sys_id": "6c559892db812300f56c711ebf96192d",
            "image_height": "",
            "sys_updated_by": "ws_hn",
            "download_link": "https://dev22291.service-now.com/api/now/attachment/6c559892db812300f56c711ebf96192d/file",
            "content_type": "application/octet-stream",
            "sys_created_on": "2018-10-11 12:58:26",
            "size_compressed": "1055",
            "compressed": "true",
            "state": "",
            "table_sys_id": "bcdf18d5db241300f56c711ebf961947",
            "chunk_size_bytes": "",
            "hash": "",
            "sys_created_by": "ws_hn"
        },

*/

    // Establish the environment
    var poll_helper = new x_snd_eb.PollHelper(poll_request);
    var integration = poller.getIntegration();
    var conn = integration.getActiveConnection();
    var cvar = conn.getVariables();
    var info = [
        'Incident : ' + params.int_ref
    ];

    // Use Unifi code to find the Bond for the Incident
    var bond = new x_snd_eb.Bond(integration.getConfig());
    bond.locateReference(integration,params.int_ref,params.ext_ref);
    if ( !bond.isValidRecord() ) {
        // If no bond was found, ignore this poll
        info.push('- Bond not found - Attachments ignored');
        poll_request.response_status = info.join('\n') + '\n\n' + JSON.stringify(body,null,2);
        return;
    }

    var attachment_hwm;

    // Process each result
    body.result.forEach(function(attach){

        // Build an attachment object to pass on to the next poller
        var attachment = {
            remote_id    : attach.sys_id,
            file_name    : attach.file_name,
            content_type : attach.content_type,
            size_bytes   : attach.size_bytes
        };

        info.push('- Get attachment (' + attach.remote_id + '): ' + attach.file_name);

        x_snd_eb.Poller.execute( cvar.get_attachment_poller, {
            int_ref    : params.int_ref,
            ext_ref    : params.ext_ref,
            attachment : attachment
        });

        // Keep track of the latest created_on time
        attachment_hwm = attach.sys_created_on;

    });

    // Update Attachment High water mark (if later)
    if ( attachment_hwm > params.attachment_hwm ) {
        bond.setData(ATTACHMENT_HWM,attachment_hwm);
    }

    poll_request.response_status = info.join('\n') + '\n\n' + JSON.stringify(body,null,2);

})(poll_request, poller, response, params);

Response script: This script creates a variable to store a time based high water marker and parses the response into a body object to contain the result, (returning if it doesn't contain anything).

It then establishes the environment, getting the Integration, Connection & Connection Variables and sets up the essential PollHelper() function (which we initialise from the poll_request) along with the info [] array.

After that it finds the bond for the Incident (returning if there isn't one) & then processes each of the results (returned attachment records). For each, it builds an attachment object and sets up a Poll Request to retrieve & process the remote attachment (returning a PollRequest object). It also tracks the latest sys_created_on time.

After processing each result, the script checks whether the attachment was created later than the latest attachment high water mark; if so, it sets and stores that 'sys_created_on' value as the attachment high water mark (the 'attachment_hwm' is what the Setup script checks against when defining what the Poll will do). The results are then logged to the Response status field of the Poll Request.

x_snd_eb.Poller.execute(): This method has two parameters. In the first we pass the sys_id of the child Poller (as created in __ the 'Get Attachment Poller' page). In the second we pass an object containing the correlation_id on the bonded Incident as the int_ref element, the sys_id of the bonded Incident as the ext_ref element and the attachment object as the attachment element (telling the child Poller which attachment record to poll).

params: The params object is passed through to the subsequent scripts (and on to further Pollers, if required). This is used to pass the int_ref, ext_ref & attachment elements to the child Poller.

Your Response Script form should look like this:

Save the Poll Processor.

Update Child Poll Processor

Navigate to and open the Get Attachment Poll Processor (created on the 'Get Attachment Poll Processor' page) and update the value of the Parent field by selecting its parent Poll Processor created above.

Remember, We have not scripted any business logic to run from the value in the Parent field. It is given for documentary purposes only (for you to easily identify which parent Poll Processor kicked off the child).

Now let's move on and configure the Select Attachments Poller.