Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 176 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

2.2

Loading...

Release

Loading...

Loading...

Loading...

Loading...

Loading...

Overview

Loading...

Loading...

Loading...

Integration Guides

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Unifi Documentation

Welcome to the Unifi documentation space! Please take some time to read through the documentation as this will help you get the best out of the application.

Release

Release Notes Hotfixes Setup

Overview

Integration Guides

Feature Guides

Bonding

Transport

Configuration

Polling

Administration

Scripting

Attachments

Resolve Scenario

For each of our Scenarios we will need to configure the relevant Messages & Fields. This scenario will need to be tested before moving on to the next.

The Message we shall be configuring for the Resolve Scenario is:

  1. ResolveIncident

We will define which Field records require configuring for that Message at the appropriate time.

The scenario will need to be successfully tested before we can say it is complete.

We shall look in detail at the Message and its respective Fields in turn over the next few pages, before moving on to Test.

Quick Tour
Supported Features
Application Modules
Outbound Incident
Bidirectional Incident
Incident Update Poller
Incident Multiple Message Poller
Incident Create Poller
Incident Parent and Child Poller
Incident Attachment Poller
Packager
Error Handling Tools
Bonds
Bonded Attachments
Data Flow
Transactions
Stages
HTTP Requests
Response Actions
Processes
Integrations
Connections
Messages
Message Scripts
Fields
Field Maps
Event Actions
Pollers
Poll Processors
Poll Requests
Large Response Payloads
Activity Logs
Data Stores
Properties
Scheduled Scripts
System Logs
Self-test
Variables
Snippets
Attachment Handling
Multipart Form Data
ResolveIncident Message
ResolveIncident Fields
Test ResolveIncident

Resolve Scenario

For each of our Scenarios we will need to configure the relevant Messages & Fields. This scenario will need to be tested before moving on to the next.

The Message we shall be configuring for our Resolve Scenario is:

  1. ResolveIncident

We will define which Field records require configuring for that Message at the appropriate time.

The scenario will need to be successfully tested before we can say it is complete.

We shall look in detail at each of the Messages and their respective Fields in turn over the next few pages, before moving on to Test.

ResolveIncident MessageResolveIncident FieldsTest ResolveIncident

Release Notes

Here you will find details of what's changed in this release, including new features & improvements, depracated features and general fixes.

Introduction

Welcome to the release notes for Unifi - Version 2.2. Please have a read through to see new features and fixes that have been added.

Upgrade Notice

Please note that, as with every release, there may be some changes that are not entirely compatible with your existing integrations. While we do everything we can to make sure you won’t have to fix your integrations when upgrading, we strongly encourage all our customers to perform full end-to-end tests of their integrations before upgrading Unifi in Production.

We also highly recommend aligning your Unifi upgrade with your ServiceNow upgrade. This means you only need to test your integrations one time rather than once for the ServiceNow upgrade and once for the Unifi upgrade.

Feedback and Reviews

We really appreciate feedback on what we’re doing - whether it’s right or wrong! We take feedback very seriously, so if you feel you’d give us anything less than a 5 star rating, we’d love to hear from you so we can find out what we need to do to improve!

If you would rate us 5 stars, and haven’t left a review on the ServiceNow Store yet, we’d be grateful if you would head over there to leave us your feedback. It only takes a few minutes and really does help us a lot. Go on, you know you want to

Highlights

Paris Support

We’ve tested and verified that Unifi continues to work as expected on the latest Paris release of ServiceNow.

Packager

We’ve introduced a brand new feature that makes exporting and migrating integrations seriously easy, 1-click easy in fact. You can now click the “Package” button on an integration in the Portal and the system will gather all the related files that make that integration work and put them in a brand new update set and download it to your desktop. This feature does require the latest version of the Unifi Global Utility.

Details

New Features & Improvements

  • An API name is automatically generated when creating a new Process. [UN-192]

  • Integration Diagnostic now checks for global utility installation and version. [UN-369]

  • Millisecond time fields have been added to transactional records. [UN-541]

  • Integration Diagnostic now checks for hotfix version. [UN-682]

Changes

  • The display value for Connections now includes the Integration. [UN-347]

  • Bond reference method is no longer available for Response and Receipt type Messages. [UN-603]

  • Integration no longer controls number of attachments per message as this is done by the message itself. [UN-651]

General Fixes

  • Added the connection variable page to Portal. [UN-656]

  • Copying a Connection Variable now works. [UN-657]

  • Fixed icon alignment on Messages list in UID. [UN-755]

  • Fixed typo with Event Action. [UN-659]

Update Scenario

For each of our Scenarios we will need to configure the relevant Messages & Fields. This scenario will need to be tested before moving on to the next.

The Messages we shall be configuring for our Update Scenario are:

  1. Receipt

  2. UpdateIncident

We will define which Field records require configuring for each of those Messages at the appropriate time.

The scenario will need to be successfully tested before we can say it is complete.

We shall look in detail at each of the Messages and their respective Fields in turn over the next few pages, before moving on to Test.

Polling

We will configure a scheduled poll to query the remote system at regular intervals and pull back data that has changed which it will pass to Unifi to process.

To set up a scheduled poll that will query the remote system at regular intervals, check whether any data has changed and then pass that data to Unifi, we will need to configure the following records:

  • Poll Processor

  • Poller

Once those records are configured, we will need to configure inbound Messages to process the returned data. We will look at the polling records in turn over the next couple of pages.

We're now ready to configure the Poll Processor.

Polling

We will configure a scheduled poll to query the remote system at regular intervals and pull back data that has changed which it will pass to Unifi to process.

To set up a scheduled poll that will query the remote system at regular intervals, check whether any data has changed and then pass that data to Unifi, we will need to configure the following records:

  • Poll Processor

  • Poller

Once those records are configured, we will need to configure an inbound message to process the returned data. We will also need to make some changes to our outbound messages before we can test our update scenario (in order to prove the poll is returning the expected data and the target record is updated accordingly). We will look at the polling records in turn over the next couple of pages.

We're now ready to configure the Poll Processor.

Outbound Incident Guide

Follow this guide to configure a simple outbound integration to the table API of your Personal Developer Instance. It is given as an aid for those new to Unifi, or to play as part of a trial.

Welcome

Congratulations on your decision to use Unifi, the only integration platform you need for ServiceNow. We are sure you will be more than satisfied with this extremely powerful, versatile and technically capable solution.

Getting Started

This Guide utilises the Unifi Integration Designer portal interface which allows you to configure and manage integrations much more intuitively and with greater efficiency.

Unifi Integration Designer

From within native ServiceNow, open the Unifi Integration Designer portal by navigating to [ws] Unifi > Unifi Integration Designer.

Update Scenario

For each of our Scenarios we will need to configure the relevant Messages & Fields. This scenario will need to be tested before moving on to the next.

The Messages we shall be configuring for the Update Scenario are:

  1. Response

  2. UpdateIncident

We will define which Field records require configuring for each of those Messages at the appropriate time.

The scenario will need to be successfully tested before we can say it is complete.

Response Message

The Response Message is the immediate synchronous response that is sent to acknowledge the successful transport of another Message.

As previous, after clicking the 'Messages' icon, you will see the following screen (note: both the previously configured messages are now visible in the list):

1) Click New.

New Message Modal

The fields to be configured for the Response New Message modal are as follows:

Conclusion

Congratulations on completing this Outbound Incident Integration Guide.

This Guide has shown us how to configure a basic Incident integration, sending outbound messages via the REST service. The elements we configured were:

  • Process

  • Integration

  • Connection

Create Scenario

For each of our Scenarios we will need to configure the relevant Messages & Fields. This scenario will need to be tested before moving on to the next.

The Messages we shall be configuring for the Create Scenario are:

  1. CreateIncidentResponse

  2. CreateIncident

We will define which Field records require configuring for each of those Messages at the appropriate time.

The scenario will need to be successfully tested before we can say it is complete.

Create Scenario

For each of our Scenarios we will need to configure the relevant Messages & Fields. This scenario will need to be tested before moving on to the next.

The Messages we shall be configuring for our Create Scenario are:

  1. Response

  2. CreateIncidentReceipt

  3. CreateIncident

Bond Identification

In order for both systems to identify & understand which records are bonded and to facilitate only returning data from bonded records, we need to make a few configuration changes.

Our previously configured Outbound Incident Integration was very simple example and we weren't concerned with identifying which system made the updates. Neither were we concerned with telling the remote system which record they were bonded with.

Now that we're polling our PDI for data as well as sending data, we need to be aware of both the above concerns.

The first concern (identifying which system made the updates) has been taken care of in the Poll Processor Setup script (only returning data not updated by the Basic Authentication User). However, it doesn't make sense to try and return that data from all the records in the remote system. We should only be concerned with those records we're bonded with. To facilitate this we need to make a few configuration changes. We need to make a change in the remote system (our PDI) and some changes to our existing outbound CreateIncident Message.

First, we will need to Edit the Incident Form in our PDI.

Inbound Message

We will need to configure an inbound message to process the data returned from the poll.

In order to process the data that is returned from the remote system, we will need to create the appropriate messages in Unifi. To satisfy the requirements of this Guide, we will only need to configure the one message:

  • UpdateIncidentInbound

We shall look in detail at how to configure that message and the appropriate message scripts over the next couple of pages.

Let's begin by configuring the UpdateIncidentInbound Message.

Build the Other Half

Building the other half of our integration is much easier than you think.

If you're asking yourself, 'Do we have to do all that again?' the short answer is no, we don't. When using Unifi both ends, building the other half of the integration is a simple two-stage process.

  • First we Move the Integration, exporting it from one instance and importing it to the other (creating a mirror image in the other instance).

  • Second we Reconfigure the Connections so that each is pointed at the other.

We will look at both in more detail over the next couple of pages.

Message Identification

Unifi needs to identify the name of the inbound message in order to know how to process the inbound data.

When we configured our Outbound Incident Integration we weren't concerned with identifying inbound messages, because there weren't any (we were only sending outbound).

Now that we're polling our PDI for data as well as sending data, we need to be aware of the above concern.

To facilitate this we need to make a change to our Integration.

Message Identification

Getting Started

This Guide utilises the Unifi Integration Designer portal interface which allows you to configure and manage integrations much more intuitively and with greater efficiency.

Unifi Integration Designer

From within native ServiceNow, open the Unifi Integration Designer portal by navigating to [ws] Unifi > Unifi Integration Designer.

Polling

We will configure a scheduled poll to query the remote system at regular intervals and pull back data from the relevant, newly created, unbonded records which it will pass to Unifi to process.

To set up a scheduled poll that will query the remote system at regular intervals, check whether any new records have been created and then pass that data to Unifi, we will need to configure the following records:

  • Poll Processor

  • Poller

Once those records are configured, we will need to configure the relevant inbound and outbound messages to process and respond to the returned data. We will also need to make some further changes before we can test our create scenario (in order to identify which records to poll for). We will look at the polling records in turn over the next couple of pages.

Messages

We will need to configure messages to process and respond to the data returned from the poll.

In order to process and respond to the data that is returned from the remote system, we will need to create the appropriate Messages in Unifi. To satisfy the requirements of this Guide, we will need to configure the following Messages:

  • CreateIncidentInboundReceipt

  • CreateIncidentInbound

We shall look in detail at how to configure each of those Messages and the appropriate Fields to configure the Message Scripts over the next few pages.

Let's begin by configuring the CreateIncidentInboundReceipt

Trigger

  • Messages

  • Fields

  • In testing our integration, we created, updated and resolved an Incident - following the data as it flowed from our ServiceNow Incident record, through the Unifi transaction message bus, to the external system's Incident record.

    By Using the Unifi integration platform, we have discovered that building and testing our integration is simpler and more efficient, saving both time and money. Our hope is that this Guide has been a valuable aid to you in that process.

    For further information please see our technical documentation.

    If you have any feedback or questions, please contact us via our website contact form.

    Activity Log will show “No logs.” if no logs are generated. [UN-768]

  • Errors are no longer duplicated in Activity Log to make it easier to debug. [UN-769]

  • Improved documentation interface in UID. [UN-772]

  • Message Scripts now only throw their own errors (e.g. with Fields). [UN-749]

  • Improved spacing with UID Dashboard grid items. [UN-770]

  • leave a 5-star review on the Store!
    Receipt Message
    UpdateIncident Message
    UpdateIncident Fields
    Test UpdateIncident
    Poll Processor
    Poller
    Poll Processor
    Edit Incident Form
    Edit CreateIncident Message
    UpdateIncidentInbound Message
    UpdateIncidentInbound Fields
    Move the Integration
    Reconfigure the Connections
    Scope

    We have created this Outbound Incident Guide as an aid to customers who are beginning their journey in deploying the Unifi integration platform. We would not want you to be overwhelmed by exploring all that Unifi has to offer here, so we have deliberately limited the scope of this document. It will guide you through an example of how to configure a basic Incident integration, sending outbound messages via the REST API to the table API of another ServiceNow instance (i.e. your Personal Developer Instance, ‘PDI’).

    We do not recommend synchronous integrations for enterprise ticket exchange. This Guide is purely here for you to have a play as part of a trial. It is designed to connect to a PDI without Unifi being installed on the other side.

    For more technical information on how to use Unifi, please see our technical documentation.

    Warning

    Do not build integrations directly within the Unifi application scope. This can create issues with upgrades and application management.

    Installation

    The prerequisite to configuring Unifi is to have it installed on your instance. As with any other ServiceNow scoped application, Unifi must be purchased via the ServiceNow Store before installation.

    We recommend you follow the Setup instructions prior to configuring your Integration.

    Setup
    We shall look in detail at each of the Messages and their respective Fields in turn over the next few pages, before moving on to Test.

    Response Message
    UpdateIncident Message
    UpdateIncident Fields
    Test UpdateIncident
    We shall look in detail at each of the Messages and their respective Fields in turn over the next few pages, before moving on to Test.

    CreateIncidentResponse Message
    CreateIncidentResponse Fields
    CreateIncident Message
    CreateIncident Fields
    Test CreateIncident
    We will define which Field records require configuring for each of those Messages at the appropriate time.

    The scenario will need to be successfully tested before we can say it is complete.

    We shall look in detail at each of the Messages and their respective Fields in turn over the next few pages, before moving on to Test.

    Response Message
    CreateIncidentReceipt Message
    CreateIncidentReceipt Fields
    CreateIncident Message
    CreateIncident Fields
    Test CreateIncident
    Before configuring those polling records, let's first look at Connection Variables.

    Connection Variables
    Poll Processor
    Poller
    Message.

    CreateIncidentInboundReceipt Message
    CreateIncidentInboundReceipt Fields
    CreateIncidentInbound Message
    CreateIncidentInbound Fields
    Dashboard

    You will be greeted with the following Dashboard (which opens in a new window):

    Any existing Processes will be listed as tiles, showing the number of Active Integrations for each.

    If appropriate, you can either edit the Settings of, or add a New Integration to an existing Process by clicking the ellipsis (at the bottom right of the tile).

    Hovering over the tile of an existing Process will display 'Show integrations'. Clicking it will take you to the Integrations page (for that Process).

    In the next section, we shall look at configuring the Process.

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'Response'

    3

    Type

    The primary purpose of the message.

    'Response'

    4

    Direction

    Your Response New Message modal should look like this:

    5) Click Submit.

    You will be redirected to the Messages page. You need not configure the Response Message any further.

    Now it's time to move on and configure the UpdateIncident Message.

    This script is necessary because we have chosen to include the Message name in the structure of the payload object (see Response Script on the 'Poll Processor' page). If we had chosen instead to set it in the options object, it would have been processed and passed to Unifi for automatic Message identification - without the need to configure this script.

    To enable the Integration to identify which messages to use to process inbound requests:

    Navigate to the 'Integration' icon to open < Your Integration >, then navigate to Integration > Message Identification.

    1) Update the code in the 'Identify message script' field so that it looks like this:

    The Message Identification form should look like this:

    2) Save.

    In order for both systems to identify and understand which records are bonded, we need to make a few more changes which we shall group together under the heading of Bond Identification.

    function identify(payload) {
    
      return (payload.message.name || '') + '';
    
    }
    Dashboard

    You will be greeted with the following Dashboard (which opens in a new window):

    Any existing Processes will be listed as tiles, showing the number of Active Integrations for each.

    If appropriate, you can either edit the Settings of, or add a New Integration to an existing Process by clicking the ellipsis (at the bottom right of the tile).

    Hovering over the tile of an existing Process will display 'Show integrations'. Clicking it will take you to the Integrations page (for that Process).

    In the next section, we shall look at configuring a new Process.

    Quick Tour

    A high-level overview of the Unifi application.

    Navigation Overview

    The navigation menu items are grouped logically according to several different areas:

    • Bonding records hold all the data that links your instance to external systems.

    • Transport records give full visibility into what messages were sent and received.

    • Configuration is where you create and manage all your integrations.

    • Polling allows for pollers to be setup to automatically pull data from systems that cannot push.

    • Administration contains global settings and other items useful for working with the app.

    • Support links to the Unifi Support page. Here you can find contact details and a link to our documentation.

    Setup

    Navigate to Administration > Properties and ensure the Integrations Enabled property is checked.

    Configuration

    Much of the configuration can be carried out simply & intuitively using the Unifi Integration Designer portal interface.

    Integrations are grouped by Process and each contains the configuration necessary to connect to one external system.

    To add a new Integration you must have already configured a Process record (with associated web services) if you want to receive inbound Messages

    Integrations must have an active Connection for them to work. The active Connection tells outbound Messages where to go and specifies the user that is allowed to send data inbound (you must create unique users for each vendor).

    Add Messages to control when and what data is sent and received and how it is processed.

    Operations

    Use the Unifi Operations Portal for a real-time view of Transactions coming & going and a live view of the Bonds, showing their state & grouped by integration.

    Use the Dashboard to monitor your integrations and see how external systems are performing.

    Bidirectional Asynchronous Incident Guide

    Follow this guide to configure a bidirectional asynchronous integration to the Incident table. This push-push integration will use Unifi both ends.

    Welcome

    Congratulations on your decision to use Unifi, the only integration platform you need for ServiceNow. We are sure you will be more than satisfied with this extremely powerful, versatile and technically capable solution.

    Scope

    We have created this Guide as an aid to customers who are beginning their journey in deploying the Unifi integration platform. This document will guide you through an example of how to configure a bidirectional asynchronous Incident integration, sending and receiving messages via the Scripted REST Service.

    This guide is here to help you get up and running as quickly as possible, enabling you to realise the enormous benefits to be gained when using Unifi to configure your integration.

    For more technical information on how to use Unifi, please see our .

    Warning

    Do not build integrations directly within the Unifi application scope. This can create issues with upgrades and application management.

    Guide Structure and Testing Approach

    As with the previous release, the vast majority of the configuration is carried out in Unifi Integration Designer (our portal interface) - Processes, Integrations, Connections, Messages, Fields & Field Maps. Although there are many other elements which are configurable in the portal, they fall outside the scope of this document. For the purpose of this Guide, the remaining configuration elements are the Web Service & Trigger. These are to be configured in native ServiceNow as before.

    We could have chosen to deal with those elements configured in the portal first & then move on to those configured in native ServiceNow. Instead, however, we have structured this Guide to align with the testing approach. Firstly, we shall configure the main elements which have to be in place for the Integration to work (Process, Web Service, Integration, Connection, Trigger), then we shall move on to build & test each of the scenarios individually. For example, build the CreateIncident Message (along with CreateIncidentReceipt & Response), configure the relevant Fields for those Messages and then test the CreateIncident Message. Then do the same for the UpdateIncident Message (& Receipt) and so on.

    Some Dos & Don’ts

    We want to include some advice on things to be aware of - either to ensure you do them, or avoid doing them - when building & testing Unifi integrations; in particular and especially if many people are building in one instance at the same time (whether that be a training instance or sub-production instance).

    • Make sure your Process API name is unique, otherwise use an existing Process.

    • Make sure your SOAP and/or REST endpoints are also unique.

    Installation

    The prerequisite to configuring Unifi is to have it installed on your instance. As with any other ServiceNow scoped application, Unifi must be purchased via the ServiceNow Store before installation.

    We recommend you follow the Setup instructions prior to configuring your Integration.

    Edit Incident Form

    The first configuration change we need to make to facilitate Bond identification is to add the Correlation ID field to the Incident form in our PDI.

    Correlation ID

    In order for the remote system to store data about which record they're bonded with and to enable us to identify and only return data from those bonded records, we need to send and store a unique identifier. We will make use of the available correlation_id field on the Incident record. First we will add the field to the Incident form in our PDI.

    Incident Form

    From any Incident record in your PDI, right-click & navigate to Configure > Form Layout.

    Select the Correlation Id field from the 'Available' slushbucket and move it to the 'Selected' slushbucket.

    Save to add the field to your form.

    Next, we will need to Edit the CreateIncident Message.

    Conclusion

    Congratulations on using this Multiple Message Poller Guide to successfully poll your PDI for updates - deciding between multiple messages in Unifi to process the returned data.

    This Guide has shown us how we might configure a poller integration - polling data from the table API of a Personal Developer Instance (PDI) and then configure multiple inbound messages to process that data (deciding which Message to use in the process). As such, we created the following records:

    • Poll Processor

    • Poller

    • Inbound Message

    • Fields

    In testing our integration, we created some incidents in the remote instance which were bonded. We then updated the bonded records from both instances (polling for updates each time). We successfully proved that we were only querying bonded records, pulling back updates made in the remote instance since the last update time, only retrieving a select number of fields and that the returned requests were looped through, generating transactions for each updated ticket.

    We also proved that we were able to store previously returned records in order to facilitate comparison & to enable the decision as to which Message to use to process the data - successfully telling Unifi which Message to use.

    By Using the Unifi integration platform, we have discovered that building and testing our integration is simpler and more efficient, saving both time and money. Our hope is that this Guide has been a valuable aid to you in that process.

    For further information please see our .

    If you have any feedback or questions, please contact us via our website .

    Incident Update Poller Guide

    Follow this guide to configure a poller integration - polling the table API of your Personal Developer Instance (PDI) for updates only. This is the first of five Poller Guides. See 'Scope' for more.

    Welcome

    We will be configuring a Poller and Poll Processor in order to pull Incident data which has been updated from an external instance and pass it to Unifi. We will then configure the relevant inbound Message in order to process that data.

    If you have been following along with the Outbound Incident Guide you will know that it is given as an example of how you might configure such an integration. It is not meant to be prescriptive. The same applies here.

    Having said that, this Guide has been written to follow on from that previous one and has been structured accordingly.

    Scope

    This document will guide you through an example of how you might configure a poller integration - polling the table API of your Personal Developer Instance (PDI).

    This Guide is complementary to the Outbound Incident Guide. It assumes that both the Integration and the Connection are still in place and will be using those same elements as configured in that Guide. It also assumes that you know how to use the REST API of your PDI to query for information and read ticket data.

    If you haven’t completed the Outbound Incident Guide, please review & complete the following sections of that document, as they must be in place before continuing with this Guide:

    The Outbound Incident Guide demonstrates how to configure outbound messages to the table API of your PDI. This Guide will demonstrate how you might poll data from the table API of your PDI and then configure inbound messages to process that data.

    Definitions

    It is not always possible for a remote system to send us the data. In such cases, we can make a scheduled request for it using Pollers. We can setup, execute and process those Requests using Poll Processors.

    Poller

    A poller defines the frequency of polling and which logic to use. It is effectively a scheduled job which ties together an Integration and Poll Processor. Although a Poller belongs to only one Integration, an Integration can have multiple Pollers.

    Poll Processor

    A Poll Processor contains the logic that will be applied when polling a remote system for data. It contains three main scripts:

    Setup Script

    The Setup Script is used to build the environment for the poll and define what it will do (for example, create/setup the URL that will be called).

    Request Script

    The Request Script is used to reach into the remote system and execute the request. This is usually done by making a REST call to the URL defined in the Setup Script.

    Response Script

    The Response Script is used to process the information returned from the remote system.

    Warning

    Do not build integrations directly within the Unifi application scope. This can create issues with upgrades and application management.

    Approach

    We will need to store and check some returned data in order to evaluate when the data was changed and which system has made the updates to the data (we don’t want to pull back data we have changed).

    We will begin by polling for updates only and processing those requests using an update message in Unifi.

    We will also need to make some additional changes to the previously configured integration in order to allow for message identification and the ability to identify which records are bonded.

    Conclusion

    Congratulations on completing this bidirectional asynchronous Incident integration Guide.

    This Guide has shown us how to configure an asynchronous Incident integration, sending bidirectional messages via the REST service. The elements we configured were:

    • Process

    • Web Service

    • Integration

    • Connections

    • Trigger

    • Messages

    • Fields

    In testing our integration, we created, updated and resolved an Incident - following the data as it flowed from our ServiceNow Incident record, through the Unifi transaction message bus, to the external system's Incident record.

    By Using the Unifi integration platform, we have discovered that building and testing our integration is simpler and more efficient, saving both time and money. Our hope is that this Guide has been a valuable aid to you in that process.

    For further information please see our .

    If you have any feedback or questions, please contact us via our website .

    Conclusion

    Congratulations on successfully polling your PDI for non-bonded Incidents using this Create Poller Guide.

    This Guide has shown us how we might configure a poller integration - polling data from the table API of a Personal Developer Instance (PDI) and then configure the relevant message to process and respond to that data. As such, we created the following records:

    • Connection Variables

    • Poll Processor

    • Poller

    • Messages

    • Fields

    We also created & used a specific Assignment group in the remote instance (PDI), in order to facilitate the following:

    • Ticket Identification

    In testing our integration, we created some incidents in the remote instance which were non-bonded and assigned to a range of groups. We then polled for newly created tickets. We successfully proved that we were only querying non-bonded records which were assigned to a specific group, pulling back records created in the remote instance since the last update time, only retrieving a select number of fields and that the returned requests were looped through, generating transactions for each non-bonded ticket.

    By Using the Unifi integration platform, we have discovered that building and testing our integration is simpler and more efficient, saving both time and money. Our hope is that this Guide has been a valuable aid to you in that process.

    For further information please see our .

    If you have any feedback or questions, please contact us via our website .

    Process

    The first element to configure is the Process, which is the top level configuration element where all Integrations are contained.

    The first thing to do when creating a new integration is to assign it to its Process. For instance, a new Incident integration would be created within an Incident Process. If you do not yet have a Process defined, then you will need to create a new Process

    From the Unifi Integration Designer Dashboard, click on New Process.

    On the 'New Process' modal, the fields to be configured are as follows:

    Build - Integration Level

    It is possible to run the Build process from the Integration. This will cause the process to cycle through each of the Messages on the Integration in turn.

    We have been running the Build process at the Message level in order to see the changes in our Message Scripts as we go. This may be considered good practice (particularly when first starting out) as any discrepancies can be discovered & rectified as you go (in potentially fewer, smaller batches). Once you are more practiced and confident in the accuracy of your configurations, you can run the Build process at the Integration level. This means that the process will cycle through all the Field records on each of the Messages on the Integration in turn & auto-generate all the relevant Message Script code.

    As mentioned in the page, we saw that a 'Build Integration' button had appeared in the banner at the top of the page. This was because, whenever a change is made to a Field record that is associated to a Message (whether that is being created, updated, or deleted) the button will be available and act as a visual reminder that changes have been made and Message Script(s) need to be built.

    To run the Build Process at the Integration level we have two choices. We can either either run it from the Integration record, or we can use the 'Build Integration' button which appears in the banner at the top of the page.

    To run it from the Integration record. In Unifi Integration Designer

    Build - Integration Level

    It is possible to run the Build process from the Integration. This will cause the process to cycle through each of the Messages on the Integration in turn.

    We have been running the Build process at the Message level so as to see the changes in our Message Scripts as we go. This may be considered good practice (particularly when first starting out) as any discrepancies can be discovered & rectified as you go (in potentially fewer, smaller batches). Once you are more practiced and confident in the accuracy of your configurations, you can run the Build process at the Integration level. This means that the process will cycle through all the Field records on each of the Messages on the Integration in turn & auto-generate all the relevant Message Script code.

    As mentioned in '', we saw that a 'Build Integration' button had appeared in the banner at the top of the page. This was because, whenever a change is made to a Field record that is associated to a Message (whether that is being created, updated, or deleted) the button will be available and act as a visual reminder that changes have been made and Message Script(s) need to be built.

    To run the Build Process at the Integration level we have two choices. We can either either run it from the Integration record, or we can use the 'Build Integration' button which appears in the banner at the top of the page.

    To run it from the Integration record. In Unifi Integration Designer

    Testing

    You should have successfully configured a Poll Processor and Poller. You should also have configured the ResolveIncidentInbound message. The next thing to do is to test.

    It may help to turn off the Poller we created (set Active to 'false') whilst conducting these tests and to manually execute it as required (this can still be done even if the Poller is inactive). This is so that we don't have to wait for the Poller to run, but rather manually activate it when needed by clicking 'Execute Now'.

    To turn off the Poller, in the Unifi Integration Designer window, navigate to the 'Pollers' icon & set Active to false.

    Our Poll Processor has been configured to poll for updates from our PDI and make a decision, telling Unifi which Message to use to process that data. We will therefore test our poller by means of testing both of the inbound Messages on our Integration:

    Inbound Messages

    We will need to configure inbound Messages to process the data returned from the poll.

    In order to process the data that is returned from the remote system, we will need to create the appropriate Messages in Unifi. The following Messages will be required:

    • UpdateIncidentInbound

    • ResolveIncidentInbound

    To satisfy the requirements of this Guide (and because we have already configured one of those Messages in the previous Incident Update Poller Guide, we will only need to configure the one message i.e. ResolveIncidentInbound.

    We shall look in detail at how to configure that Message and the appropriate Message Scripts over the next couple of pages.

    Response Message

    The Response Message is the immediate synchronous response that is sent to acknowledge the successful transport of another Message.

    In Unifi Integration Designer, click on the 'Messages' icon & then New to begin configuring the Response Message.

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

    When setting up a Connection:
    • Never use your own User as the Inbound User as it will prevent the integration from working.

    • Always ensure that your Inbound User is NOT used by anyone else for the same Process i.e. if you’re creating a Connection for an Integration on the Incident Process, your Inbound User has to be the only User used by an Integration within that Process.

  • When configuring a Trigger (Business Rule) on a table to be integrated, make sure one doesn’t exist already. If you have more than one, you will make duplicate updates.

  • technical documentation
    Setup
    technical documentation
    contact form
  • Connection

  • Process
    Integration
    technical documentation
    contact form
    technical documentation
    contact form

    Let's begin by configuring the ResolveIncidentInbound Message.

    ResolveIncidentInbound Message
    ResolveIncidentInbound Fields

    1

    Name

    The name of the ServiceNow process being integrated.

    <SN Process Name> (e.g. Incident)

    2

    API Name*

    The unique name of this process for use with the API.

    <your_unique_api>

    3

    Target table

    The primary target or process table that this integration uses.

    'Incident' [incident]

    4

    Reference field

    The field on the target table that is used as the reference for the external system.

    'Number'

    5

    Description

    Describe what this Process is for.

    <Your description>

    *API Name

    The API Name is how we identify which Process we are integrating with. The Scripted SOAP/REST Service will reference the API Name (which is why it is important for this to be a unique reference).

    Your 'New Process' modal should look like this:

    6) Click Create.

    You will be redirected to your Process Dashboard:

    Click either the '+' tile or 'New Integration' in preparation to configure the Integration.

    Before we configure the Integration, however, we will first step back into the native ServiceNow window to configure the Web Service.

    #

    Field

    Description

    Value

    , navigate to:
    'Integration' icon
    .

    1) Click Build.

    To run it from the 'Build Integration' button which appears in the banner at the top of the page.

    1) Click Build Integration.

    2) On the Build Integration modal, click Build.

    When complete, you will see the following Integration Build Worker modal:

    3) Click Done.

    Navigate to: 'Messages' icon.

    Feature Alert: The widget at the bottom of the page also shows when 'Build' was last run.

    Click through each Message in turn, navigating to Advanced > Script Editor to view the auto-generated code in the Message Scripts.

    We have now built and tested the integration in one instance. We are now ready to move on and Build the other half.

    'CreateIncidentReceipt Fields'
    , navigate to:
    'Integration' icon
    .

    1) Click Build.

    To run it from the 'Build Integration' button which appears in the banner at the top of the page.

    1) Click Build Integration.

    2) On the Build Integration modal, click Build.

    When complete, you will see the following Integration Build Worker modal:

    3) Click Done.

    Navigate to: 'Messages' icon.

    Feature Alert: At the bottom right of the window you will see a widget that displays whether the Integration is Active and when 'Build' was last run.

    Click through each Message in turn, navigating to Advanced > Script Editor to view the auto-generated code in the Message Scripts.

    We have now built and tested the Outbound Incident Integration.

    CreateIncidentResponse Fields
    UpdateIncidentInbound
  • ResolveIncidentInbound

  • We will look in more detail at the steps for each over the next couple of pages.

    First, we shall test the UpdateIncidentInbound Message.

    Test UpdateIncidentInbound
    Test ResolveIncidentInbound

    2

    Type

    The primary purpose of the message.

    'Response'

    3

    Direction

    The direction(s) this message is configured to support. (Choices: Inbound, Outbound, Bidirectional)

    'Bidirectional

    Your Response New Message modal should look like this:

    4) Click Submit.

    You will be redirected to the Messages page. We need not configure our Response Message any further.

    Next, we shall move on and configure the CreateIncidentReceipt Message.

    #

    Field

    Description

    Value

    1

    Message name

    The message name that is unique for this integration.

    'Response'

    The direction(s) this message is configured to support. (Choices: Inbound, Outbound, Bidirectional)

    'Inbound'

    Supported Features

    Details of the API models & integration features Unifi supports.

    API Models

    Unifi supports push-push and push-pull request models*.

    Model

    Delivery Response

    Sync Process Response

    Async Process Response

    * Use Direct Web Services or custom Scripted Web Services

    Integrations

    Process

    The first element to configure is the Process, which is the top level configuration element where all Integrations are contained.

    The first thing to do when creating a new integration is to assign it to its Process. For instance, a new Incident integration would be created within an Incident Process. If you do not yet have a Process defined, then you will need to create a new Process

    From the Unifi Integration Designer Dashboard, click on New Process.

    On the 'New Process' modal, the fields to be configured are as follows:

    #

    Field

    Description

    Value

    *API Name

    The API Name is how we identify which Process we are integrating with. The Scripted SOAP/REST Service will reference the API Name (which is why it is important for this to be a unique reference)

    Your 'New Process' modal should look like this:

    6) Click Create.

    You will be redirected to the Dashboard of your newly created Process:

    Click either the '+' tile or 'New Integration' to move on and configure the Integration.

    Integration

    This is what defines the connection between a Process and the single system it's connecting with. It is also where most of the configuration and settings are stored.

    New Integration

    In the Unifi Integration Designer window, after clicking either on the '+' tile or 'New Integration', you are given a 'New Integration' modal to complete.

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

    Your 'New Integration' modal should look like this:

    4) Click Create.

    You will be redirected to the Details page of the newly created Integration.

    Icons

    Before continuing we would like to draw your attention to some of the relevant icons that are now visible down the left hand navigation strip.

    The icons are:

    a) 'Integration' icon: Opens the current integration's Details page.

    b) 'Messages' icon: Opens the current integration's Messages page.

    c) 'Fields' icon: Opens the current integration's Fields page.

    d) 'Field Maps' icon: Opens the current integration's Field Maps page.

    e) 'Documentation' icon: Opens the automatically generated documentation for the current integration. (Another awesome feature in Unifi.)

    f) 'Connections' icon: Opens the current integration's Connections page.

    Details

    The Details page of your Integration form should look like this:

    5) Navigate to Settings > Feedback.

    Feedback Settings Fields

    The Feedback fields to be configured for the Integration record are as follows:

    The Feedback Settings fields should look like this:

    All of the remaining 'Settings' values are to be left as-is:

    • Attachments Settings

    • Bond Settings

    All of the 'Error handling' values are to be left as-is:

    8) Click Save.

    9) Click the 'Connections' icon to move on and configure the Connection.

    CreateIncidentResponse Message

    The CreateIncidentResponse Message is the immediate, synchronous response that is sent after processing the Createincident Message.

    New Message Modal

    In Unifi Integration Designer, navigate to the 'Messages' icon. Click New.

    The fields to be configured for the CreateIncidentResponse New Message modal are as follows:

    #

    Your CreateIncidentResponse New Message modal should look like this:

    4) Click Submit and view to further configure the Message.

    Script Editor Fields

    The Scripts are where the request processing and data mapping occurs. They are also the place where Bond state & ownership are set.

    5) Navigate to Advanced > Script Editor.

    When you first open the Script Editor, you will see the following:

    Having visibility of your message scripts in the one pane makes scripting so much more efficient.

    Because we are dealing with an inbound message, we can adjust the view to only show the 'Payload to Stage' & 'Stage to Target' script fields.

    6) Navigate to View > Inbound.

    Your Script Editor fields will initially look like this:

    Scripts

    We will primarily by utilising OOTB Fields & Field Maps to configure our Message Scripts. In the current release, however, there is no OOTB Field Map record with which we can set the state on the Bond. We shall, therefore, script that manually. For more information , see the ' & '' pages in our technical documentation.

    The Script Editor fields to be configured are as follows:

    The code in the 'Stage to Target' script field should look like this:

    Setting the Bond state to Open allows messages to be sent/received. See the '' page for details.

    Your Script Editor fields should now look like this:

    8) Click Save.

    9) Click Close to navigate back to the Message.

    We are now ready to configure the Fields for our CreateIncidentResponse Message.

    Build - Integration Level

    It is possible to run the Build process at the Integration level. This will cause the process to cycle through each of the Messages on the Integration in turn.

    We have been running the Build process at the Message level in order to see the changes in our Message Scripts as we go. This may be considered good practice (particularly when first starting out) as any discrepancies can be discovered & rectified as you go (in potentially fewer, smaller batches). Once you are more practiced and confident in the accuracy of your configurations, you can run the Build process at the Integration level. This means that the process will cycle through all the Field records on each of the Messages on the Integration in turn & auto-generate all the relevant Message Script code.

    As mentioned on the 'CreateIncidentInboundReceipt Fields' page, we saw that a 'Build Integration' button had appeared in the banner at the top of the page. This was because, whenever a change is made to a Field record that is associated to a Message (whether that is being created, updated, or deleted) the button will be available and act as a visual reminder that changes have been made and Message Script(s) need to be built.

    To run the Build Process at the Integration level we have two choices. We can either either run it from the Integration record, or we can use the 'Build Integration' button which appears in the banner at the top of the page.

    To run it from the Integration record. In Unifi Integration Designer, navigate to: 'Integration' icon.

    1) Click Build.

    To run it from the 'Build Integration' button which appears in the banner at the top of the page.​

    1) Click Build Integration.

    2) On the Build Integration modal, click Build.

    When complete, you will see the following Integration Build Worker modal:

    3) Click Done.

    Running Build on the Integration has processed all 9 Messages (i.e. all the Messages created following the Outbound Incident Guide, Incident Update Poller Guide & Incident Multiple Message Guide as well as this Guide)

    Navigate to: 'Messages' icon.

    Feature Alert: The widget at the bottom of the page also shows when 'Build' was last run.

    Click through each of the relevant Messages in turn, navigating to Advanced > Script Editor to view the auto-generated code in the Message Scripts.

    We are now ready to move on and Test the Create Poller.

    Conclusion

    Congratulations on successfully polling your PDI for updates using this Update Poller Guide.

    This Guide has shown us how we might configure a poller integration - polling data from the table API of a Personal Developer Instance (PDI) and then configure an inbound message to process that data. As such, we created the following records:

    • Poll Processor

    • Poller

    • Inbound Message

    • Fields

    We also made further configuration changes to both the remote instance (PDI) and internal instance, in order to facilitate the following:

    • Message Identification

    • Bond Identification

    In testing our integration, we created some incidents in the remote instance which were bonded. We then updated the bonded records from both instances (polling for updates each time). We successfully proved that we were only querying bonded records, pulling back updates made in the remote instance since the last update time, only retrieving a select number of fields and that the returned requests were looped through, generating transactions for each updated ticket.

    By Using the Unifi integration platform, we have discovered that building and testing our integration is simpler and more efficient, saving both time and money. Our hope is that this Guide has been a valuable aid to you in that process.

    For further information please see our .

    If you have any feedback or questions, please contact us via our website .

    ResolveIncident Message

    The ResolveIncident Message is an update type message that we will configure to deal specifically with our resolve scenario (resolve the bonded records).

    Again, after clicking the 'Messages' icon, you are directed to the following screen (note: the four previously configured messages are now visible in the list):

    1) Click the ellipsis to the right of the UpdateIncident Message & then click Copy.

    It is now easier than ever to create the ResolveIncident Message. Rather than create it from scratch, it will be quicker to copy the UpdateIncident Message and make some minor changes.

    Receipt Message

    The Receipt Message is the asynchronous receipt that is sent after processing update type messages.

    Again, after clicking the 'Messages' icon, you are directed to the following screen (note: the three previously configured messages are now visible in the list):

    1) Click on the ellipsis to the right of the CreateIncidentReceipt Message & click Copy.

    Rather than create the Receipt Message from scratch, it will be quicker to copy the CreateIncidentReceipt Message and make one minor change.

    Move the Integration

    The first step to building the other half of the Integration is to export it from one instance and import it to the other.

    Export the Integration

    Using the Packager feature makes moving integrations between instances simpler and more efficient than ever.

    Incident Multiple Message Poller Guide

    Follow this second of five Poller Guides to configure an integration - polling the table API of your Personal Developer Instance (PDI) for updates & deciding between multiple messages to process.

    Welcome

    We will be configuring another Poller and Poll Processor in order to pull data which has been updated from an external instance and then pass it to Unifi. We will then configure the relevant inbound Messages in order to process that data.

    If you have been following along with the Outbound Incident Guide and the previous Poller Guide you will know that they are given as examples of how you might configure such integrations. They are not meant to be prescriptive. The same applies here.

    Having said that, this Guide has been written to follow on from those previous ones and has been structured accordingly.

    Setup

    The instructions on this page will show you to get up and running with Unifi as quickly and efficiently as possible.

    Overview

    Follow these steps to install Unifi and get your system up and running quickly.

    1. Install Unifi

    Poller

    Outbound push

    Async only

    Yes

    Yes

    -

    Inbound push

    Async only

    Yes

    Yes

    -

    Outbound pull

    -

    -

    -

    Yes

    Inbound pull*

    -

    -

    -

    No

    Feature

    Supported

    Unique configuration per Integration

    Yes

    Environment management

    Yes

    Vendor specific

    Yes

    technical documentation
    contact form

    Application Module Overview

    A quick overview of the Unifi Application and its modules.

    Unifi Integration Designer

    This is a quick link which will open the Unifi Integration Designer page in a new browser window. From here, much of the configuration of your integrations can be carried out in a more intuitive and efficient manner.

    Unifi Operations Portal

    This is a quick link which will open the Unifi Operations Portal page in a new browser window. It provides a live, real-time view of the last 20 Transactions processed & the Bonds that have been worked on today - showing their state & grouped by Integration. From here, you can jump straight into the relevant records (e.g. Transaction, HTTP Request, Bond, bonded record).

    Dashboard

    This is a quick link to the legacy Unifi Dashboard which displays reports providing operational insights into the data being exchanged.

    Bonding

    The bonding tables are used to manage the state of the connection between the two records in each system.

    Bonds

    Table: x_snd_eb_bond

    A bond is a record that joins an integration to an internal process record (i.e. a ticket) by storing the internal and external system references together, along with the integration and other bond specific data. It also stores a commentary of the full history of the integration actions, making it very easy to see what has happened across the lifetime of the bond.

    Bonded Attachments

    Table: x_snd_eb_attachment

    Bonded Attachment records track the synchronisation status of attachments on the record that has been bonded.

    Transport

    The communication tables facilitate the transportation, extraction, transformation and loading of data communications. They are used to simplify development and debugging, aid in operations management, and provide full insight into the details of every data exchange.

    Transactions

    Table: x_snd_eb_transaction

    A Transaction is essentially a container used to group together the stages and requests created for single message exchange. Every inbound or outbound message belongs to a Transaction and this includes response and receipt messages.

    Stages

    Table: x_snd_eb_stage

    The Stage table allows data to be extracted and stored before it is processed. Although a requirement for asynchronous messaging, this separation makes it very easy to develop and maintain the integrations that the application supports.

    • Stage is configured so it can be extended for each process.

    • The introduction of Dynamic Stage now means there is no need to manually create the staging table.

    HTTP Requests

    Table: x_snd_eb_http_request

    HTTP Requests are the lowest level of communication, containing the raw data that is exchanged between systems.

    Configuration

    Processes

    Table: x_snd_eb_process

    The Process record allows integrations to be aligned to particular process. Many processes can be made available for integrations, and many integrations can belong to each process.

    Process records define the top level configuration that all integrations using this process will follow. A typical process to be made available for integration would be Incident.

    Integrations

    Table: x_snd_eb_integration

    An Integration acts as the top level container for configuring a process to be used by a single external or internal supplier. All the options specific to the integration are set on this record.

    • An integration is only active when a connection is active.

    Connections

    Table: x_snd_eb_connection

    Connection records allow many endpoint access configurations to be set up for a single integration. This makes managing access for different instances very easy, such as development, test and production.

    Only one Connection can be made active at any time. Making one Connection active will automatically enable the Integration and disable all the other Connections. Disabling a connection will disable the Integration.

    Messages

    Table: x_snd_eb_message

    The Unifi application uses a message centric architecture, meaning that every outbound/inbound request is configured as a single Message. A Message might be a create or update request, a receipt or a response. All Messages will send/receive a response Message and asynchronous Messages can also be configured to send/receive a receipt.

    Fields

    Table: x_snd_eb_field

    Fields simplify and bring additional functionality to the configuring of Messages & Message Scripts. They allow Message Scripts to be broken down into smaller, reusable components.

    A Field record defines the processing of a discrete component of a Message and often represents the handling of an individual field on the source/target record (e.g. Short description). They are also used to define the objects that will carry other Transaction specific data (e.g. Name, Time stamp, Source reference, Target reference).

    Field Maps

    Table: x_snd_eb_field_map

    The Field Map defines the behaviour, or ‘type’ of a Field. It defines template code into which details from Field records are substituted. It has a template script field for each of the Message Script types (Source to Stage, Stage to Request, Payload to Stage, Stage to Target).

    Message Scripts

    Table: x_snd_eb_message_script

    Data extraction, transformation and loading is handled by the Message Scripts. Each message can have custom scripts added that facilitate one of the following scenarios:

    • Payload to Stage (Inbound)

    • Stage to Target (Inbound)

    • Source to Stage (Outbound)

    • Stage to Request (Outbound)

    Response Actions

    Table: x_snd_eb_response_action

    Response Actions are interceptors that allow you to customise the way responses are handled.

    Diagnostic

    The Diagnostic module is a link to a diagnostic test that can be run to check the configuration of your integration.

    Polling

    In cases where it is not possible for a remote system to send us the data, we can make a scheduled request for it using Pollers.

    Pollers

    Table: x_snd_eb_poller

    A Poller makes a scheduled request to a remote system. It is a configuration record which defines the frequency of polling and which logic to use.

    Poll Processors

    Table: x_snd_eb_poll_processor

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

    Poll Requests

    Table: x_snd_eb_poll_request

    The Poll Request is an operational record which stores the details and outcomes of a scheduled poll.

    Administration

    Activity Logs

    Table: x_snd_eb_activity_log

    The Activity Logs module displays all the entries to the Unifi Activity Log table from the current day.

    Data Stores

    Table: x_snd_eb_data_store

    A Data Store is simply a key-value pair stored in the database that is available to all records in the system. They are used primarily in Message Scripts and Poll Requests when you want to get and set functional data that is relevant to the integration but does not belong on the target record.

    Properties

    The Properties module is where you will find the global system settings for the Unifi application.

    Scheduled Scripts

    Table: x_snd_eb_scheduled_script

    The Scheduled Scripts module displays the scripts which are automatically created by the system in order to perform tasks.

    System Logs

    The System Logs module is a quick link to the ServiceNow system logs and shows errors and warnings from the current day.

    Self-test

    The Self-test module is a link to a suite of internal tests that can be run at any time.

    Support

    Get Help

    The Get Help module is a quick link to the Unifi Portal welcome page where you will find links to our Documentation site along with ways to connect with us for application support.

    Install Global Utility

  • Install Hotfix

  • Configure Your Integrations

  • 1. Install Unifi

    If you have purchased Unifi, you will need to ensure the instance you want to install Unifi on has been given entitlement to the application. You can manage this through the Store.

    Once you have setup entitlement, you can use the Application Manager in ServiceNow to install Unifi. You can find more information on how to Install a ServiceNow Store Application in the ServiceNow Product Documentation.

    If you have not yet purchased Unifi, you can request a trial from the ServiceNow Store.

    2. Install Global Utility

    Unifi has some enhanced functionality that requires access to methods not available to scoped applications. We grant Unifi access to those methods through a single global utility Script Include which you can install via Update Set.

    It is strongly advised that you install this utility to get the most out of Unifi.

    1. Download [ws] Unifi Global Utility - 2.2.1

    2. Import the file as an update set, then preview and commit it. You can find more information on how to Load customizations from a single XML file in the ServiceNow Product Documentation.

    Features

    Moving Attachments

    Method: snd_eb_util.moveAttachments

    The ServiceNow scoped attachment API does not support moving attachments from one record to another. This is necessary for inbound attachments which initially reside on the HTTP Request and are then moved to the Target record.

    Jelly Processing

    Method: snd_eb_util.runJelly

    Jelly processing is not supported in the ServiceNow scoped API’s, however it is very useful for XML processing. Use of the Global Utility drastically improves XML payload capabilities if you are working with XML payloads.

    SOAP Response Element

    Method: snd_eb_util.getSoapResponseElement

    When working with Scripted SOAP Services, it’s important to be able to set the soapResponseElement directly in order to preserve the exact payload to be sent back to the calling system. This can only be done with the Global Utility.

    Binary Attachment Handling

    Method: snd_eb_util.writeAttachment

    The Scoped Attachment API does not support writing binary attachments which can cause problems when receiving things like Word documents or PDF’s. This method allows Unifi to use the global attachment API to write those files to the database meaning they will work properly.

    Update Set Packaging

    Method: snd_eb_util.packager.*

    The packager methods included in the global utility allow Unifi to automatically export all the components of an integration in one easy step. The packager methods will allow Unifi to create an update set for the integration, add all the configuration records to that update set, and export it as a file download from the Integration page on the Unifi Integration Designer portal.

    3. Install Hotfix

    Unifi has the ability to be patched between releases by using a special Script Include called hotfix.

    Please go to the hotfixes page where you can see the hotfixes that have been made and apply them to Unifi.

    4. Configure Your Integrations

    If you’re new to Unifi then you might like to follow one of our integration guides. You can access the Integration Guides from the menu.

    11KB
    [ws] Unifi Global Utility - 2.2.1.xml
    Open
    [ws] Unifi Global Utility - 2.2.1
    • General

    • Timeouts

    • Retry

    The remaining 'Integration' values are to be left as-is:

    • Message Identification

    #

    Field

    Description

    Value

    1

    Name

    The name of the integration.

    <Your Name>

    2

    Service type

    The type of web service this integration is using (SOAP/REST).

    'REST'

    3

    Message format

    Automatically pre-process incoming messages for simpler message scripting. (Choices: XML, JSON, Advanced)

    'JSON'

    #

    Field

    Description

    Value

    6

    Enable UI messages

    Allow information and error messages to be shown to the user as UI Notifications. Only applies to certain notifications.

    <true>

    7

    Note bond history

    Use the 'Note bond history' to process bond history updates. (Set to true for the history to be promoted to the work notes fields of the record we're integrating - for the analyst to view)

    <true>

    Copy Message Modal

    The fields to edit for the Copy Message modal are as follows:

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'ResolveIncident'

    Your Copy Message modal should look like this:

    3) Click Copy.

    You will be redirected to the Details page of the newly created ResolveIncident Message.

    Bond Fields

    Navigate to Message > Bond.

    The Bond fields to be edited are as follows:

    #

    Field

    Description

    Value

    4

    Bond suspended

    Process this message when the bond state is Suspended (internal suspend).

    <true>

    5

    Bond vendor suspended

    Process this message when the bond state is Vendor suspended (external suspend).

    <true>

    Your Bond form should look like this:

    6) Navigate to Outbound > Trigger.

    Outbound Trigger Fields

    The Outbound Trigger (as required)* fields to be edited are as follows:

    #

    Field

    Description

    Value

    7

    Outbound condition*

    The condition that the ServiceNow record must meet to trigger this message being processed.

    'State > changes to > Resolved'

    *Outbound condition (as required):

    It is not necessary for you to enter a condition. The value given is an example. You may create any condition (or not) to align with your business process requirements. In this case, it makes sense to send the ResolveIncident Message when the state changes to Resolved.

    Your Outbound Trigger form should look like this:

    8) Click Save.

    We are now ready to configure the Fields for the ResolveIncident Message.

    Copy Message Modal

    The fields to edit for the Copy Message modal are as follows:

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'Receipt'

    Your Copy Message modal should look like this:

    3) Click Copy.

    You will be redirected to the Details page of the newly created Receipt Message.

    Script Editor Fields

    Navigate to Advanced > Script Editor, then View > Inbound.

    Your Script Editor fields should initially look like this:

    The Script Editor fields to be edited are as follows:

    #

    Field

    Description

    Value

    4

    Stage to Target (Inbound)

    The script to run.

    Delete the following code that sits outside of the End tag: bond.setOpen();

    Scripts

    The code in the 'Stage to Target' script field should look like this:

    Your Script Editor fields should now look like this:

    5) Click Save.

    6) Click Build Message.

    You will see the 'Message build successful' Info Message.

    7) Click the 'Messages' icon to move on & configure the UpdateIncident Message.

    There is no further configuration required for the Receipt Message.

    In Unifi Integration Designer, navigate to and open < Your Integration >.

    Click the 'Integration' icon to open the Details page.

    Click Package.

    The Package Integration modal is displayed.

    Confirm by clicking Package.

    Unifi packages the Integration into an Update Set which is automatically downloaded.

    The Integration Package Worker modal is displayed.

    The modal tells us how many records were processed and the name of the Update Set that was created (the integration name prepended with the date/time).

    Copy the name of the Update Set.

    Click Done to close the modal.

    Navigate to the downloaded Update Set and Show in folder*.

    *Example shown in Chrome. Other browsers may vary.

    Then rename the file (using your Update Set name in order to easily identify it when uploading to the other instance).

    Import the Integration (external instance)

    In the Application Navigator of the external instance, navigate to System Update Sets > Retrieved Update Sets.

    At the bottom of the Retrieved Update Sets list, click the Import Update Set from XML related link.

    If you have the UI16 Developer Patch installed (download from Share by clicking here), you can navigate directly to the Import XML page from the context menu of the Update Set Picker by clicking Import from XML.

    The Import XML screen is displayed:

    Click Choose file to upload the previously downloaded file.

    Upload.

    You are redirected back to the Retrieved Update Sets list view:

    Open the Update Set

    Your Retrieved Update Set form is displayed:

    Click Preview Update Set.

    Close the Update Set Preview modal.

    Click Commit Update Set.

    Close the Update Set Commit progress modal.

    We have successfully installed the application containing our Integration on the external instance. The vast majority of the configuration is already in place. All that remains is to make a few configuration changes and Reconfigure the Connections to enable each instance to connect with the other.

    Scope

    This document will guide you through an example of how you might configure a poller integration - polling the table API of your Personal Developer Instance (PDI).

    This Guide is complementary to the Outbound Incident Guide. It assumes that both the Integration and the Connection are still in place and will be using those same elements as configured there. It also assumes that you know how to use the REST API of your PDI to query for information and read ticket data.

    If you haven’t completed the Outbound Incident Guide, please review & complete the following sections of that document, as they must be in place before continuing with this Guide:

    • Process

    • Integration

    This document also builds on the Incident Update Poller Guide. As such, it assumes that the changes made in that Guide are still in place and will make use of some of those same elements.

    If you haven’t completed the Incident Update Poller Guide, please review & complete the following sections of that document at least, as they must be in place before continuing with this Guide:

    • UpdateIncidentInbound Message

    • UpdateIncidentInbound Fields

    The Incident Update Poller Guide demonstrated how you might poll for updates from the table API of your PDI and then configure an inbound Message to process that data. This Guide will also demonstrate how you might poll for updates from the table API of your PDI, but will also require that we store local data in order to decide which Message to use and then configure multiple inbound Messages to process that data

    Definitions

    It is not always possible for a remote system to send us the data. In such cases, we can make a scheduled request for it using Pollers. We can setup, execute and process those Requests using Poll Processors.

    Poller

    A poller defines the frequency of polling and which logic to use. It is effectively a scheduled job which ties together an Integration and Poll Processor. Although a Poller belongs to only one Integration, an Integration can have multiple Pollers.

    Poll Processor

    A Poll Processor contains the logic that will be applied when polling a remote system for data. It contains three main scripts:

    Setup Script

    The Setup Script is used to build the environment for the poll and define what it will do (for example, create/setup the URL that will be called).

    Request Script

    The Request Script is used to reach into the remote system and execute the request. This is usually done by making a REST call to the URL defined in the Setup Script.

    Response Script

    The Response Script is used to process the information returned from the remote system.

    Warning

    Do not build integrations directly within the Unifi application scope. This can create issues with upgrades and application management.

    Approach

    As well as storing and checking some returned data in order to evaluate when the data was changed and which system has made the updates (we don’t want to pull back data we have changed), we will also need to store and check other data in order to decide which Message to use to process that data.

    We will begin by polling for updates and then process those requests using multiple Messages in Unifi.

    1

    Name

    The name of the ServiceNow process being integrated.

    <SN Process Name> (i.e. Incident)

    2

    API Name*

    The unique name of this process for use with the API.

    <your_unique_api>

    3

    Target table

    The primary target or process table that this integration uses.

    'Incident' [incident]

    4

    Reference field

    The field on the target table that is used as the reference for the external system.

    'Number'

    5

    Description

    Describe what this Process is for.

    <Your description>

    Field

    Description

    Value

    1

    Message name

    The message name that is unique for this integration.

    'CreateIncidentResponse'

    2

    Type

    The primary purpose of the message.

    'Response'

    3

    Direction

    The direction(s) this message is configured to support. (Choices: Inbound, Outbound, Bidirectional)

    'Inbound'

    #

    Field

    Description

    Value

    7

    Stage to Target (Inbound)

    The script to run.

    Replace the commented out instructions with the following code: bond.setOpen();

    Fields'
    Field Maps
    Bonds

    Integration

    This is what defines the connection between a Process and the single system it's connecting with. It is also where most of the configuration and settings are stored.

    New Integration

    Back in the Unifi Integration Designer window, after clicking either on the '+' tile or 'New Integration', you are given a 'New Integration' modal to complete.

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

    Your 'New Integration' modal should look like this:

    4) Click Create.

    You will be redirected to the Details page of the newly created Integration.

    Icons

    Before continuing we would like to draw your attention to some of the relevant icons that are now visible down the left hand navigation strip.

    The icons are:

    a) 'Integration' icon: Opens the current integration's Details page.

    b) 'Messages' icon: Opens the current integration's Messages page.

    c) 'Fields' icon: Opens the current integration's Fields page.

    d) 'Field Maps' icon: Opens the current integration's Field Maps page.

    e) 'Documentation' icon: Opens the automatically generated documentation for the current integration. (Another awesome feature in Unifi.)

    f) 'Connections' icon: Opens the current integration's Connections page.

    Details

    The Details page of your Integration should look like this:

    5) Navigate to Integration > Message Identification.

    Message Identification Fields

    Unifi needs to identify the name of the inbound message in order to know how to process the inbound data.

    6) Update the code in the 'Identify message script' field so that it looks like this:

    The Message Identification form should look like this:

    7) Navigate to Settings > Feedback.

    Feedback Settings Fields

    The Feedback fields to be configured for the Integration record are as follows:

    The Feedback Settings form should look like this:

    All of the remaining 'Settings' values are to be left as-is:

    • Attachments Settings

    • Bond Settings

    All of the 'Error handling' values are to be left as-is:

    9) Click Save.

    10) Click the 'Connections' icon to move on and configure the Connection.

    ResolveIncident Message

    The ResolveIncident Message is an update type message that we will configure to deal specifically with our resolve scenario (resolve the bonded records).

    Again, after clicking the 'Messages' icon, you are directed to the following screen (note: the five previously configured messages are now visible in the list):

    1) Click the ellipsis to the right of the UpdateIncident Message & then click Copy.

    Rather than create the ResolveIncident Message from scratch, it will be quicker to copy the UpdateIncident Message and make some minor changes.

    Copy Message Modal

    The fields to edit for the Copy Message modal are as follows:

    Your Copy Message modal should look like this:

    3) Click Copy.

    You will be redirected to the Details page of the newly created ResolveIncident Message.

    Bond Fields

    Navigate to Message > Bond.

    The Bond fields to be edited are as follows:

    Your Bond form should look like this:

    6) Navigate to Outbound > Trigger.

    Outbound Trigger Fields

    The Outbound Trigger (as required)* fields to be edited are as follows:

    *Outbound condition (as required):

    It is not necessary for you to enter a condition. The value given is an example. You may create any condition (or not) to align with your business process requirements. in this case it makes sense to send the Resolve message when the Incident is Resolved.

    Your Outbound Trigger form should look like this:

    9) Click Save.

    We are now ready to configure the Fields for our ResolveIncident Message.

    ResolveIncidentInbound Message

    We will configure another inbound update type message to process the data returned from the poll and update our target record.

    Rather than create the ResolveIncidentInbound Message from scratch, it will be quicker to copy the UpdateIncidentInbound Message and make some minor changes.

    Click on the 'Messages' icon to open the Messages page.

    1) Click the ellipsis to the right of the UpdateIncidentInbound Message & then click Copy.

    Copy Message Modal

    The fields to edit for the Copy Message modal are as follows:

    Your Copy Message modal should look like this:

    3) Click Copy.

    You will be redirected to the Details page of the newly created ResolveIncidentInbound Message.

    Details Fields

    The Details fields to be edited are as follows:

    Your Details form should look like this:

    5) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be edited are as follows:

    Your Bond form should look like this:

    9) Click Save.

    We are now ready to configure the Fields for our ResolveIncidentInbound Message.

    Test ResolveIncidentInbound

    Follow these steps to test the ResolveIncidentInbound Message.

    Resolve Test Incident

    In the remote instance (your PDI), navigate to < Your Incident > created in the earlier test.

    Update the Incident record as follows:

    #

    Field

    Your Incident record should look like this:

    4) Right-click & Save.

    Poll for Updates

    Back in the originating instance, navigate to & open < Your Poller >. Click Execute Now.

    Open the corresponding Poll Request & confirm that the Incident was found (and the Message name was ResolveIncidentInbound):

    View the Transactions that have been sent. This can be done either in Native ServiceNow, or in the Unifi Operations Portal.

    Navigate to [ws] Unifi > Transport > Transactions.

    Navigate to [ws] Unifi > Unifi Operations Portal.

    We can see that the ResolveIncidentInbound message has been received, is Complete & Accepted and displays the relevant Incident & Bond numbers.

    Confirm the Transaction has updated the bonded ticket in the originating instance:

    We can see that the State, Resolution code & Resolution notes have been updated on the bonded ticket.

    Navigate to the Notes tab to view the Activities stream:

    We can see that the update has also been logged in the Activities stream.

    Poller

    A Poller is a configuration record which defines the frequency of polling and which logic to use.

    A Poller is a configuration record which defines the frequency of polling and which logic to use (the logic itself is defined in the Poll Processor). Each time it is run, it creates a corresponding Poll Request record.

    New Poller

    Click the 'Pollers' icon & then New.

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

    *These fields are mandatory, or automatically defaulted to true.

    Your New Poller modal should look like this:

    5) Submit and view to further configure the Poller.

    Details

    The fields to be configured for the Details form are as follows:

    Your Details form should look like this:

    7) Navigate to Scheduling.

    Scheduling

    The fields to be configured for the Scheduling form are as follows:

    *This field is mandatory.

    Your Scheduling form should look like this:

    10) Save the Poller.

    In order to process the inbound Requests, we next need to configure our Inbound Message.

    Incident Create Poller Guide

    Follow this guide to configure a poller integration - polling the table API of your Personal Developer Instance (PDI) for creates only. This is the third of five Poller Guides. See 'Scope' for more.

    Welcome

    We will be configuring a Poller and Poll Processor in order to pull Incident records which have been created in an external instance and pass the data to Unifi. We will then configure the relevant Messages in order to process and respond to that data.

    If you have been following along with the Outbound Incident Guide and each of the previous Poller Guides you will know that they are given as examples of how you might configure such integrations. They are not meant to be prescriptive. The same applies here.

    Having said that, this Guide has been written to follow on from those previous ones and has been structured accordingly.

    Scope

    This document will guide you through an example of how you might configure a poller integration - polling the table API of your Personal Developer Instance (PDI).

    This Guide is complementary to the Outbound Incident Guide. It assumes that both the Integration and the Connection are still in place and will be using those same elements as configured there. It also assumes that you know how to use the REST API of your PDI to query for information and read ticket data.

    If you haven’t completed the Outbound Incident Guide, please review & complete the following sections of that document, as they must be in place before continuing with this Guide:

    This document is complementary to and builds on the Incident Update Poller Guide. As such, it assumes that the changes made in that Guide are still in place and will make use of some of those same elements.

    If you haven’t completed the Incident Update Poller Guide, please review & complete the following sections of that document at least, as they must be in place before continuing with this Guide:

    Both the Incident Update Poller Guide and the Incident Multiple Message Poller Guide demonstrated how you might poll for updates from the table API of your PDI and then configure inbound Messages to process that data. This Guide will demonstrate how you might poll for newly created, unbonded records from the table API of your PDI and then configure an inbound Create Message (along with its outbound Receipt) to process and respond to that data.

    Definitions

    It is not always possible for a remote system to send us the data. In such cases, we can make a scheduled request for it using Pollers. We can setup, execute and process those Requests using Poll Processors.

    Poller

    A poller defines the frequency of polling and which logic to use. It is effectively a scheduled job which ties together an Integration and Poll Processor. Although a Poller belongs to only one Integration, an Integration can have multiple Pollers.

    Poll Processor

    A Poll Processor contains the logic that will be applied when polling a remote system for data. It contains three main scripts:

    Setup Script

    The Setup Script is used to build the environment for the poll and define what it will do (for example, create/setup the URL that will be called).

    Request Script

    The Request Script is used to reach into the remote system and execute the request. This is usually done by making a REST call to the URL defined in the Setup Script.

    Response Script

    The Response Script is used to process the information returned from the remote system.

    Warning

    Do not build integrations directly within the Unifi application scope. This can create issues with upgrades and application management.

    Approach

    We will need to store and check some returned data in order to evaluate when the data was changed and which system has made the updates to the data (we don’t want to pull back data we have changed).

    We will begin by polling for newly created, unbonded records only and processing those requests using a create message in Unifi.

    We will also need to make some additional changes in order to identify which unbonded records to poll.

    Poller

    A Poller is a configuration record which defines the frequency of polling and which logic to use.

    A Poller is a configuration record which defines the frequency of polling and which logic to use (the logic itself is defined in the Poll Processor). Each time it is run, it creates a corresponding Poll Request record.

    New Poller

    Click the 'Pollers' icon & then New.

    Alternatively, you can edit the previously configured 'Update Poller' (changing the Poll Processor & Description). (There is no need to have two pollers polling for updates every 5 minutes, so if creating a new Poller, remember to deactivate the previous one.)

    The fields to be configured for our Poller record are as follows:

    *These fields are mandatory, or automatically defaulted to true.

    Your New Poller modal should look like this:

    5) Submit and view to further configure the Poller.

    Details

    The fields to be configured for the Details form are as follows:

    Your Details form should look like this:

    7) Navigate to Scheduling.

    Scheduling

    The fields to be configured for the Scheduling form are as follows:

    *This field is mandatory.

    Your Scheduling form should look like this:

    10) Save the Poller.

    In order to process the inbound Requests, we need to configure our Inbound Messages.

    CreateIncidentInboundReceipt Message

    We will configure an outbound receipt message to respond to the data returned from the poll and update the originating record in the remote instance with the correlation id.

    New Message Modal

    Click the 'Messages' icon, then New.

    The fields to be configured for the CreateIncidentInboundReceipt New Message modal are as follows:

    #

    Your CreateIncidentInboundReceipt New Message modal should look like this:

    5) Click Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    Your Response form should look like this:

    7) Navigate to Outbound > Settings.

    Outbound Settings Fields

    The Outbound Settings fields to be configured are as follows:

    Your Outbound Settings form should look like this:

    10) Click Save.

    We are now ready to configure the Fields for our CreateIncidentInboundReceipt Message.

    Trigger

    The Trigger is a Business Rule which stipulates the conditions under which Messages will be sent for the Process concerned.

    Business Rule Fields

    When configuring a Trigger (Business Rule) on a table to be integrated, make sure one doesn’t exist already. If you have more than one, you will make duplicate updates.

    Poller

    A Poller is a configuration record which defines the frequency of polling and which logic to use.

    A Poller is a configuration record which defines the frequency of polling and which logic to use (the logic itself is defined in the Poll Processor). Each time it is run, it creates a corresponding Poll Request record.

    New Poller

    Click the 'Pollers' icon & then New.

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

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    
    
    if (x_snd_eb.ws_console.hasError()) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    bond.setOpen();
    Connection
    Message Identification
    Edit Incident Form
    Edit CreateIncident Message
  • Connection

  • Edit CreateIncident Message

  • Process
    Integration
    Message Identification
    Edit Incident Form

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'ResolveIncident'

    #

    Field

    Description

    Value

    4

    Bond suspended

    Process this message when the bond state is Suspended (internal suspend).

    <true>

    5

    Bond vendor suspended

    Process this message when the bond state is Vendor suspended (external suspend).

    <true>

    #

    Field

    Description

    Value

    7

    Outbound condition*

    The condition that the ServiceNow record must meet to trigger this message being processed.

    'State > changes to > Resolved'

    8

    Outbound condition*

    The script that must be met for the message to be processed. Use current to get access to the triggering record.

    [Blank]

    Hotfixes

    Unifi can be patched between releases by using a special Script Include called hotfix. This page contains any hotfixes that have been made for this version. Follow the instructions to apply them.

    If you find a bug in Unifi we may issue a hotfix so you can get the features you need without having to upgrade.

    Unifi has a Script Include called hotfix. Simply replace the script in the hotfix Script Include with the one shown below and you will instantly have access to the fixes.

    These hotfixes will be shipped as real fixes with the next version of Unifi, so make sure you have the correct hotfix for your version.

    /**
     * Executes a child function corresponding to the object's type property.
     * The object is passed to the child function so methods and properties can be overridden.
     *
     * @param  {Object} obj The full class object to be patched.
     */
    function hotfix(obj) {
      var type = typeof obj === 'function' ? obj.prototype.type : obj.type;
      if (type && typeof hotfix[type] === 'function') {
        hotfix[type](obj);
      }
    }
    
    hotfix.version = '2.2.1.4';
    
    hotfix.EventAction = function (EventAction) {
    
      /**
       * Process this Event action given the current record
       * @param  {[type]} current [description]
       * @return {[type]}         [description]
       */
      EventAction.prototype.process = function process(current) {
        // Check if we have condition script, and if so does it match?
        if (this.isAdvanced() && !this._runScript('condition_script', { current: current })) {
          return;
        }
    
        // Check condition filter against the given table, and check if it matches
        // the limit
        if (!this.isAdvanced() && !this.doesTriageFilterMatch()) {
          return;
        }
    
        // If either of the above match, run the action script
        this._runScript('action_script', { current: current });
      };
    
      /**
       * Runs the Event Actions filter against its table and checks with the limit field
       * to determine if the threshold has been met.
       *
       * @return {Boolean}
       */
      EventAction.prototype.doesTriageFilterMatch = function doesTriageFilterMatch() {
        var ga,
            count;
    
        // If we do not have a table then we cannot run the filter, detaults to a correct match
        if (this.getValue('table') == null) {
          ws_console.debug('Table not found, triage matches');
          return true;
        }
    
        ga = new GlideAggregate(this.getValue('table'));
        ga.addEncodedQuery(this.getValue('filter'));
        ga.addAggregate('COUNT');
        ws_console.logQuery(ga);
    
        count = ga.next() ? ga.getAggregate('COUNT') : 0;
        ws_console.debug('Record count is %0', [count]);
    
        return (count >= this.getValue('limit'));
      };
    
      /**
       * Finds all active event actions that match the given criteria. Each matching Event Action
       * is then process to ascertain whether the action should be executed or not, i.e.
       * if the conditions have been met.
       *
       * @param  {String} event        Event name to find Event Actions for
       * @param  {GlideRecord} current The GlideRecord that this event was triggered for
       * @param  {String} integration  Integration sys_id
       * @param  {String} message      Message sys_id
       */
      EventAction.process = function process(event, current, integration, message) {
        var gr,
            query = [],
            config = new Process().getConfig();
    
        gr = new GlideRecord('x_snd_eb_event_action');
        gr.addQuery('event', '=', event);
        gr.addQuery('active', '=', 'true');
        if (integration) {
          query.push('integration=' + integration);
          query.push('ORintegrationISEMPTY');
          if (message) {
            query.push('message=' + message);
            query.push('ORmessageISEMPTY');
          } else {
            query.push('messageISEMPTY');
          }
        } else {
          query.push('integrationISEMPTY');
        }
        gr.addEncodedQuery(query.join('^'));
        gr.orderByDesc('integration');
        gr.orderByDesc('message');
        ws_console.logQuery(gr);
    
        while(gr.next()) {
          new EventAction(config, gr).process(current);
        }
      };
    };
    
    hotfix.Transaction = function (Transaction) {
    
      // Fix transaction/bond domains for inbound create messages
      Transaction.prototype.setBond = function setBond(bond) {
        this.bond = bond;
        this.setValue('bond', bond.getValue('sys_id'));
    
        // The bond will be created in global so we should update it to match
        // incoming transactions which are created in the domain of the integration user .
        if (bond.getValue('sys_domain') == 'global' && bond.isNew() && this.getValue('direction') == 'Inbound') {
          bond.setValue('sys_domain', this.getValue('sys_domain'));
        }
    
        this.setValue('sys_domain', bond.getValue('sys_domain'));
      };
    };
    
    hotfix.Message = function (Message) {
      Message.prototype.evaluateScript = function evaluateScript(record, element, vars) {
        var source = vars.source;
        var result;
        vars.message = this.getRecord();
        vars.variables = this.getIntegration().getActiveConnection().getVariables();
        if (vars.stage) {
          vars.$stage = vars.stage.$stage;
        }
        result = utils.evaluateScript(record, element, vars);
    
        // UN-1003: reset source - GlideScopedEvaluator changes the GlideRecord object
        // to ScopedGlideRecord which breaks object equality.
        if (source && source.$model) {
            source.$model.setRecord(source);
        }
    
        return result;
      };
    }
    • General

    • Timeouts

    • Retry

    #

    Field

    Description

    Value

    1

    Name

    The name of the integration.

    <Your Name>

    2

    Service type

    The type of web service this integration is using (SOAP/REST).

    'REST'

    3

    Message format

    Automatically pre-process incoming messages for simpler message scripting. (Choices: XML, JSON, Advanced)

    'JSON'

    #

    Field

    Description

    Value

    8

    Enable UI messages

    Allow information and error messages to be shown to the user as UI Notifications. Only applies to certain notifications.

    <true>

    Process this message when the bond state is Vendor suspended.

    <true>

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'ResolveIncidentInbound'

    #

    Field

    Description

    Value

    4

    Description

    The description for this message and the requirement it is meeting.

    <Your description>

    #

    Field

    Description

    Value

    6

    Bond pending

    Process this message when the bond state is Pending.

    <true>

    7

    Bond suspended

    Process this message when the bond state is Suspended.

    <true>

    8

    Bond vendor suspended

    The frequency at which the Poller should run.

    'Periodically'

    4

    Run as

    Poller will run with credentials of specified user.

    <Your Inbound user> (from Connetion)

    *

    Active

    Set to true to use this Poller record for processing.

    <true>

    #

    Field

    Description

    Value

    1*

    Name

    The name of your Poller.

    <Your Name>

    2*

    Poll processor

    The Poll Processor to use when running this Poller.

    <Your Poll Processor>

    3

    #

    Field

    Description

    Value

    6

    Description

    A description of what this Poller is for and/or how it works.

    <Your description>

    #

    Field

    Description

    Value

    8*

    Repeat interval

    The interval at which the Poller should repeat.

    '05' (Minutes)

    9

    Starting

    The date/time the Poller should start.

    <Your Start date/time>

    Run

    In the native ServiceNow window, navigate to System Definition > Business Rules. Click New.

    The Business Rule fields to be configured are as follows:

    #

    Field

    Description

    Value

    1

    Name

    The name of the business rule.

    <Your Name>

    2

    Table

    The table that this business rule will run on.

    ‘Incident’ [incident]

    3

    The top section of your Business Rule record should look like this:

    When to run Fields

    Click on the 'When to run' tab and configure the fields as follows:

    #

    Field

    Description

    Value

    5

    When

    When this business rule should execute relative to the database operation.

    'before'

    6

    Insert

    Select this check box to execute the business rule when a record is inserted into the database.

    <true>

    7

    Your 'When to run' tab should look like this:

    Advanced Fields

    Click on the 'Advanced' tab and configure the fields as follows:

    #

    Field

    Description

    Value

    9

    Script*

    The script to run.

    Replace the entire contents of the script field with your business rule code, substituting the name of your business rule (see below). E.g. 'Business rule: Unifi Incident trigger'

    *Script:

    The code in the script field should look like this:

    Your 'Advanced' tab should look like this:

    10) Click Submit.

    The main elements are now in place for our Integration to work. We are now ready to configure and test each of our Scenarios in turn.

    #

    Field

    Description

    Value

    1*

    Name

    The name of your Poller.

    <Your Name>

    2*

    Poll processor

    The Poll Processor to use when running this Poller.

    <Your Poll Processor>

    3

    Run

    The frequency at which the Poller should run.

    'Periodically'

    4

    Run as

    Poller will run with credentials of specified user.

    <Your Inbound user> (from Connetion)

    *

    Active

    Set to true to use this Poller record for processing.

    <true>

    *These fields are mandatory, or automatically defaulted to true.

    Your New Poller modal should look like this:

    5) Submit and view to further configure the Poller.

    Details

    The fields to be configured for the Details form are as follows:

    #

    Field

    Description

    Value

    6

    Description

    A description of what this Poller is for and/or how it works.

    <Your description>

    Your Details form should look like this:

    7) Navigate to Scheduling.

    Scheduling

    The fields to be configured for the Scheduling form are as follows:

    #

    Field

    Description

    Value

    8*

    Repeat interval

    The interval at which the Poller should repeat.

    '15' (Minutes)

    9

    Starting

    The date/time the Poller should start.

    <Your Start date/time>

    *This field is mandatory.

    Your Scheduling form should look like this:

    10) Save the Poller.

    In order to process and respond to the inbound Requests, we next need to configure our Messages.

    Description

    Value

    1

    State

    The Incident lifecycle state.

    ‘Resolved’

    2

    Resolution code

    The Incident resolution code.

    <Your Resolution code>

    3

    Resolution notes

    The Incident resolution notes.

    <Your Resolution notes>

    #

    Field

    Description

    Value

    1*

    Name

    The name of your Poller.

    <Your Name>

    2*

    Poll processor

    The Poll Processor to use when running this Poller.

    <Your Poll Processor>

    3

    Run

    The frequency at which the Poller should run.

    'Periodically'

    4

    Run as

    Poller will run with credentials of specified user.

    <Your Inbound user> (from Connetion)

    *

    Active

    Set to true to use this Poller record for processing.

    <true>

    #

    Field

    Description

    Value

    6

    Description

    A description of what this Poller is for and/or how it works.

    <Your description>

    #

    Field

    Description

    Value

    8*

    Repeat interval

    The interval at which the Poller should repeat.

    '05' (Minutes)

    9

    Starting

    The date/time the Poller should start.

    <Your Start date/time>

    Field

    Description

    Value

    1

    Message name

    The message name that is unique for this integration.

    'CreateIncidentInboundReceipt'

    2

    Type

    The primary purpose of the message.

    'Receipt'

    3

    Direction

    The direction(s) this message is configured to support.

    'Outbound'

    4

    Description

    The description for this message and the requirement it is meeting.

    <Your description>

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    #

    Field

    Description

    Value

    8

    Path

    A path to append to the URL defined in the connection. Specify a full URL to override the connection. Define inline scripts to reference Stage to Request script variables by wrapping code in braces {}, e.g. /{transaction.message_id}.

    '/{bond.getValue("external_reference")}'

    9

    Action method

    The SOAP Action or the REST Method to use for this message. If this field is empty the SOAP Action will default to the message name and the REST Method will default to POST.

    'PUT'

    Trigger

    The Trigger is a Business Rule which stipulates the conditions under which Messages will be sent for the process concerned.

    Business Rule Fields

    When configuring a Trigger (Business Rule) on a table to be integrated, make sure one doesn’t exist already. If you have more than one, you will make duplicate updates.

    In the native ServiceNow window, navigate to System Definition > Business Rules > New.

    The Business Rule fields to be configured are as follows:

    The top section of your Business Rule record should look like this:

    'When to run' Tab Fields

    Click on the When to run tab and configure the fields as follows:

    Your 'When to run' tab should look like this:

    'Advanced' Tab Fields

    Click on the Advanced tab and configure the fields as follows:

    *Script:

    The code in the script field should look like this:

    Your 'Advanced' tab should look like this:

    10) Click Submit.

    The main elements are now in place for our Integration to work. We are now ready to configure and test each of our Scenarios in turn.

    Test UpdateIncident

    Follow these steps to test the UpdateIncident Message.

    Update the Incident

    Navigate to < Your Incident > created in the previous test.

    Your Incident record should look like this:

    1) Enter < Your Work notes > in the 'Work notes' field.

    2) Click Post.

    You should see an Info Message, confirming the UpdateIncident Message is being sent to your Integration:

    The Work note is added to the Activities stream on the 'Notes' tab:

    View the Bond

    Click through to the Bond record from the related list on the Incident.

    Your Bond record should have been updated as follows:

    3) History:

    • < History updated on the Bond > (Sending UpdateIncident...)

    4) Transaction:

    • Message: 'Updateincident'

    • Direction: 'Outbound'

    • Transaction state: 'Complete' (The data has been successfully transported)

    • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

    View the Transaction

    Click through to the Transaction record from the related list on the Bond.

    Your Transaction record should look like this:

    5) Transaction details:

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    6) Errors:

    • Error: (If there was a transactional error the Transaction state would show as 'Error' and the details would be captured here).

    • Process error: (If there was a process error the Process state would show as 'Rejected' and the details would be captured here)

    7) Stages:

    • Direction: 'Outbound' & 'Inbound'

    • Message: 'UpdateIncident' & 'Receipt'

    • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

    • External reference: < External system's ticket reference >

    View the Stage

    Click through to the Outbound Stage record from the related list on the Transaction. (If you wish, you could also do the same for the Inbound Stage record.)

    Check the values in the fields match what you expect.

    Your Stage record should look like this:

    8) Stage details:

    • Direction: 'Outbound'

    • External reference: < External system's ticket reference >

    • Internal reference: < ServiceNow ticket reference >

    • Message: 'UpdateIncident'

    9) Mapped stage fields:

    • work_notes: < Your Work note >

    View the HTTP Request

    Click through to the Outbound HTTP Request record from the related list on the Transaction. (If you wish, you could also do the same for the Inbound HTTP Request record.)

    Your HTTP Request record should look like this:

    10) HTTP Request details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Transaction: < Your Transaction >

    • Message: 'UpdateIncident'

    11) Response details:

    • Status code: '200'

    • Response headers: < The header of the response being received >

    • Response payload: < The payload of the response being received >

    Compare with the External System's Incident

    Navigate to the corresponding Incident in the external system.

    Check the values in the fields match those you noted when you saved the Incident in the internal system.

    Your external system's Incident record should look like this (depending on the system you're integrating with, your record may look different; the important matter is that the values match):

    12) Activities: < Your Work note > (added by < your.external.system.user >)

    Challenge

    • Repeat the steps above - this time placing a check in the 'Additional comments (Customer visible)' checkbox.

    • What do you expect to happen?

    As when testing our CreateIncident Message, if completing this test after having integrated with the external system (as opposed to connecting to your own instance), it would be good to test the UpdateIncident Message in both directions.

    We are now ready to move to the Resolve Scenario.

    CreateIncidentReceipt Message

    The CreateIncidentReceipt Message is the asynchronous receipt that is sent after processing the Createincident Message.

    After clicking the 'Messages' icon, you will see the following screen (note: the previously configured message is visible in the list):

    1) Click New.

    New Message Modal

    The fields to be configured for the CreateIncidentReceipt New Message modal are as follows:

    Your CreateIncidentReceipt New Message modal should look like this:

    5) Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    Your Response form should look like this:

    7) Navigate to Inbound > Settings.

    Inbound Settings Fields

    The Inbound Settings fields to be configured are as follows:

    The code in the 'Reference lookup script' field should look like this:

    Reference lookup script: In an asynchronous integration it's important to identify which message an asynchronous receipt is replying to. This script extracts the transaction's unique identifier.

    In the case of an inbound create/update it would return their external message id (source id) to identify which transaction our asynchronous receipt belongs to. In the case of an inbound asynchronous receipt it would return our internal message id (target id) to identify which transaction their asynchronous receipt belongs to.

    Your Inbound Settings form should look like this:

    9) Navigate to Advanced > Script Editor.

    Script Editor Fields

    The Scripts are where the request processing and data mapping occurs. They are also the place where Bond state & ownership are set.

    When you first open the Script Editor, you will see the following:

    Having visibility of your message scripts in the one pane makes scripting so much more efficient.

    Because we are dealing with an inbound message, we can adjust the view to only show the 'Payload to Stage' & 'Stage to Target' script fields.

    10) Navigate to View > Inbound.

    Your Script Editor fields will initially look like this:

    Scripts

    We will primarily by utilising OOTB Fields & Field Maps to configure our Message Scripts. In the current release, however, there is no OOTB Field Map record with which we can set the state on the Bond. We shall, therefore, script that manually. For more information , see the ' & '' pages in our technical documentation.

    The Script Editor fields to be configured are as follows:

    The code in the 'Stage to Target' script field should look like this:

    Your Script Editor fields should now look like this:

    12) Click 'Save'.

    13) Click 'Close' to navigate back to the Message.

    We are now ready to configure the Fields for our CreateIncidentReceipt Message.

    Test UpdateIncident

    We will test our UpdateIncident Message.

    Update The Incident

    Navigate to < Your Incident > created in the previous test.

    Your Incident record should look like this:

    1) Enter < Your Work notes > in the 'Work notes' field.

    2) Click Post.

    The following activities are added to the 'Notes' tab (confirming sending the UpdateIncident Message to your integration):

    View the Bond

    Click through to the Bond record from the related list on the Incident.

    Your Bond record should have been updated as follows:

    3) History:

    • < History updated on the Bond > (Sending UpdateIncident...)

    4) Transaction:

    • Message: 'Updateincident'

    • Direction: 'Outbound'

    • Transaction state: 'Complete' (The data has been successfully transported)

    • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

    View the Transaction

    Click through to the Transaction record from the related list on the Bond.

    Your Transaction record should look like this:

    5) Transaction details:

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    6) Errors:

    • Error: (If there was a transactional error the Transaction state would show as 'Error' and the details would be captured here).

    • Process error: (If there was a process error the Process state would show as 'Rejected' and the details would be captured here)

    7) Stage:

    • Direction: 'Outbound'

    • Message: 'UpdateIncident'

    • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

    • External reference: < External system's ticket reference >

    View the Stage

    Click through to the Stage record from the related list on the Transaction.

    Check the values in the fields match what you expect.

    Your Stage record should look like this:

    8) Stage details:

    • Direction: 'Outbound'

    • External reference: < External system's ticket reference >

    • Internal reference: < ServiceNow ticket reference >

    • Message: 'UpdateIncident'

    9) Mapped stage fields:

    • Work notes: < Your Work note >

    View the HTTP Request

    Click through to the HTTP Request record from the related list on the Transaction.

    Your HTTP Request record should look like this:

    10) HTTP Request details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Transaction: < Your Transaction >

    • Message: 'UpdateIncident'

    11) Response details:

    • Status code: '200'

    • Response headers: < The header of the response being received >

    • Response payload: < The payload of the response being received >

    Compare with the External System's Incident

    Navigate to the corresponding Incident in the external system.

    Check the values in the fields match those you noted when you saved the Incident in the internal system.

    Your external system's Incident record should look like this (depending on the system you're integrating with, your record may look different; the important matter is that the values match):

    12) Activities: < Your Work note > (added by < your.external.system.user >)

    Challenge

    • Repeat the steps above - this time placing a check in the 'Additional comments (Customer visible)' checkbox.

    • What do you expect to happen?

    CreateIncidentInboundReceipt Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the CreateIncidentInboundReceipt Message.

    Field: incident.number

    The ‘incident.number’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we first created the Message level record when completing the Incident Update Poller Guide. We will now create its Message level counterpart.

    From the CreateIncidentInboundReceipt Message, navigate to Message > Fields.

    Your CreateIncidentInboundReceipt Fields page should look like this:

    1) Find the incident.number (Integration level) Field & set Active to true.

    The ‘Build Integration’ button becomes visible in the banner and the empty circle icon next to the Field name turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field) when we set Active to true. (Note: the empty 'circle icon' indicates that the Integration level Field is available to add to the Message.).

    By setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart.

    Build

    We don't need to configure any more the Field records for the CreateIncidentInboundReceipt Message, so we are ready to build our message scripts.

    2) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    3) Navigate to Advanced > Script Editor > View > Outbound to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    We will look at the Message Scripts in turn.

    Source to Stage:

    Your Source to Stage Message Script should look like this:

    Stage to Request:

    Your Stage to Request Message Script should look like this:

    Next, we'll configure the CreateIncidentInbound Message.

    Connection

    The Connection allows messages to be sent and received and stores all the authentication details of the Integration specific to a single environment.

    Inbound User

    Before configuring the Connection, you need to ensure you have a user in the instance to use as the Inbound user for the Integration. To configure your Inbound user:

    In the native ServiceNow window, navigate to User Administration > Users. Click New.

    The fields to be configured for the User record are as follows:

    UpdateIncident Message

    The UpdateIncident Message is an update type message that sends updates to the bonded record.

    After submitting the 'Response' Message, you were redirected to the Messages page (note: the three previously configured messages are now visible in the list):

    1) Click New.

    New Message Modal

    The fields to be configured for the UpdateIncident New Message modal are as follows:

    CreateIncident Message

    The CreateIncident Message will create a ticket on the target table of the integrated system.

    After clicking the 'Messages' icon, you will see the following screen (note: the previously configured message is visible in the list):

    1) Click New.

    New Message Modal

    The fields to be configured for the CreateIncident New Message modal are as follows:

    Connection

    The Connection allows messages to be sent and received and stores all the authentication details of the Integration specific to a single environment.

    Integration User

    Before we configure our Connection, we need to ensure we have a user in the instance to use as the Inbound user for our Integration. To configure our Integration user:

    In the native ServiceNow window, navigate to User Administration > Users. Click New.

    The fields to be configured for the User record are as follows:

    Test ResolveIncident

    Follow these steps to test the ResolveIncident Message.

    Resolve the Incident

    Navigate to < Your Incident > created in the earlier test.

    Update the Incident record as follows:

    Test Update Poll

    You should have successfully configured a Poll Processor, Poller and an inbound update message. You should also have made further changes to allow for message & bond identification. Now to test.

    It may help to turn off the Poller we created (set Active to 'false') whilst conducting these tests and to manually execute it as required (this can still be done even if the Poller is inactive). This is so that we don't have to wait for the Poller to run, but rather manually activate it when needed by clicking 'Execute Now'.

    To turn off the Poller, in the Unifi Integration Designer window, navigate to the 'Pollers' icon & set Active to false.

    In order to test our integration we will need some bonded tickets in the remote instance. If there aren't any already in place, then they'll need to be created.

    Test UpdateIncidentInbound

    Follow these steps to test the UpdateIncidentInbound Message.

    To test our integration we will need some bonded tickets in the remote instance. If there aren't any already in place, then they'll need to be created.

    Create Test Incidents

    In native ServiceNow, navigate to Incident > Create New.

    The Incident fields to configure are as follows:

    Test Create Poll

    You should have successfully configured a Poll Processor and Poller. You should also have configured an inbound create type Message and its outbound receipt. Follow these steps to test.

    It may help to turn off the Poller we created (set Active to 'false') whilst conducting these tests and to manually execute it as required (this can still be done even if the Poller is inactive). This is so that we don't have to wait for the Poller to run, but rather manually activate it when needed by clicking 'Execute Now'.

    To turn off the Poller, in the Unifi Integration Designer window, navigate to the 'Pollers' icon & set Active to false.

    In order to test our Integration we will need to create test Incidents in the remote instance.

    function identify(payload) {
    
      return (payload.message.name || '') + '';
    
    }
    (function executeRule(current, previous /*null when async*/) {
    
        x_snd_eb.snd_console.execute('Business rule: Unifi Incident trigger', function () {
            x_snd_eb.ActivityLog.setDocument(current, current.getTableName());
            x_snd_eb.Message.processOutbound(current);
        });
    
    })(current, previous);

    Active

    Set to true to enable this business rule.

    <true>

    4

    Advanced

    Set to true to reveal the advanced version o the form.

    <true>

    Update

    Select this check box to execute the business rule when a record is update.

    <true>

    8

    Order

    The sequence in which this business rule should run.

    '1,000,000,000'

    Set to true to enable this business rule.

    <true>

    4

    Advanced

    Set to true to reveal the advanced version o the form.

    <true>

    Select this check box to execute the business rule when a record is update.

    <true>

    8

    Order

    The sequence in which this business rule should run.

    '1,000,000,000'

    #

    Field

    Description

    Value

    1

    Name

    The name of the business rule.

    <Your Name>

    2

    Table

    The table that this business rule will run on.

    ‘Incident’ [incident]

    3

    #

    Field

    Description

    Value

    5

    When

    When this business rule should execute relative to the database operation.

    'Before'

    6

    Insert

    Select this check box to execute the business rule when a record is inserted into the database.

    <true>

    7

    #

    Field

    Description

    Value

    9

    Script*

    The script to run.

    Replace the entire contents of the script field with your business rule code, substituting the name of your business rule (see below). E.g. 'Business rule: Unifi Incident Trigger'

    Active

    Update

    (function executeRule(current, previous /*null when async*/) {
    
        x_snd_eb.snd_console.execute('Business rule: Unifi Incident Trigger', function () {
            x_snd_eb.ActivityLog.setDocument(current, current.getTableName());
            x_snd_eb.Message.processOutbound(current);
        });
    
    })(current, previous);

    Bond: < Your Bond >

  • Message: 'UpdateIncident'

  • Direction: 'Outbound'

  • Transaction state: 'Complete' (The data has been successfully transported)

  • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

  • Transaction: < Your Transaction >

  • Integration: < Your Integration >

  • Direction: 'Outbound'

  • Request state: 'OK' (There are no errors with the HTTP Request.)

  • Attempt number: < Number of HTTP Request attempts > (Failed requests are retried up to the maximum attempts number as configured on the Integration.)

  • Endpoint URL: < The external system’s access URL >

  • Action Method: 'POST'

  • Request headers: < The header of the request being sent >

  • Request payload: < The payload of the request being sent >

  • 'Bidirectional'

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'CreateIncidentReceipt'

    3

    Type

    The primary purpose of the message.

    'Receipt'

    4

    Direction

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    #

    Field

    Description

    Value

    8

    Reference lookup script

    The script containing functions for extracting internal and external references from the request payload.

    Update the code in the Reference lookup script field so that it looks like the code below

    #

    Field

    Description

    Value

    11

    Stage to Target (Inbound)

    The script to run.

    Replace the commented out instructions with the following code: bond.setOpen();

    Fields'
    Field Maps

    The direction(s) this message is configured to support. (Choices: Inbound, Outbound, Bidirectional)

    Bond: < Your Bond >

  • Message: 'UpdateIncident'

  • Direction: 'Outbound'

  • Transaction state: 'Complete' (The data has been successfully transported)

  • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

  • Transaction: < Your Transaction >

  • Integration: < Your Integration >

  • Direction: 'Outbound'

  • Request state: 'OK' (There are no errors with the HTTP Request.)

  • Attempt number: < Number of HTTP Request attempts > (Failed requests are retried up to the maximum attempts number as configured on the Integration.)

  • Endpoint URL: < The external system’s access URL >

  • Action Method: 'PUT'

  • Request headers: < The header of the request being sent >

  • Request payload: < The payload of the request being sent >

  • #

    Field

    Description

    Value

    1

    User ID

    The id of the user (to be used by the external system for authentication).

    <your.integration_user>

    2

    First name

    The integration user's first name.

    <Your First Name>

    3

    Last name

    The integration user's last name.

    Your User record should look like this:

    Connection

    Although you can set up many connections to enable switching between environments (one connection per environment), it is worth noting that only one connection can be active for an Integration at a time.

    We will, however, set up only one connection in the 'Development' environment.

    Back in the Unifi Integration Designer window, click on the 'Connections' icon, then click New.

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

    #

    Field

    Description

    Value

    6

    Environment

    The environment this connection applies to.

    'Development'

    7

    Endpoint URL

    The external system's access URL.

    <External system Endpoint URL>

    8

    Outbound Connectivity

    The format of the Endpoint URL is as follows:

    https://<your_developer_instance>.service-now.com/api/now/table/incident

    Your New Connection modal should look like this:

    9) Click 'Submit and view'.

    Clicking 'Submit' will redirect you to the list view of the record you're creating. Clicking 'Submit and view' will redirect you to the newly created record.

    Connection Details

    The fields to be configured for the Details form are as follows:

    #

    Field

    Description

    Value

    10

    Authentication

    The authentication method to use for this connection.

    'Basic'

    11

    User*

    The username used in basic authentication.

    <external.system.user>

    12

    *(External) User/Password: As created/set in your PDI.

    **Inbound user: As created above.

    Your Details form should look like this:

    14) Save the Connection.

    We are now ready to step back into the native ServiceNow window to configure the Trigger.

    #

    Field

    Description

    Value

    1

    Message name

    The message name that is unique for this integration.

    'UpdateIncident'

    3

    Type

    The primary purpose of the message.

    'Update'

    2

    Direction

    Your UpdateIncident New Message modal should look like this:

    5) Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    7*

    Async

    Turn this option on if you want inbound processing to occur asynchronously or this message is the first of an asynchronous message pair.

    <false>

    Your Response form should look like this:

    8) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be configured are as follows:

    #

    Field

    Description

    Value

    *

    Bond ownership

    Determine if the sender should own the bond or not in order for this message to be processed? Use 'Ignore' to process regardless of the owner flag. (Choices: Ignore, Must own, Must not own.)

    'Ignore'

    *

    Bond condition type

    The type of conditional check made on the bond. (None: no checks are made. State: checks against the state are made using the conditional checkboxes. Scripted: the 'Bond condition' script is used.)

    'State'

    9

    *These fields are automatically populated.

    Your Bond form should look like this:

    10) Navigate to Outbound > Trigger.

    Outbound Trigger Fields

    The Outbound Trigger fields to be configured (as required)* are as follows:

    #

    Field

    Description

    Value

    11

    Outbound condition*

    The condition that the ServiceNow record must meet to trigger this message being processed.

    <Your condition> e.g. 'Work notes changes' OR 'Additional comments changes'

    *Outbound condition (as required):

    It is not necessary for you to enter a condition. The value given is an example. You may create any condition (or not) to align with your business process requirements.

    Your Outbound Trigger form should look like this:

    12) Navigate to Outbound > Settings.

    Outbound Settings Fields

    The Outbound Settings fields to be configured are as follows:

    #

    Field

    Description

    Value

    13

    Path

    A path to append to the URL defined in the connection. Specify a full URL to override the connection. Define inline scripts to reference Stage to Request script variables by wrapping code in braces {}, e.g. /{transaction.message_id}.

    '/{bond.getValue("external_reference")}'

    14

    Action method

    The SOAP Action or the REST Method to use for this message. If this field is empty the SOAP Action will default to the message name and the REST Method will default to POST.

    'PUT'

    Your Outbound Settings form should look like this:

    15) Click Save.

    We are now ready to configure the Fields for our UpdateIncident Message.

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'CreateIncident'

    3

    Type

    The primary purpose of the message.

    'Create'

    4

    Direction

    Your CreateIncident New Message modal should look like this:

    5) Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'CreateIncidentResponse'>

    7*

    Async

    Turn this option on if you want inbound processing to occur asynchronously or this message is the first of an asynchronous message pair.

    <false>

    *This field is automatically defaulted to true.

    Your Response form should look like this:

    8) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be configured are as follows:

    #

    Field

    Description

    Value

    *

    Bond ownership

    Determine if the sender should own the bond or not in order for this message to be processed? Use 'Ignore' to process regardless of the owner flag. (Choices: Ignore, Must own, Must not own.)

    'Ignore'

    *

    Bond condition type

    The type of conditional check made on the bond. (None: no checks are made. State: checks against the state are made using the conditional checkboxes. Scripted: the 'Bond condition' script is used.)

    'State'

    9

    *These fields are automatically populated.

    Your Bond form should look like this:

    10) Navigate to Outbound > Trigger.

    Outbound Trigger Fields

    The Outbound Trigger fields to be configured (as required)* are as follows:

    #

    Field

    Description

    Value

    11

    Outbound condition*

    The condition that the ServiceNow record must meet to trigger this message being processed.

    <Your condition> e.g. 'Short description contains Starter'

    *Outbound condition (as required):

    It is not necessary for you to enter a condition. The value given is an example. You may create any condition (or not) to align with your business process requirements.

    Your Outbound Trigger form should look like this:

    12) Navigate to Outbound > Settings.

    Outbound Settings Fields

    The Outbound Settings fields to be configured are as follows:

    #

    Field

    Description

    Value

    13

    Action method

    The SOAP Action or the REST Method to use for this message. If this field is empty the SOAP Action will default to the message name and the REST Method will default to POST.

    'POST'

    Your Outbound Settings form should look like this:

    14) Click Save.

    We are now ready to configure the Fields for our CreateIncident Message.

    #

    Field

    Description

    Value

    1

    User ID

    The id of the user (to be used by the external system for authentication).

    <your.integration_user>

    2

    First name

    The integration user's first name.

    <Your First Name>

    3

    Last name

    The integration user's last name.

    Your User record should look like this:

    Connection

    You can set up many connections to enable switching between environments (one connection per environment). However, only one connection can be active for an Integration at a time.

    Remember: When setting up a Connection:

    • Make sure your SOAP and/or REST endpoints are unique.

    • Never use your own User as the Inbound User as it will prevent the integration from working.

    • Always ensure that your Inbound User is NOT used by anyone else for the same Process i.e. if you’re creating a Connection for an Integration on the Incident Process, your Inbound User has to be the only User used by an Integration within that Process.

    We are going to configure a Connection for the Development environment.

    Back in the Unifi Integration Designer window, click on the 'Connections' icon, then click New.

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

    #

    Field

    Description

    Value

    6

    Environment

    The environment this connection applies to.

    'Development'

    7

    Endpoint URL

    The external system's access URL.

    <External system Endpoint URL>

    8

    Outbound Connectivity

    The format of the Endpoint URL is as follows:

    https://<your_instance>.service-now.com/<your_resource_path>

    Your New Connection modal should look like this:

    9) Click Submit and view.

    Clicking 'Submit' will redirect you to the list view of the record you're creating. Clicking 'Submit and view' will redirect you to the newly created record.

    Connection Details

    The fields to be configured for the Details form are as follows:

    #

    Field

    Description

    Value

    10

    Authentication

    The authentication method to use for this connection.

    'Basic'

    11

    User

    The username used in basic authentication.

    <external.system.user>

    12

    Your Details form should look like this:

    Feature Alert: The widget at the bottom of the page now shows the Integration as Active.

    For this Development environment Connection, we have set the Endpoint URL to point to our own instance and used the same Integration User for both Inbound and Outbound (as created above). Being able to connect to our own instance makes it simple and efficient to test our integration (seeing Transactions going out and coming in) before we connect to the external system.

    14) Save the Connection.

    We are now ready to step back into the native ServiceNow window to configure the Trigger.

    Value

    1

    State

    The Incident lifecycle state.

    'Resolved'

    2

    Resolution code

    The Incident resolution code.

    <Your Resolution code>

    3

    Resolution notes

    The Incident resolution notes.

    <Your Resolution notes>

    Your Incident record should look like this:

    4) Right-click & Save.

    You should see an Info Message, confirming the ResolveIncident Message is being sent to your Integration:

    The Activities stream is updated with the details:

    View the Bond

    Click through to the Bond record from the related list on the Incident.

    Your Bond record should have been updated as follows:

    5) History:

    • < History updated on the Bond > (Sending ResolveIncident...)

    6) Transaction:

    • Message: 'Resolveincident'

    • Direction: 'Outbound'

    • Transaction state: 'Complete' (The data has been successfully transported)

    • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

    View the Transaction

    Click through to the Transaction record from the related list on the Bond.

    Your Transaction record should look like this:

    7) Transaction details:

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Bond: < Your Bond >

    • Message: 'ResolveIncident'

    • Direction: 'Outbound'

    • Transaction state: 'Complete' (The data has been successfully transported)

    • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

    8) Errors:

    • Error: (If there was a transactional error the Transaction state would show as 'Error' and the details would be captured here).

    • Process error: (If there was a process error the Process state would show as 'Rejected' and the details would be captured here)

    9) Stages:

    • Direction: 'Outbound' & 'Inbound'

    • Message: 'ResolveIncident' & 'Receipt'

    • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

    • External reference: < External system's ticket reference >

    View the Stage

    Click through to the Outbound Stage record from the related list on the Transaction. (If you wish, you could also do the same for the Inbound Stage record.)

    Check the values in the fields match what you expect.

    Your Stage record should look like this:

    10) Stage details:

    • Direction: 'Outbound'

    • External reference: < External system's ticket reference >

    • Internal reference: < ServiceNow ticket reference >

    • Message: 'ResolveIncident'

    • Transaction: < Your Transaction >

    • Integration: < Your Integration >

    11) Mapped stage fields:

    • close_code: < Your Resolution code >

    • close_notes: < Your Resolution notes >

    • state: '6'

    View the HTTP Request

    Click through to the Outbound HTTP Request record from the related list on the Transaction. (If you wish, you could also do the same for the Inbound HTTP Request record.)

    Your HTTP Request record should look like this:

    12) HTTP Request details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Transaction: < Your Transaction >

    • Message: 'ResolveIncident'

    • Direction: 'Outbound'

    • Request state: 'OK' (There are no errors with the HTTP Request.)

    • Attempt number: < Number of HTTP Request attempts > (Failed requests are retried up to the maximum attempts number as configured on the Integration.)

    • Endpoint URL: < The external system’s access URL >

    • Action Method: 'POST'

    • Request headers: < The header of the request being sent >

    • Request payload: < The payload of the request being sent >

    13) Response details:

    • Status code: '200'

    • Response headers: < The header of the response being received >

    • Response payload: < The payload of the response being received >

    Compare with the External System's Incident

    Navigate to the corresponding Incident in the external system.

    Check the values in the fields match those you noted when you saved the Incident in the internal system.

    Your external system's Incident record should look like this (depending on the system you're integrating with, your record may look different; the important matter is that the values match):

    14) State: 'Resolved'

    15) Activities: < Your Resolution code/notes & State > (added by < your.external.system.user >)

    Navigate to the Resolution Information tab.

    Your Resolution Information tab should look like this:

    16) Resolution code: < Your Resolution code >

    17) Resolution notes: < Your Resolution notes >

    As when testing our previous scenarios, if completing this test after having integrated with the external system (as opposed to connecting to your own instance), it would be good to test the ResolveIncident Message in both directions.

    If you have completed this testing for the first time (sending to your own instance only), you are now ready to move on and look at running Build at the Integration level.

    #

    Field

    Description

    Create Test Incidents

    In the native ServiceNow window, navigate to Incident > Create New.

    The Incident fields to configure are as follows:

    #

    Field

    Description

    Value

    1

    Caller

    Person who reported or is affected by this incident.

    <Your Caller>

    2

    Short description

    A brief description of the incident.

    <Your Short description>

    3

    Though our CreateIncident Message has been configured to map more than just the Short Description & Description fields, we have only filled these fields because that is all we have included in the payload of our Poller.

    Your Incident form should look like this:

    4) Note the Info Message confirming the CreateIncident Message is being sent to your Integration.

    5) Note the Bond is 'Open' and both the Internal & External reference are in place.

    Repeat as necessary so that there are two or three bonded tickets in the remote instance:

    Update from Originating Instance

    Update one of the bonded tickets in the originating instance to cause the UpdateIncident Message to fire:

    View the Transactions that have been sent. This can be done either in Native ServiceNow, or in the Unifi Operations Portal.

    Navigate to [ws] Unifi > Transport > Transactions.

    Navigate to [ws] Unifi > Unifi Operations Portal.

    We can see that the three CreateIncident messages & one UpdateIncident message have been sent. All are Complete & Accepted & display the relevant Incident & Bond numbers.

    Confirm the Transaction has updated the bonded ticket in the remote instance:

    We can see that the update has reached the bonded ticket (& that the correlation id matches the outbound Incident number)

    Poll for Updates

    In Unifi Integration Designer, click on the 'Pollers' icon. Navigate to & open < Your Poller > (created earlier). & click Execute Now:

    In native ServiceNow, navigate to [ws] Unifi > Polling > Poll Requests. Click to Open & view the generated Poll Request. Confirm that no Incident was found (this is exactly as we expect because we are only polling for updates made by the remote instance):

    Update from Remote Instance

    In the remote instance, update two of the bonded tickets in turn.

    Updates are made to the Description field only. Correlation ID is highlighted for us to identify the correct bonded ticket.

    Poll for Updates

    Back in the originating instance, navigate to & open < Your Poller >. Click Execute Now.

    Open the corresponding Poll Request & confirm that both Incidents were found (and only those):

    View the Transactions that have been sent. This can be done either in Native ServiceNow, or in the Unifi Operations Portal.

    Navigate to [ws] Unifi > Transport > Transactions.

    Navigate to [ws] Unifi > Unifi Operations Portal.

    We can see that two UpdateIncidentInbound messages have been received. Both are Complete & Accepted & display the relevant Incident & Bond numbers.

    Confirm the Transactions have updated the bonded tickets in the originating instance.

    Challenge

    For completeness, to prove we are only querying and pulling back data from bonded records, update an incident in the remote system which isn't bonded (Correlation ID is empty) & run the Poller again.

    What do you expect to happen?

    Field

    Description

    Value

    1

    Caller

    Person who reported or is affected by this incident.

    <Your Caller>

    2

    Short description

    A brief description of the incident.

    <Your Short description>

    3

    Description

    Detailed explanation on the incident.

    <Your Description>

    Though the CreateIncident Message has been configured to map more than just the Short Description & Description fields, we have only filled these fields because that is all whe have included in the payload of our Poller.

    Your Incident form should look like this:

    4) Note the Info Message confirming the CreateIncident Message is being sent to your Integration.

    5) Note the Bond is 'Open' and both the Internal & External reference are in place.

    Repeat as necessary so that there are two or three bonded tickets in the remote instance:

    Update from Originating Instance

    Update one of the bonded tickets in the originating instance to cause the UpdateIncident Message to fire:

    View the Transactions that have been sent. This can be done either in Native ServiceNow, or in the Unifi Operations Portal.

    Navigate to [ws] Unifi > Transport > Transactions.

    Navigate to [ws] Unifi > Unifi Operations Portal.

    We can see that the three CreateIncident messages & one UpdateIncident message have been sent. All are Complete & Accepted & display the relevant Incident & Bond numbers.

    Confirm the Transaction has updated the bonded ticket in the remote instance:

    We can see that the update has reached the bonded ticket (& that the correlation id matches the outbound Incident number)

    Poll for Updates

    In Unifi Integration Designer, click on the 'Pollers' icon. Navigate to & open < Your Poller > (created earlier). Click Execute Now:

    In native ServiceNow, navigate to [ws] Unifi > Polling > Poll Requests. Click to Open & view the generated Poll Request. Confirm that no Incident was found (this is exactly as we expect because we are only polling for updates made by the remote instance):

    Update from Remote Instance

    in the remote instance, update two of the bonded tickets in turn.

    Updates have been made to the Description field only. Correlation ID is highlighted for us to identify the correct bonded ticket.

    Poll for Updates

    Back in the originating instance, navigate to & open < Your Poller >. Click Execute Now.

    Open the corresponding Poll Request & confirm that both Incidents were found (and only those) and that the Message name was UpdateIncidentInbound:

    View the Transactions that have been sent. This can be done either in Native ServiceNow, or in the Unifi Operations Portal.

    Navigate to [ws] Unifi > Transport > Transactions.

    Navigate to [ws] Unifi > Unifi Operations Portal.

    We can see that two UpdateIncidentInbound messages have been received. Both are Complete & Accepted & display the relevant Incident & Bond numbers.

    Confirm the Transactions have updated the bonded tickets in the originating instance.

    Challenge

    For completeness, to prove we are only querying and pulling back data from bonded records, update an incident in the remote system which isn't bonded (Correlation ID is empty) & run the Poller again.

    What do you expect to happen?

    Next, we shall test the ResolveIncidentInbound Message.

    #

    Create Test Incidents

    In your PDI, navigate to Incident > Create New.

    The Incident fields to configure are as follows:

    #

    Field

    Description

    Value

    1

    Caller

    Person who reported or is affected by this incident.

    <Your Caller>

    2

    Impact

    Measure of the business criticality of the affected service.

    <Your Impact>

    3

    *Assignment group: This should be the group you created in your PDI to enable Unifi to identify which newly created, non-bonded tickets to poll and whose sys id was stored in a connection variable and passed into the Setup Script of the Poll Processor.

    Your Incident form should look like this:

    Note the values entered (including State), so that you can check them against the mapped fields on the corresponding record in the instance being integrated to.

    Repeat the above steps, this time choosing a different Assignment group.

    Your Incident form should look like this:

    Repeat the above steps for a third time, this time leaving Assignment group (empty).

    Your Incident form should look like this:

    Repeat the above steps for a fourth time, again setting the Assignment group to <Your Assignment group> (as per Step 4 in the table above).

    Your Incident form should look like this:

    You should now have at least four non-bonded tickets in the remote instance (two of which are assigned to <Your Assignment group>):

    Poll for Creates

    In Unifi Integration Designer, click on the 'Pollers' icon. Navigate to & open < Your Poller > (created earlier). & click Execute Now:

    In native ServiceNow, navigate to [ws] Unifi > Polling > Poll Requests. Click to Open & view the generated Poll Request. Confirm that only the two Incidents were found (this is exactly as we expect because we are only polling for Incidents assigned to a specific Assignment group):

    View the Transactions that have been sent. This can be done either in Native ServiceNow, or in the Unifi Operations Portal.

    Navigate to [ws] Unifi > Transport > Transactions.

    Navigate to [ws] Unifi > Unifi Operations Portal.

    We can see that two CreateIncidentInbound message has been received. They are Complete & Accepted and display the relevant Incident & Bond numbers.

    For each Transaction, confirm the following:

    The Transaction has created the bonded ticket in this instance.

    Your first new Incident should look like this:

    Your second new Incident should look like this:

    The calller_id was populated with the default value gs.getUserID() because the table API was returning display_value instead of value. If the Create Poller was active and running then the caller_id would be the Integration User. Because the Create Poller was manually executed whilst inactive, then the value is the user who executed the poll.

    The Transaction has updated the bonded ticket in the remote instance (your PDI) (with the correlation id).

    Your first originating Incident should look like this:

    Your second originating Incident should look like this:

    Challenge

    For completeness, to prove we are only querying and pulling back data from non-bonded records, create an incident in this instance which causes the outbound CreateIncident Message to fire - as per the Outbound Incident Guide - (creating a new Incident in the remote instance) & run the Poller again.

    What do you expect to happen?

    Test CreateIncident

    We will test our CreateIncident Message.

    Create an Incident

    Navigate to Incident > Create New.

    The Incident fields to configure are as follows:

    #

    Field

    *Note: We have chosen these fields as these were the ones we mapped when creating our Field records for the CreateIncident Message. Your choices may differ depending on which Field records you created.

    Your Incident form should look like this:

    3) Right-click & Save.

    Note the values entered (including State & Priority), so that you can check them against the mapped fields on the corresponding record in the instance being integrated to.

    You should see an Info Message, confirming the CreateIncident Message is being sent to your Integration:

    You should also see a note in the Activities stream:

    When you scroll down to the 'Unifi Integrations' related list (you may have to configure the related lists to add it to your Incident form), notice:

    4) A Bond has been created. The State remains 'Pending' until the list is refreshed.

    5) Refresh the list by clicking Bonds.

    You should see the External reference populated & the State changed to 'Open':

    We are using a sys_id for the External reference in our example because we are integrating with the table API. If possible, it is better to use something more meaningful, like the Number of the ticket integrated with, as this aids in debugging.

    6) Click the Bond Number link to open the Bond record.

    View the Bond

    Your Bond record should look like this:

    7) Bond details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    8) History:

    • < History of transaction updates on the Bond > (Sending CreateIncident...)

    9) Transaction:

    • Message: 'Createincident'

    • Direction: 'Outbound'

    • Transaction state: 'Complete' (The data has been successfully transported)

    • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

    You are able to view the logs in the 'Unifi Activity Logs' related list.

    10) Transaction process next queued: Logs from checking whether there are any other transactions queued and processing those.

    11) Transaction sending: Logs from taking the Stage data, building the Request record & sending the Request to the integrated system.

    12) Business rule: < Your Trigger >: Logs from the Business Rule that triggers Unifi.

    View the Transaction

    Click through to the Transaction record from the related list on the Bond.

    Your Transaction record should look like this:

    13) Transaction details:

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    14) Errors:

    • Error: (If there was a transactional error the Transaction state would show as 'Error' and the details would be captured here).

    • Process error: (If there was a process error the Process state would show as 'Rejected' and the details would be captured here)

    15) Stage:

    • Direction: 'Outbound'

    • Message: 'CreateIncident'

    • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

    • External reference: < External system's ticket reference >

    View the Stage

    Click through to the Stage record from the related list on the Transaction.

    Check the values in the fields match what you expect.

    Your Stage record should look like this:

    16) Stage details:

    • Direction: 'Outbound'

    • External reference: < External system's ticket reference >

    • Internal reference: < ServiceNow ticket reference >

    • Message: 'CreateIncident'

    17) Mapped stage fields (yours may differ depending on which Field records you created):

    • Caller ID: < Your caller.id >

    • Short description: < Your Short description >

    • State: '1'

    View the HTTP Request

    Click through to the HTTP Request record from the related list on the Transaction.

    This is where you will find details of the data that was transported between the systems being integrated. (These records are extremely useful for developing and debugging integrations because of the immediate availability and contextual relevance to the integration you are developing.)

    Your HTTP Request record should look like this:

    18) HTTP Request details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Transaction: < Your Transaction >

    • Message: 'CreateIncident'

    19) Response details:

    • Status code: '200'

    • Response headers: < The header of the response being received >

    • Response payload: < The payload of the response being received >

    Compare with the External System's Incident

    Navigate to the corresponding Incident in the external system.

    Check the values in the fields match those you noted when you saved the Incident in the internal system.

    Your external system's Incident record should look like this (depending on the system you're integrating with, your record may look different; the important matter is that the values match):

    20) Caller: < Your Caller >

    21) State: < Your State >

    22) Short description: < Your Short description >

    23) Activities: < Note showing activity on the Incident > (Opened by < your.external.system.user > configured in the Connection)

    We are now ready to move on to the Update Scenario.

    Test ResolveIncident

    We will test our ResolveIncident Message.

    Resolve The Incident

    Navigate to < Your Incident > created in the earlier test.

    Update the Incident record as follows:

    #

    Field

    Your Incident record should look like this:

    4) Right-click & Save.

    You should see an Info Message, confirming the ResolveIncident Message is being sent to your Integration:

    The Activities stream is updated with the details:

    View the Bond

    Click through to the Bond record from the related list on the Incident.

    Your Bond record should have been updated as follows:

    5) History:

    • < History updated on the Bond > (Sending ResolveIncident...)

    6) Transaction:

    • Message: 'Resolveincident'

    • Direction: 'Outbound'

    • Transaction state: 'Complete' (The data has been successfully transported)

    • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

    View the Transaction

    Click through to the Transaction record from the related list on the Bond.

    Your Transaction record should look like this:

    7) Transaction details:

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    8) Errors:

    • Error: (If there was a transactional error the Transaction state would show as 'Error' and the details would be captured here).

    • Process error: (If there was a process error the Process state would show as 'Rejected' and the details would be captured here)

    9) Stage:

    • Direction: 'Outbound'

    • Message: 'ResolveIncident'

    • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

    • External reference: < External system's ticket reference >

    View the Stage

    Click through to the Stage record from the related list on the Transaction.

    Check the values in the fields match what you expect.

    Your Stage record should look like this:

    10) Stage details:

    • Direction: 'Outbound'

    • External reference: < External system's ticket reference >

    • Internal reference: < ServiceNow ticket reference >

    • Message: 'ResolveIncident'

    11) Mapped stage fields:

    • close_code: < Your Resolution code >

    • close_notes: < Your Resolution notes >

    • state: '6'

    View the HTTP Request

    Click through to the HTTP Request record from the related list on the Transaction.

    Your HTTP Request record should look like this:

    12) HTTP Request details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Transaction: < Your Transaction >

    • Message: 'ResolveIncident'

    13) Response details:

    • Status code: '200'

    • Response headers: < The header of the response being received >

    • Response payload: < The payload of the response being received >

    Compare with the External System's Incident

    Navigate to the corresponding Incident in the external system.

    Check the values in the fields match those you noted when you saved the Incident in the internal system.

    Your external system's Incident record should look like this (depending on the system you're integrating with, your record may look different; the important matter is that the values match):

    14) State: 'Resolved'

    15) Activities: < Your Resolution code/notes & State > (added by < your.external.system.user >)

    Navigate to the Resolution Information tab.

    Your Resolution Information tab should look like this:

    16) Resolution code: < Your Resolution code >

    17) Resolution notes: < Your Resolution notes >

    So far, when configuring our scenarios we have built the Message Scripts for each Message individually. Let's now see how we can run the Build process at the Integration level.

    UpdateIncidentInbound Message

    We will configure an inbound update message to process the data returned from the poll and update our target record.

    New Message Modal

    Click the 'Messages' icon, then New.

    The fields to be configured for the UpdateIncidentInbound New Message modal are as follows:

    #

    Your UpdateIncidentInbound New Message modal should look like this:

    5) Click Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    *This field is automatically defaulted to true.

    The 'Response' Message was previously configured (in the Outbound Incident Guide) to apply in an 'Inbound' direction. Change it to 'Bidirectional'.

    Your Response form should look like this:

    8) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be configured are as follows:

    *These fields are automatically populated.

    Your Bond form should look like this:

    10) Navigate to Inbound > Settings.

    Inbound Settings Fields

    The Inbound Settings fields to be configured are as follows:

    *Bond reference method:

    Internal - lookup using the internal reference only.

    External - lookup using the external reference only.

    Both - lookup using both the internal and external references.

    We have chosen the 'External' method because, in the payload we built, we only supplied the source_reference. If we had also supplied the correlation_id as the target_reference, then we would have chosen 'Both' (which would have offered an extra level of validation to the checking).

    Your Inbound Settings form should look like this:

    12) Click Save.

    We are now ready to configure the Fields for our UpdateIncidentInbound Message.

    var answer = {};
    
    answer.getExternalMessageID = function (payload, request) {
      return '' + (payload.message.source_id || '');
    };
    
    answer.getInternalMessageID = function (payload, request) {
      return '' + (payload.message.target_id || '');
    };
    bond.setOpen();
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.number [x_snd_eb_field.do?sys_id=c7a87254dbaa141041f945e81396195e]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.number = '' + (source.number || default_value);
      } else if (source.number != '') {
        $stage.number = '' + source.number;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.number [x_snd_eb_field.do?sys_id=c7a87254dbaa141041f945e81396195e]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.correlation_id = '' + $stage.number;
      } else if ($stage.number) {
        $payload.correlation_id = '' + $stage.number;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//

    State: 'Open' (Message exchange is available)

  • Status: 'OK' (All transactions have completed)

  • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

  • External reference: < External system's ticket reference >

  • Bond: < Your Bond >

  • Message: 'CreateIncident'

  • Direction: 'Outbound'

  • Transaction state: 'Complete' (The data has been successfully transported)

  • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

  • Transaction: < Your Transaction >

  • Integration: < Your Integration >

  • Direction: 'Outbound'

  • Request state: 'OK' (There are no errors with the HTTP Request.)

  • Attempt number: < Number of HTTP Request attempts > (Failed requests are retried up to the maximum attempts number as configured on the Integration.)

  • Endpoint URL: < The external system’s access URL >

  • Action Method: 'POST'

  • Request headers: < The header of the request being sent >

  • Request payload: < The payload of the request being sent >

  • Description

    Value

    1*

    Caller

    Person who reported or is affected by this incident.

    <Your Caller>

    *

    State

    The Incident lifecycle state.

    'New' - Default (Automatically populated)

    2*

    Short description

    A brief description of the incident.

    <Your Short description>

    Bond: < Your Bond >

  • Message: 'ResolveIncident'

  • Direction: 'Outbound'

  • Transaction state: 'Complete' (The data has been successfully transported)

  • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

  • Transaction: < Your Transaction >

  • Integration: < Your Integration >

  • Direction: 'Outbound'

  • Request state: 'OK' (There are no errors with the HTTP Request.)

  • Attempt number: < Number of HTTP Request attempts > (Failed requests are retried up to the maximum attempts number as configured on the Integration.)

  • Endpoint URL: < The external system’s access URL >

  • Action Method: 'PUT'

  • Request headers: < The header of the request being sent >

  • Request payload: < The payload of the request being sent >

  • Description

    Value

    1

    State

    The Incident lifecycle state.

    'Resolved'

    2

    Resolution code

    The Incident resolution code.

    <Your Resolution code>

    3

    Resolution notes

    The Incident resolution notes.

    <Your Resolution notes>

    Process this message when the bond state is Open.

    <true>

    Field

    Description

    Value

    1

    Message name

    The message name that is unique for this integration.

    'UpdateIncidentInbound'

    2

    Type

    The primary purpose of the message.

    'Update'

    3

    Direction

    The direction(s) this message is configured to support.

    'Inbound'

    4

    Description

    The description for this message and the requirement it is meeting.

    <Your description>

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    7*

    Async

    Turn this option on if you want inbound processing to occur asynchronously or this message is the first of an asynchronous message pair.

    <false>

    #

    Field

    Description

    Value

    *

    Bond ownership

    Determine if the sender should own the bond or not in order for this message to be processed? Use 'Ignore' to process regardless of the owner flag. (Choices: Ignore, Must own, Must not own.)

    'Ignore'

    *

    Bond condition type

    The type of conditional check made on the bond. (None: no checks are made. State: checks against the state are made using the conditional checkboxes. Scripted: the 'Bond condition' script is used.)

    'State'

    9

    #

    Field

    Description

    Value

    11

    Bond reference method*

    Method of searching for and validating an existing bond for incoming messages.

    'External'

    Bond open

    <Your Last Name>

    4

    Password

    The user's password (to be used in basic authentication).

    <Your Password>

    5

    Roles

    The role required for access to the integrated records.

    'itil'

    Active

    Use this connection for the integration when true.

    <true>

    Password*

    The password used in basic authentication.

    <External system user password>

    13

    Inbound user**

    The user profile used by the external system for authentication. An active connection must be found for the user to gain access.

    <lookup: Your Inbound user>

    The direction(s) this message is configured to support.

    'Outbound'

    Bond open

    Process this message when the bond state is Open.

    <true>

    The direction(s) this message is configured to support.

    'Outbound'

    Bond new

    Process this message when a new bond is required.

    <true>

    <Your Last Name>

    4

    Password

    The user's password (to be used in basic authentication).

    <Your Password>

    5

    Roles

    The role required for access to the integrated records.

    'itil'

    Active

    Use this connection for the integration when true.

    <true>

    Password

    The password used in basic authentication.

    <External system user password>

    13

    Inbound user

    The user profile used by the external system for authentication. An active connection must be found for the user to gain access.

    <lookup: Your Inbound User>

    Description

    Detailed explanation on the incident.

    <Your Description>

    Urgency

    The extent to which resolution of an incident can bear delay.

    <Your Urgency>

    4

    Assignment group*

    The group to which the ticket is assigned.

    <Your Assignment group>

    5

    Short description

    A brief description of the incident.

    <Your Short description>

    6

    Description

    Detailed explanation on the incident.

    <Your Description>

    CreateIncidentResponse Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the CreateIncidentResponse Message.

    Copy Field Maps

    It is worth copying all relevant OOTB Field Maps as are necessary for your integration before using any of them in your Field Records - thereby mitigating the risk of any potential issues with future upgrades.

    The Field Map we shall use for our CreateIncidentResponse Field record is:

    • Source Reference

    To copy the Source Reference Field Map, navigate to the 'Field Maps' icon.

    1) Click on the ellipsis to the right of the Source Reference Field Map & click Copy.

    Copy Field Map Modal

    The fields to edit for the Copy Field Map modal are as follows:

    *Name: We have chosen to prefix the existing Field Map Name with the initials of our Integration (you are free to choose any appropriate means of identifying/differentiating your copy).

    Your Copy Field Map modal should look like this:

    Integration should be automatically populated.

    3) Click Copy.

    You will be redirected to the Details page of the newly created Field Map.

    Field: result.sys_id

    In Unifi Integration Designer, from the CreateIncidentResponse page, navigate to Message > Fields. Click New.

    The fields to be configured for the sys_id New Field modal are as follows:

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    *Property: We are setting 'sys_id' as the property because that is what is required by the table API. If it were possible, it would better to use something more meaningful, like the Number of the ticket integrated with, as this aids in debugging.

    The 'result.sys_id' New Field modal should look like this:

    10) Submit the record.

    You will be redirected back to the Fields page of the CreateIncidentResponse Message.

    Build

    Now that we’ve configured the Field records for the CreateIncidentResponse message, we are ready to build our message scripts.

    The following Field record should now be in place for your CreateIncidentResponse messsage:

    Feature Alert: In the picture above you will notice that a 'Build Integration' button has appeared in the banner at the top of the page. Whenever a change is made to a Field record that is associated to a Message (whether that is being created, updated, or deleted) the button will be available and acts as a visual reminder that changes have been made and Message Script(s) need to be built. We will talk more about this feature in the page.

    11) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    12) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    We will now examine our new, auto-generated Message Scripts.

    Payload to Stage:

    Stage to Target:

    The code we had previously added when configuring our Message as per the '' page is still in place.

    Both the stage & bond external reference are being set to the sys id only because we are integrating with the table API and that's what it requires. If possible, it is better to use something more meaningful, like the Number of the ticket integrated with, as this aids in debugging.

    Next, we will configure the CreateIncident Message.

    CreateIncidentInbound Message

    We will configure an inbound create message to process the data returned from the poll and create a new target record.

    New Message Modal

    Click the 'Messages' icon, then New.

    The fields to be configured for the CreateIncidentInbound New Message modal are as follows:

    #

    Your CreateIncidentInbound New Message modal should look like this:

    5) Click Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    *This field is automatically defaulted to true.

    Your Response form should look like this:

    8) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be configured are as follows:

    *These fields are automatically populated.

    Your Bond form should look like this:

    10) Navigate to Inbound > Settings.

    Inbound Settings Fields

    The Inbound Settings fields to be configured are as follows:

    *Bond reference method (defaulted to 'External' & not editable for Create type Messages):

    Internal - lookup using the internal reference only.

    External - lookup using the external reference only.

    Both - lookup using both the internal and external references.

    Bond reference method: The perspective of the available choices is in relation to the receiving instance i.e. Internal (internal reference) means the bonded ticket in our instance and External (external reference) means the bonded ticket in their instance. These settings define which values to lookup against to search for and validate whether or not a bond already exists.

    In the case of a create type message (as per our requirement), it is defaulted to 'External' because there is not yet a bonded ticket in the receiving instance to reference (if we were to receive a create type message which referenced a bond that already existed it would be rejected because we don't want to create another bond for a record we've already seen ).

    The code in the 'Reference lookup script' field should look like this:

    Reference lookup script: It’s important to identify which message an asynchronous receipt is replying to. This script extracts the transaction’s unique identifier.

    In the case of an inbound create/update (as per our requirement) it would return their external message id (source id) to identify which transaction our asynchronous receipt belongs to. (In the case of an inbound asynchronous receipt it would return our internal message id (target id) to identify which transaction their asynchronous receipt belongs to.)

    Your Inbound Settings form should look like this:

    12) Navigate to Advanced > Script Editor.

    Script Editor Fields

    As well as being the place where Bond state & ownership are set, the Scripts are where the request processing and data mapping occurs.

    Click on View > Inbound.

    The Script Editor fields to be configured are as follows:

    Scripts

    In the current release, there is no OOTB Field Map record with which we can set the state on the Bond. We shall, therefore, script that manually. For more information , see the `` & `` pages in our technical documentation.

    The code in the 'Stage to Target' script field should look like this:

    Your Script Editor fields should look like this:

    14) Click Save.

    15) Close the Script Editor to navigate back to the Message.

    We are now ready to configure the Fields for our CreateIncidentInbound Message.

    Connection Variables

    Connection Variables can be especially useful if you have multiple connection environments - e.g. Dev, Test, Prod - each containing different data.

    Although having multiple environments may not apply to this integration, we will create Connection Variables to contain certain data values which will be substituted into the Poll Processor scripts.

    Instead of scripting data values directly into the code of your Poll Processor scripts, it may be better practice to use Connection Variables in their place. Not only does it make those scripts cleaner, but it also means that changes in requirements can be more easily enacted by changing the values of the data in those variables, without having to change the code in the scripts.

    We will use Connection Variables to identify which Assignment group to look for and which field elements to return data from when polling.

    Icons

    Before continuing we would like to draw your attention to some of the relevant icons that will be visible down the left hand navigation strip in the Unifi Integration Designer.

    The icons are:

    a) 'Integration' icon: Opens the current integration's Details page.

    b) 'Messages' icon: Opens the current integration's Messages page.

    c) 'Fields' icon: Opens the current integration's Fields page.

    d) 'Field Maps' icon: Opens the current integration's Field Maps page.

    e) 'Pollers' icon: Opens the current integration's Pollers page.

    f) 'Poll Processors' icon: Opens the current integration's Poll Processors page.

    g) 'Connections' icon: Opens the current integration's Connections page.

    Assignment Group

    It is necessary to identify which of the non-bonded records in the external instance (your PDI) are applicable to the integration. One way of doing this is to define a specific Assignment group to which all incidents will be assigned for the integration.

    We will create a new group which will be used only for this integration. We will then use the Sys ID of that group in a Connection Variable to pass into the Poll Processor scripts to enable Unifi to identify which records should be bonded.

    In your PDI, navigate to User Administration > Groups. Click New.

    The fields to be configured for the Group New record are as follows:

    Your Group New record should look like this:

    3) Submit the record.

    Variable: external_group

    This variable will contain the sys id of the group created above. It will be used in the Poll Processor Setup script to identify which non-bonded Incidents to query.

    To open Unifi Integration Designer, navigate to [ws] Unifi > Unifi Integration Designer, then navigate to < Your Integration > (created following the Outbound Incident Guide).

    Click the 'Connections' icon, then navigate to and open < Your Connection >.

    From the Connection, navigate to Connection > Variables & click New.

    The 'external_group' New Connection Variable fields to be configured are as follows:

    *Value: Value may vary. Use the sys id of the group created in your PDI.

    Your 'external_group' New Connection Variable modal should look like this:

    7) Click Submit.

    You will be redirected back to the Variables page of the Connection record.

    Variable: base_fields

    This variable will contain the minimum set of fields required to identify and select records in the remote system.

    Click New.

    The 'base_fields' New Connection Variable fields to be configured are as follows:

    Your 'base_fields' New Connection Variable modal should look like this:

    11) Click Submit.

    You will be redirected back to the Variables page of the Connection record.

    Variable: data_fields

    This variable will contain fields which will be retrieved from the remote system, in addition to the required base_fields. We have chosen a sample selection of fields. You may choose different fields if you wish. However, the fields you select here must also be mapped with corresponding Field Records (more on that on the page).

    Click New.

    The 'data_fields' New Connection Variable fields to be configured are as follows:

    Your 'data_fields' New Connection Variable modal should look like this:

    15) Click Submit.

    The following Connection Variables should now be in place for your Connection:

    Now let's move on and configure the Poll Processor.

    Reconfigure the Connections

    The next step in building the other half of the Integration is to reconfigure the connections.

    Now that both halves of the Integration are in place, we need to reconfigure each of the Connections to point to the other instance. Before doing that though, we need to create a new Inbound User for the external instance.

    Create an Inbound User (external instance)

    To configure our Integration user:

    In native ServiceNow, navigate to User Administration > Users. Click New.

    The fields to be configured for the User record are as follows:

    This Inbound user will become the Outbound user in the other instance. We will need to update the other instance accordingly.

    Edit the Connection (external instance)

    We are going to edit the existing 'Development' Connection so that it will become our 'Test' Connection and use the Inbound user just created.

    We will need to have our other instance point to this external one also (not only to itself). Therefore, we will create a new 'Test' Connection in the other instance to do that. (See the .)

    In Unifi Integration Designer, navigate to the 'Connections' icon.

    6) Click to open the previously created Development Connection to edit it.

    Edit the values in the Connection as follows:

    *Inbound user created above.

    Your Connection form should look like this

    We have not updated the Endpoint URL nor the Outbound User because they already contain the correct values (i.e. the internal instance's Endpoint & Inbound user).

    9) Save the Connection.

    Create a Test Connection (internal instance)

    Back in the internal instance, navigate to the 'Connections' icon. Click New.

    We could have edited our existing 'Development' Connection to point to the external instance (instead of itself). We have chosen instead to create a new 'Test' Connection to do that. That way we have two Connections, a 'Development' Connection which points to itself and a 'Test' connection which points to the external instance.

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

    Outbound Connectivity

    The format of the Endpoint URL is as follows:

    https://<your_instance>.service-now.com/<your_resource_path>

    For this Test environment Connection, we have edited the Development Connection, changing the <your_instance> element of the Endpoint URL to point to the external system instance (leaving the <your_resource_path> element unchanged). For our Outbound User we have used the external system's Inbound User (as created above).

    Your New Connection modal should look like this:

    13) Submit and view to further configure the Connection.

    Clicking ‘Submit’ will redirect you to the list view of the record you’re creating. Clicking ‘Submit and view' will redirect you to the newly created record.

    Connection Details

    The fields to be configured for the Details form are as follows:

    (External) User/Password: As created above & set in the external instance.*

    Your Details form should look like this:

    18) Save the Connection.

    View Connections

    There will now be both a Development and a Test Connection for your Integration. Only the Test Connection should be Active.

    These can be viewed by clicking the 'Connections' icon.

    We have completed building the other half of the Integration. We are now ready to go back and repeat the Testing for each of the scenarios we've built.

    See the following pages:

    2.1 Release Notes

    Here you will find details of what's changed in this release, including new features & improvements, depracated features and general fixes.

    Introduction

    Welcome to the release notes for Unifi - Version 2.1. Please have a read through to see new features and fixes that have been added.

    Web Service

    The entry point for a Process - you would build one endpoint per process. Once connected, messages are guided to the integration based on the unique combination of authentication user & endpoint.

    Scripted REST Service

    In native ServiceNow, navigate to System Web Services > Scripted Web Services > Scripted REST APIs. Click New.

    The Scripted REST Service fields to be configured are as follows:

    UpdateIncident Message

    The UpdateIncident Message is an update type message that sends updates to the bonded record.

    Again, after clicking the 'Messages' icon, you are directed to the following screen (note: the four previously configured messages are now visible in the list):

    1) Click New.

    New Message Modal

    The fields to be configured for the UpdateIncident New Message modal are as follows:

    Upgrade Notice

    Please note that, as with every release, there may be some changes that are not entirely compatible with your existing integrations. While we do everything we can to make sure you won't have to fix your integrations when upgrading, we strongly encourage all our customers to perform full end-to-end tests of their integrations before upgrading Unifi in Production.

    We also highly recommend aligning your Unifi upgrade with your ServiceNow upgrade. This means you only need to test your integrations one time rather than once for the ServiceNow upgrade and once for the Unifi upgrade.

    Feedback and Reviews

    We really appreciate feedback on what we're doing - whether it's right or wrong! We take feedback very seriously, so if you feel you'd give us anything less than a 5 star rating, we'd love to hear from you so we can find out what we need to do to improve!

    If you would rate us 5 stars, and haven't left a review on the ServiceNow Store yet, we'd be grateful if you would head over there to leave us your feedback. It only takes a few minutes and really does help us a lot. Go on, you know you want to leave a 5-star review on the Store!

    Highlights

    Major Portal Update

    The biggest change in this release is the update to the Portal interface, now known as Unifi Integration Designer.

    The old operations dashboard has now been moved to the new Unifi Operations Portal, ready for lots of exciting updates around operations in the near future. It's been replaced with a brand new configuration dashboard, allowing you to view, create, copy and manage your processes and integrations with ease.

    There are lots of improvements across the board when configuring an integration, too, not least of all including support for all the components you need to build any Ticket Exchange integration together in an intuitive way.

    Integration Pause

    We've introduced a brand new capability to pause an integration. This allows you to temporarily prevent outbound messages from being sent, instead allowing them queue ready for sending in future. This is different to deactivating the integration, which would prevent message processing altogether. You might want to do this if you are having a lot of errors with the external system, or perhaps if it's gone down for maintenance. Once you know the system is back up and online, you can resume the integration with the click of a button and it will automatically start processing the queued messages.

    Event Actions

    The introduction of Event Actions is part of our ongoing strategy to improve operations management of integrations. By creating an Event Action, you can easily triage events such as transaction errors and perform actions to handle or report on those actions. For example, you might want to create an Incident record if you receive more than 5 transaction errors in 15 minutes.

    Notes

    Logged Attachments

    With the introduction of Activity Logs you no longer need to attach logs to requests/transactions. Activity Logs are present in related lists on all relevant Transaction stack records.

    The attached logs were previously controlled by the Attach logs and Attach payloads checkboxes on Integration, but they are now overridden off by a new Integration Enable Attachments system property. This property acts as the master switch and effectively disables the checkboxes on the Integration. Note: the checkboxes have been removed from the Integration form but can still be edited from the list view.

    Details

    New Features & Improvements

    • Admins can now force close a bond. [UN-106]

    • Description field added to Data Stores. [UN-123]

    • New option on Integration to send attachments with Create messages. [UN-184]

    • Activity Log now references the Target (e.g. Incident). [UN-288]

    • Added a cleaner job, controlled by system properties, to remove orphaned Transactions. [UN-544]

    • New Poll Request states (Retrieving, Processing) are set while a Poller is processing . [UN-293]

    • Field style added to Active field on Poller. [UN-298]

    • Activity Log is now able to show the table that called it. [UN-305]

    • Field style added to Poll Request state. [UN-313]

    • Queued Transactions are now ignored when the bond is closed. [UN-370]

    • Fields can now be copied. [UN-389]

    • The Integration field is now auto-populated when creating a Field from a Message. [UN-395]

    • The Table field is now auto-populated when creating a Field. [UN-396]

    • Added Domain field to Transaction stack forms (Bond, Transaction, Stage, and HTTP Request). [UN-401]

    • Copy Message now copies all its Fields. [UN-420]

    • Copying an Integration now copies all the Fields. [UN-421]

    • Copy Integration is now available in the Portal. [UN-422]

    • Connection is now shown on Transaction. [UN-426]

    • Integration Status (Up, Down, Awaiting) is now tracked on the Integration. [UN-427]

    • Integration State (Active, Paused, Off) is now tracked on the Integration. [UN-428]

    • Added option to Run Event Actions on an Integration. [UN-431]

    • Bond now references the Connection it was created for. [UN-438]

    • Dynamic Stage ($stage) now has a getValue() method. [UN-441]

    • Fields and Field Maps can now be configured in the Portal. [UN-443]

    • Message level Fields can inherit from Integration level Fields. [UN-449]

    • Pollers are now listed on Integration. [UN-456]

    • Bonded Attachment records now track direction (Inbound or Outbound). [UN-461]

    • Added console object to all scripts for ease of logging. [UN-477]

    • Updated Activity Logs on the bond so it shows all Activity Logs for the Document record. [UN-513]

    • Improved Activity Log titles. [UN-514]

    • Admins can now force re-open a closed Bond. [UN-517]

    • Improved Execute Now button for Pollers. [UN-521]

    • Added Activity Logs to Poll Requests. [UN-522]

    • Added Integration field to Poll Request. [UN-523]

    • Improved naming for Portal based Activity Logs. [UN-529]

    • HTTP Request and Transaction now shows the Response Action that was used. [UN-533]

    • Cascade delete now applies to Field Maps belonging to an Integration. [UN-545]

    • Cascade delete now applies to Fields belonging to an Integration. [UN-546]

    • Cascade delete now applies to Pollers belonging to an Integration. [UN-547]

    • Cascade delete now applies to Pollers belonging to an Poll Processor. [UN-547]

    • Added Description field to Connection. [UN-565]

    • Added Description field to Scheduled Scripts. [UN-570]

    • Added Hints to Field Map fields. [UN-571]

    • Added execution URL to Activity Log. [UN-574]

    • Modified security on Activity Logs so they are visible to Unifi Managers. [UN-586]

    • New Unifi REST service and integration role added to simplify REST API configuration. [UN-633]

    • Changed Integration Format and Message Service defaults to be REST/JSON. [UN-634]

    Changes

    • Bond closed field has been removed from Message. [UN-332]

    • The XML Template on Message no longer has a default value. [UN-398]

    • Changing the Integration on a Field now clears the Message. [UN-399]

    • Poll Processors are now copied when the Integration is copied. [UN-468]

    • Improved the Field "Depends on" logic. [UN-476]

    • Data Stores now inherit the domain from the parent document. [UN-481]

    • Message.processOutbound() will not send anything if the action on the current record has been aborted using setAbortAction(true). [UN-490]

    • Replay Request is now available to the Unifi manager role. [UN-494]

    • Most system properties are now Private and not transferrable by Update Set. [UN-652]

    • HTTP Request URL length limit increased to 2048 characters. [UN-118]

    • Transaction count on bond has been deprecated. [UN-141]

    • Number field has been removed from Messages and Message Scripts. [UN-208]

    • Modified Bond Reference Method field visibility on Message. [UN-292]

    • Ignore Transaction button now redirects to the Transaction being ignored. [UN-338]

    • Deprecated ECC Queue attachment support for attaching logs. [UN-405]

    • Deactivated the fix script x_snd_eb eBonding Upgrade. [UN-406]

    • Response is no longer mandatory on Message. [UN-439]

    • Integration properties which are numbers are now mandatory. [UN-440]

    • Endpoint URL is now visible on inbound requests. [UN-511]

    • Deprecated log attachments. [UN-540]

    • Bonded Attachment fields are now locked down. [UN-577]

    • Only Unifi Admins or Managers can replay HTTP Requests. [UN-581]

    General Fixes

    • Inbound Create messages are now rejected when a Bond with the same reference exists. [UN-136]

    • Inbound Bonded Attachments now reference the Transaction they came in on. [UN-151]

    • Fixed issue with connection name generation. [UN-159]

    • Replaying a Transaction with attachments will now replay the attachments as well. [UN-226]

    • The Bond state will now always reflect the overall status of its transactions. [UN-230]

    • Bond status is now updated correctly when processing numerous queued messages. [UN-273]

    • A new field Deferred count has been added to Bonded Attachment which tracks how many times the attachment was not sent and allows us to properly calculate attachment metrics on the Bond. [UN-287]

    • Bond numbers are no longer used unnecessarily. [UN-315]

    • Fixed issues with assigning headers in Stage to Request Message Scripts. [UN-333]

    • Fixed an issue where calling a Unifi endpoint with GET would throw an error. [UN-380]

    • UTF-8 encoded XML is now checked before processing to prevent parsing issues. [UN-382]

    • The Name value on Field is now set even when a not mapping to a real field. [UN-397]

    • Fixed an issue where the Field form would always show the alert for losing changes. [UN-451]

    • Fixed duplicate attachment messages when using ServiceNow Antivirus scanning. [UN-465]

    • Inbound transactions that are replayed are now executed as the integration instead of the current user. [UN-473]

    • Fixed an issue with Field Choice generation not having the table set. [UN-475]

    • Replaying an HTTP Request now increments the number correctly. [UN-478]

    • Errors thrown in Field Map scripts will now show up in the Transaction. [UN-479]

    • Fixed an issue with replaying Transactions created by system. [UN-482]

    • Fixed Bond History state logging. [UN-485]

    • Fixed an issue with false-positive updates from Transactions. [UN-505]

    • The "Generate field choices" action on Field now checks for existing Field Choice entries. [UN-516]

    • Reference fields in Messages are now correctly updated when copying an Integration. [UN-530]

    • Fixed an issue where full Activity Logs would be sent to system log. [UN-534]

    • Logging verbosity is now allowed at error level. [UN-535]

    • Fixed an issue where queued Transactions would not be processed. [UN-543]

    • Connection is now updated when the Integration name is changed. [UN-552]

    • API names are now allowed to use a zero (0). [UN-553]

    • Clicking the "Generate field choices" action on Field will save the record first to ensure choices are generated correctly. [UN-556]

    • Response Action user notifications now work. [UN-562]

    • Fixed undefined error with Ignore Transaction button [UN-592]

    • Fixed issue in generating messages without a Connection URL [UN-638]

    Integration Designer (Portal) Changes

    • Transactions are now ordered by date created in the live feed. [UN-452]

    • Side menu options are now highlighted when selected. [UN-453]

    • Reference links now navigate to the Portal pages instead of native ServiceNow. [UN-454]

    • Changed the style on inactive Boolean fields to differentiate them from read-only Boolean fields. [UN-564]

    • Embedded fonts/icons to improve page loading times. [UN-572]

    • Added Enable/Disable button to form headers for easy access. [UN-641]

    Integration Designer (Portal) Fixes

    • Fixed read error when attempting to view a record in Portal as a non-admin. [UN-403]

    • Fixed Portal font size for instances running Madrid onwards. [UN-404]

    • Fixed an issue with the operations dashboard truncating the live transaction feed when there are less than 20 transactions. [UN-407]

    • Attachment sending can now be controlled from the portal. [UN-415]

    • Condition widgets now work in Portal. [UN-434]

    • Fixed an issue with variables payload and headers not being assignable in Message Scripts. (Closures have been replaced with instructive comments.) [UN-463]

    • Outbound Attachment properties are no longer visible for inbound only messages. [UN-472]

    • Bond scripted condition type only shows once instead of twice. [UN-558]

    • Long text fields in Portal lists are now truncated to improve usability. [UN-569]

    • Fixed render issue with reference fields that have no value in portal [UN-578]

    • References in lists now show "(empty)" if there is no display value [UN-640]

    • Fixed issue with form appearing read-only in Portal view when directly navigation to the URL [UN-642]

    • Fixed issue with Portal form loads from an external link [UN-643]

    • Added support for day-of-week type fields. [UN-566]

    • Added support for time fields. [UN-567]

    • Added support for interval fields. [UN-568]

    • Lists and pages now update the title in Portal. [UN-637]

    Set to true to use this Field record for processing.

    <true>

    5

    Field map

    The Field Map this Field record is linked with.

    'IS - Source Reference'**

    6*

    Map to field

    Use this Field record to represent a field on a source/target table.

    <false>

    7

    Path

    Where in the payload the data will be placed.

    'result'

    8

    Property*

    The property in the payload the data will be written to.

    'sys_id'

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    9*

    Outbound

    Set to true to use for outbound Messages.

    <false>

    #

    Field

    Description

    Value

    2

    Name*

    The name of your field map. (If left unedited, it will append the word 'Copy' to the existing name.)

    <Your Name>

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncidentResponse'

    4

    Description

    Describe what this field is for and any specific details that might help you in future.

    'Extract returned sys_id & store in stage.external_reference'

    *

    Build Integration Level
    CreateIncidentResponse Message

    Active

    The asynchronous receipt to this message. Leaving this blank will cause the message to be processed async without sending a receipt.

    <lookup: 'CreateIncidentInboundReceipt'>

    Process this message when a new bond is required.

    <true>

    Field

    Description

    Value

    1

    Message name

    The message name that is unique for this integration.

    'CreateIncidentInbound'

    2

    Type

    The primary purpose of the message.

    'Create'

    3

    Direction

    The direction(s) this message is configured to support.

    'Inbound'

    4

    Description

    The description for this message and the requirement it is meeting.

    <Your description>

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    *

    Async

    Turn this option on if you want inbound processing to occur asynchronously or this message is the first of an asynchronous message pair.

    <true>

    7

    #

    Field

    Description

    Value

    *

    Bond ownership

    Determine if the sender should own the bond or not in order for this message to be processed? Use 'Ignore' to process regardless of the owner flag. (Choices: Ignore, Must own, Must not own.)

    'Ignore'

    *

    Bond condition type

    The type of conditional check made on the bond. (None: no checks are made. State: checks against the state are made using the conditional checkboxes. Scripted: the 'Bond condition' script is used.)

    'State'

    9

    #

    Field

    Description

    Value

    *

    Bond reference method

    Method of searching for and validating an existing bond for incoming messages.

    'External'

    11

    Reference lookup script

    The script containing functions for extracting internal and external references from the request payload.

    Update the code in the Reference lookup script field so that it looks like the code below

    #

    Field

    Description

    Value

    13

    Stage to Target (Inbound)

    The script to run.

    Replace the commented out instructions with the following code: bond.setOpen();

    Fields
    Field Maps

    Async receipt

    Bond new

    Describe what this connection variable is for and how it should be used.

    <Your Description>

    Describe what this connection variable is for and how it should be used.

    <Your Description>

    Describe what this connection variable is for and how it should be used.

    <Your Description>

    #

    Field

    Description

    Value

    1

    Name

    Descriptive name, e.g. DBAs, Network, etc.

    <Your Name>

    2

    Description

    The description of the Group.

    <Your Description>

    #

    Field

    Description

    Value

    4

    Key

    A unique name that will be used to get the value.

    'external_group'

    5

    Value

    The variable value to be used in the integration.

    <Your Value>*

    6

    #

    Field

    Description

    Value

    8

    Key

    A unique name that will be used to get the value.

    'base_fields'

    9

    Value

    The variable value to be used in the integration.

    'sys_id,number,correlation_id,sys_updated_on,sys_updated_by'

    10

    #

    Field

    Description

    Value

    12

    Key

    A unique name that will be used to get the value.

    'data_fields'

    13

    Value

    The variable value to be used in the integration.

    'caller_id,short_description,description,state,impact,urgency'

    14

    CreateIncidentInbound Fields

    Description

    Description

    Description

    The integration user's last name.

    <Your Last Name>

    4

    Password

    The user's password (to be used in basic authentication).

    <Your Password>

    5

    Roles

    The role required for access to the integrated records.

    <roles needed, e.g. itil>

    Use this connection for the integration when true.

    <true>

    The password used in basic authentication.

    <External system user password>

    17

    Inbound user

    The user profile used by the external system for authentication. An active connection must be found for the user to gain access.

    <lookup: Your Inbound User>

    #

    Field

    Description

    Value

    1

    User ID

    The id of the user (to be used by the external system for authentication).

    <your.integration.user>

    2

    First name

    The integration user's first name.

    <Your First Name>

    3

    #

    Field

    Description

    Value

    7

    Environment

    The environment this connection applies to.

    'Test'

    8

    Inbound user

    The user profile used by the external system for authentication.

    <Your Inbound user*>

    #

    Field

    Description

    Value

    10

    Environment

    The environment this connection applies to.

    'Test'

    11

    Endpoint URL

    The external system's access URL.

    <External system Endpoint URL>

    12

    #

    Field

    Description

    Value

    14

    Authentication

    The authentication method to use for this connection.

    'Basic'

    15

    User*

    The username used in basic authentication.

    <external.system.user>

    16

    next section
    Test CreateIncident
    Test UpdateIncident
    Test ResolveIncident

    Last name

    Active

    Password*

    Field

    Description

    Value

    1

    Name

    The name of the API. Appears in API documentation.

    <Your Name>

    2

    API ID

    The API identifier used to distinguish this API in URI paths. Must be unique within API namespace.

    Automatically populated

    *

    API namespace

    The namespace the API belongs to. The value depends on the current application scope.

    Automatically populated

    *

    Base API path

    The base API path (URI) to access this API.

    Automatically populated (after 'Save')

    The top section of your Scripted REST Service record should look like this:

    3) Save the record.

    Security Fields

    Click on the 'Security' tab and configure the fields as follows:

    #

    Field

    Description

    Value

    4

    Default ACLs

    The ACLs to enforce when accessing resources. Individual resources may override this value.

    [Blank]

    Your 'Security' tab should look like this:

    Save the record.

    Scripted REST Resource

    Navigate to the Resources Related List. Click New.

    The 'Scripted REST Resource' fields to be configured are as follows:

    #

    Field

    Description

    Value

    5

    Name

    The name of this API resource. Appears in API documentation.

    <Your Name>

    6

    HTTP method

    The HTTP method that maps to this resource.

    'POST'

    *

    *These fields are automatically populated.

    The code in the Script field should look like this:

    In the RestHelper function, change the value of the Process API name being called to match yours (e.g. 'incident_guide'). By wrapping the code in console, we give context to Activity Log and prevent multiple database updates.

    The top section of your Scripted REST Resource should look like this:

    Security Fields

    Click on the 'Security' tab and configure the fields as follows:

    #

    Field

    Description

    Value

    8

    Requires ACL authorization

    Enforce ACLs when this resource is accessed.

    <false>

    Your 'Security' tab should look like this:

    Content Negotiation Fields

    Click on the 'Content Negotiation' tab and configure the fields as follows:

    #

    Field

    Description

    Value

    9

    Override supported request formats

    Check to customize the request media types supported by this resource.

    <true>

    10

    Supported request formats

    Comma-delimited list of media types this resource can consume.

    *

    Your 'Content Negotiation' tab should look like this:

    11) Click Submit.

    Update Process Record

    With the introduction of the Packager feature, if you want the Web Service to be included in the packaged update set, you will need to update the value of the REST Service field on the Process record with the name of your Scripted REST Service. This will enable the Packager to pick it up.

    Whilst still in native ServiceNow, navigate to [ws] Unifi > Configuration > Processes.

    Click to open < Your Process >.

    12) Update the value in the REST Service field with < Your Scripted REST Service > (as created above).

    13) Click Update.

    We will now move back to the Unifi Integration Designer window to configure the Integration.

    #

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'UpdateIncident'

    3

    Type

    The primary purpose of the message.

    'Update'

    4

    Direction

    Your UpdateIncident New Message modal should look like this:

    5) Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    *

    Async

    Turn this option on if you want inbound processing to occur asynchronously or this message is the first of an asynchronous message pair.

    <true>

    7

    *This field is automatically defaulted to true.

    Your Response form should look like this:

    8) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be configured are as follows:

    #

    Field

    Description

    Value

    *

    Bond ownership

    Determine if the sender should own the bond or not in order for this message to be processed? Use 'Ignore' to process regardless of the owner flag. (Choices: Ignore, Must own, Must not own.)

    'Ignore'

    *

    Bond condition type

    The type of conditional check made on the bond. (None: no checks are made. State: checks against the state are made using the conditional checkboxes. Scripted: the 'Bond condition' script is used.)

    'State'

    9

    *These fields are automatically populated.

    Your Bond form should look like this:

    11) Navigate to Outbound > Trigger.

    Outbound Trigger Fields

    The Outbound Trigger fields to be configured (as required)* are as follows:

    #

    Field

    Description

    Value

    12

    Outbound condition*

    The condition that the ServiceNow record must meet to trigger this message being processed.

    Update the Outbound condition script field with the code below

    *Outbound condition (as required):

    It is not necessary for you to enter a condition. The value given is an example. You may create any condition (or not) to align with your business process requirements. In this case it makes sense to use this message to send an update where the state doesn't change. Typically, we would configure different messages to align with state changes (e.g. Close, Resolve).

    The code in the 'Outbound condition' script field should look like this:

    Your Outbound Trigger form should look like this:

    13) Navigate to Inbound > Settings.

    Inbound Settings Fields

    The Inbound Settings fields to be configured are as follows:

    #

    Field

    Description

    Value

    14

    Bond reference method*

    Method of searching for and validating an existing bond for incoming messages.

    'Both'

    15

    Reference lookup script

    The script containing functions for extracting internal and external references from the request payload.

    Update the code in the Reference lookup script field so that it looks like the code below

    *Bond reference method:

    Internal - lookup using the internal reference only.

    External - lookup using the external reference only.

    Both - lookup using both the internal and external references.

    As mentioned earlier, because this is an update type message, we use 'Both' as it's a more accurate method of validating updates are being sent to/received from the correct bonded records.

    The code in the 'Reference lookup script' field should look like this:

    Your Inbound Settings form should look like this:

    16) Click Save.

    We are now ready to configure the Fields for our UpdateIncident Message.

    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.

    Icons

    Before continuing we would like to draw your attention to some of the relevant icons that are visible down the left hand navigation strip of the Unifi Integration Designer.

    The icons are:

    a) 'Integration' icon: Opens the current integration's Details page.

    b) 'Messages' icon: Opens the current integration's Messages page.

    c) 'Fields' icon: Opens the current integration's Fields page.

    d) 'Field Maps' icon: Opens the current integration's Field Maps page.

    e) 'Pollers' icon: Opens the current integration's Pollers page.

    f) 'Poll Processors' icon: Opens the current integration's Poll Processors page.

    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:

    2) 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 Setup script field is to be configured as follows:

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

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

    fields: The table API will return all the data by default, so we choose to deliberately limit what is returned to the fields listed in this variable.

    query: Instead of querying all the records on the remote instance, we deliberately limit the records to those where the correlation id is not empty (i.e. it's bonded), that haven't been updated by the Authentication user (our system) and that were updated since 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 variables in for the uri query and fields. This value is appended to the existing endpoint url in the active connection before being added to the Poll Request.

    Your Setup Script form should look like this:

    4) 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 Request script field is to be configured as follows:

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

    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:

    6) Navigate to Response Script.

    Response Script

    The Response Script is used to process the information returned from the remote system. We will pass this data to Unifi to process.

    The Response script field is to be configured as follows:

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

    Response script: This script parses the response into a body object to contain the result, (returning if it doesn't contain anything). It then sets up some objects to help us (including the essential PollHelper() function which we initialise from the poll_request). After that it loops through each of the returned tickets; for each it sets up a payload object and the options for submitting it to Unifi before calling the processInbound() method. It then checks whether the ticket was updated later than the last update time; if so, it sets and stores the last update time as that 'sys_updated_on' value (this 'last_update_time' is what the Setup script checks against when defining what the Poll will do).

    After looping through all the records, the results are logged to the Response status field of the Poll Request.

    Essential code: the following lines of code must be included in the response script to send the data to Unifi

    Your Response Script form should look like this:

    8) Save the Poll Processor.

    Now let's move on and configure the Poller.

    Test CreateIncident

    Follow these steps to test the CreateIncident Message.

    Because we have configured Unifi to connect to itself, we don't need to wait until we've connected to the external system before we test. We can test both sending and receiving Messages in the one instance. It goes without saying that these tests should be repeated once we have connected to the external instance.

    To test, we will create an incident in our instance and then follow the data as it flows through the Unifi transport stack and on to the newly created ticket (whether that be in our instance, or in the external system we are integrating with).

    Assignment Group

    We have data-driven the trigger for our Create Message so that it fires when a ticket is assigned to an assignment group which has the integration referenced on it. In order to test then, we’ll need to add our integration to the Unifi Integrations field on the assignment group that triggers our incidents. We will create a new assignment group as an example.

    In native ServiceNow, navigate to User Administration > Groups. Click New.

    The Group fields to be configured are as follows:

    *Unifi Integrations: This field may need to be created/added to the Group [sys_user_group] record.

    Your Group record should look like this:

    4) Submit.

    Create an Incident

    In native ServiceNow, navigate to Incident > Create New.

    The Incident fields to configure are as follows:

    *Note: We have chosen these fields as these were the ones we mapped when creating our Field records for the CreateIncident Message. Your choices may differ depending on which Field records you created.

    Your Incident form should look like this:

    8) Right-click & Save.

    Note the values entered (including State), so that you can check them against the mapped fields on the corresponding record in the instance being integrated to.

    You should see an Info Message, confirming the CreateIncident Message is being sent to your Integration:

    When you scroll down to the 'Unifi Integrations' related list (you may have to configure the related lists to add it to your Incident form), notice:

    9) A Bond has been created. The State remains 'Pending' until the list is refreshed.

    10) Refresh the list by clicking Bonds.

    You should see the External reference populated & the State changed to 'Open':

    11) Click the Bond Number link to open the Bond record.

    View the Bond

    Your Bond record should look like this:

    12) Bond details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    13) History:

    • < History of transaction updates on the Bond > (Sending CreateIncident...)

    14) Transaction:

    • Message ID: Internal system's unique Transaction identifier

    • External Message ID: External system's unique Transaction identifier

    • Message: 'Createincident'

    • Direction: 'Outbound'

    You are able to view the logs in the 'Unifi Activity Logs' related list.

    15) Transaction process next queued: Logs from checking whether there are any other transactions queued and processing those.

    16) Transaction receive message: Logs from processing the inbound asynchronous receipt.

    17) Transaction sending: Logs from taking the Stage data, building the Request record & sending the Request to the integrated system.

    18) Business rule: < Your Trigger >: Logs from the Business Rule that triggered Unifi.

    View the Transaction

    Click through to the Transaction record from the related list on the Bond.

    Your Transaction record should look like this:

    19) Transaction details:

    • Table: 'Incident [incident]'

    • Document: < Your Incident >

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    20) Errors:

    • Error: (If there was a transactional error the Transaction state would show as 'Error' and the details would be captured here).

    • Process error: (If there was a process error the Process state would show as 'Rejected' and the details would be captured here)

    21) Stages:

    • Direction: 'Outbound' & 'Inbound'

    • Message: 'CreateIncident' & 'CreateIncidentReceipt'

    • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

    • External reference: < External system's ticket reference >

    View the Stage

    Click through to the Outbound Stage record from the related list on the Transaction. (If you wish, you could also do the same for the Inbound Stage record.)

    Check the values in the fields match what you expect.

    Your Stage record should look like this:

    22) Stage details:

    • Direction: 'Outbound'

    • Internal reference: < ServiceNow ticket reference >

    • Message: 'CreateIncident'

    • Transaction: < Your Transaction >

    23) Mapped stage fields (yours may differ depending on which Field records you created.):

    • caller_id: < Your caller.id >

    • short_description: < Your Short description >

    • state: '1'

    View the HTTP Request

    Click through to the outbound HTTP Request record from the related list on the Transaction. (If you wish, you could also do the same for the Inbound HTTP Request.)

    This is where you will find details of the data that was transported between the systems being integrated. (These records are extremely useful for developing and debugging integrations because of the immediate availability and contextual relevance to the integration you are developing.)

    Your HTTP Request record should look like this:

    24) HTTP Request details:

    • Integration: < Your Integration >

    • Connection: < Your Connection >

    • Transaction: < Your Transaction >

    • Message: 'CreateIncident'

    25) Response details:

    • Status code: '200'

    • Response headers: < The header of the response being received >

    • Response payload: < The payload of the response being received >

    Compare with the External System's Incident

    Navigate to the corresponding Incident in the external system.

    Check the values in the fields match those you noted when you saved the Incident in the internal system.

    Your external system's Incident record should look like this (depending on the system you're integrating with, your record may look different; the important matter is that the values match):

    26) Caller: < Your Caller >

    27) State: < Your State >

    28) Short description: < Your Short description >

    29) Activities: < Note showing activity on the Incident > (Opened by < your.external.system.user > configured in the Connection)

    30) Bond: Note that a bond exists in the external system in an 'Open' state and the 'Internal reference' & 'External reference' are reversed

    If completing this test after having integrated with the external system (as opposed to connecting to your own instance), it would be good to test the CreateIncident Message in both directions.

    We are now ready to move to the Update Scenario.

    ResolveIncident Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the ResolveIncident Message.

    The 'message_header', 'incident.comments', 'incident.work_notes' and 'incident.short_description' Field records are already be in place because they were also copied when we copied the Message. We can choose to include, or exclude as many of those and the Integration level ones that are available depending on our requirements (by either activating or deactivating the relevant Fields). We have chosen not to include 'incident.short_description' in our mappings, so we'll delete that.

    In Unifi Integration Designer, from the ResolveIncident Message, navigate to Message > Fields.

    1) Click on the ellipsis to the right of the incident.short_description Field & click Delete.

    2) Confirm Delete.

    UpdateIncident Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the UpdateIncident Message.

    Field: message.message_header

    The 'message_header' (Integration level) Field record should already be in place (i.e. with Active set to false). We will now create its Message level counterpart.

    CreateIncidentReceipt Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the CreateIncidentReceipt Message.

    Copy Field Maps

    It is worth copying all relevant OOTB Field Maps as are necessary for your integration before using any of them in your Field Records - thereby mitigating the risk of any potential issues with future upgrades.

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping result.sys_id [x_snd_eb_field.do?sys_id=a7653549dbf9985094dbd7795e9619bc]", function () {
      log.debug("Field map: IS - Source Reference [x_snd_eb_field_map.do?sys_id=c930653cdb7d585094dbd7795e96199a]");
      payload = payload || {};
      payload.result = payload.result || {};
      var $payload = payload.result;
    
      stage.external_reference = '' + ($payload.sys_id || '');
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    bond.setOpen();
    var answer = {};
    
    answer.getExternalMessageID = function (payload, request) {
      return '' + (payload.message.source_id || '');
    };
    
    answer.getInternalMessageID = function (payload, request) {
      return '' + (payload.message.target_id || '');
    };
    bond.setOpen();
    (function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    
        x_snd_eb.ws_console.execute('Request received', function() {
            var helper = new x_snd_eb.RestHelper('incident_guide'); // the API name of the Unifi Process
            processAttachment(helper.getRequest().getRecord());
            helper.processRequest(request, response, 'POST'); // the HTTP method of the resource
        });
    
        /**
         * This scripted REST API allows an attachment to be sent into Unifi in a
         * similar way to the OOB api/now/attachment REST API, but it processes it
         * in Unifi.
         *
         */
        function processAttachment(target_record) {
          var file_name = request.queryParams.file_name;
          var reference = request.queryParams.reference;
          var mime_type = request.getHeader('Content-Type');
    
          if (!file_name || !reference || !mime_type) return;
    
          var ga = new GlideSysAttachment();
    
          // save the body to an attachment on the request
          var attachment_id = ga.writeContentStream(target_record, file_name, mime_type, request.body.dataStream);
    
          // return custom payload for the body to process
          helper._getRequestBody = function _getRequestBody() {
            return '{\n' +
              '"message":    { "name": "AddAttachment" },\n' +
              '"reference": "' + reference + '",\n' +
              '"attachment": "<x-attachment-data sys_id=\"' + attachment_id + '\" />"\n' +
            '}';
          };
        }
    
    })(request, response);
    !current.state.changes()
    var answer = {};
    
    answer.getExternalMessageID = function (payload, request) {
      return '' + (payload.message.source_id || '');
    };
    
    answer.getInternalMessageID = function (payload, request) {
      return '' + (payload.message.target_id || '');
    };

    The direction(s) this message is configured to support.

    'Bidirectional'

    Async receipt

    The asynchronous receipt to this message.

    <lookup: 'Receipt'>

    Bond pending

    Process this message when the bond state is Pending.

    <true>

    10

    Bond open

    Process this message when the bond state is Open.

    <true>

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

    params: The params object is passed through to the subsequent scripts (and on to further Pollers, if required).

    processInbound()
    : Having the 'poll_helper.processInbound(opts);' inside the loop means that an update message will be generated for each updated ticket.

    Payload object: We have chosen to structure the payload object (var pl) as we have. There is no obligation to keep the same structure. Yours can be defined to suit your requirements.

    Payload options: In the payload options (var opts), we have commented out //message_name: 'UpdateIncidentInbound',. This is because we have chosen to include the message name in the structure of the payload object.

    Message name: Unifi needs to know the message name in order to know how to process the inbound request. We can either set it in the payload (as we have), or in the options (as per the commented out line).

    #

    Field

    Description

    Value

    1

    Name

    The name of the Processor.

    <Your Name>

    #

    Field

    Description

    Value

    3

    Setup script

    The script to setup the Poll Request record.

    Update the code in the Setup script field so that it looks like the code below

    #

    Field

    Description

    Value

    5

    Request script

    The script that executes the request.

    Update the code in the Request script field so that it looks like the code below

    #

    Field

    Description

    Value

    4

    Response script

    The script that processes the response to the request.

    Update the code in the Response script field so that it looks like the code below

    Glide List referencing the Integration [x_snd_eb_integration] table.

    <Your Integration>

    The group which triggers the Integration.

    <Your Group>

    7*

    Short description

    A brief description of the incident.

    <Your Short description>

    State: 'Open' (Message exchange is available)

  • Status: 'OK' (All transactions have completed)

  • Internal reference: < ServiceNow ticket reference > (Same as 'Document')

  • External reference: < External system's ticket reference >

  • Transaction state: 'Complete' (The data has been successfully transported)

  • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

  • Bond: < Your Bond >

  • Message: 'CreateIncident'

  • Direction: 'Outbound'

  • Transaction state: 'Complete' (The data has been successfully transported)

  • Process state: 'Accepted' (The transaction was accepted as within the scope of the business logic that's in place)

  • Integration: < Your Integration >

    Direction: 'Outbound'

  • Request state: 'OK' (There are no errors with the HTTP Request.)

  • Attempt number: < Number of HTTP Request attempts > (Failed requests are retried up to the maximum attempts number as configured on the Integration.)

  • Endpoint URL: < The external system’s access URL >

  • Action Method: 'POST'

  • Request headers: < The header of the request being sent >

  • Request payload: < The payload of the request being sent >

  • #

    Field

    Description

    Value

    1

    Name

    Descriptive name, e.g. DBAs, Network, etc.

    <Your Name

    2

    Type

    Types of this group.

    'itil'

    3

    #

    Field

    Description

    Value

    5*

    Caller

    Person who reported or is affected by this incident.

    <Your Caller>

    *

    State

    The Incident lifecycle state.

    'New' - Default (Automatically populated)

    6

    Unifi Integrations*

    Assignment group

    Deleting here only deletes the Field record for this message. The integration level record and any other message level ones remain in place.

    Field: incident.state (Message level)

    Unifi created the incident.state (Integration level) Field record earlier. It is, therefore, displayed in the list with Active set to false.

    The fields to be changed to configure the incident.state (Message level) Field record are as follows:

    #

    Field

    Description

    Value

    3

    Active

    Set to true to create a Message level Field record from its Integration level counterpart.

    <true>

    By simply setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has created the Message level counterpart.

    Your ResolveIncident Message Fields page should look like this:

    The empty circle icon next to the Field name turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field).

    We will now configure Field records for the two remaining Incident record field elements which are required.

    Fields & Field Maps

    The table below lists the Incident record field elements we will map and the relevant Field Maps required to configure each Field record.

    Incident Field

    Field Map

    close_code

    'IG Choice'*

    close_notes

    'IG Journal field'*

    *Field map: Values may vary (dependent on your configuration of the copies). Choose the copy Field Maps you created earlier.

    Field: incident.close_code (Message level)

    There is no need to ‘Generate field choices’ for Message level Field records because the Field Map always looks for them on an Integration level Field which has the same name.

    As with 'incident.state' the 'incident.close_code' Field record is a Choice 'type' Field. We will, therefore, configure the choices once at the Integration level. We’ll first configure the Message level Field and then move on to configure the choices on its Integration level counterpart.

    From the ResolveIncident Message, navigate to Message > Fields. Click New.

    The fields to be configured for our incident.close_code (Message level) New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'ResolveIncident'

    4

    Description

    The description of this Field record.

    'The incident's Resolution code (Close code in ServiceNow)'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.close_code' (Message level) New Field modal should look like this:

    9) Submit the record.

    You will be redirected back to the Fields page of the ResolveIncident Message.

    Field: incident.close_code (Integration level)

    You will need to 'Generate field choices' for this Integration level Choice 'type' Field.

    Navigate to the 'Fields' icon to open the Fields page.

    10) Click to open the incident.close_code (Integration level) Field record (the one where Message is empty).

    The incident.close_code Field record opens to the Details page.

    11) Navigate to Field > Field Choices.

    12) Click Generate field choices.

    13) Click Generate on the 'Generate field choices' modal which displays.

    The Field Choices are generated & now visible in the list.

    Field: incident.close_notes

    Because the incident.close_notes Field record is the same 'type' (IG Journal field) & the majority of the settings are the same as the incident.work_notes Field, it will be quicker to copy that Field & make a few minor changes.

    From the ResolveIncident Message, navigate to Message > Fields.

    14) Click the ellipsis next to the incident.work_notes Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    #

    Field

    Description

    Value

    15

    Element

    The field on the source/target table this Field record is mapped to.

    'Resolution notes'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    16

    *This field is automatically populated.

    Your 'incident.close_notes' Copy Field modal should look like this:

    17) Click Copy.

    You will be redirected to the Details page of the newly created incident.close_notes Field record.

    Navigate to Field > Settings.

    18) Set Mandatory to true.

    19) Click Save.

    Build

    Now that we’ve configured the Field records for the ResolveIncident message, we are ready to build our message scripts.

    To quickly navigate to the ResolveIncident message from the Details page of the newly created incident.close_notes Field record…

    ...click the 'Preview' icon to the left of the Message field.

    From the ResolveIncident message, navigate to Message > Fields.

    The following Field records should now be in place for your ResolveIncident messsage:

    20) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    21) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    We are now ready to Test our ResolveIncident Message.

    From the UpdateIncident Message, navigate to Message > Fields.

    Your UpdateIncident Fields page should look like this:

    1) Find the message.message_header (Integration level) Field & set Active to true.

    The 'Build Integration' button becomes visible in the banner and the empty circle icon next to the Field name turns green & contains a green 'check' (to indicate that Message level configuration exists for this Field). Note: the empty 'circle icon' indicates that the Integration level Field is available to add to the Message.

    As before, by setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart.

    Next, repeat the process for the incident.short_description Field.

    Field: incident.short_description

    The 'incident.short_desccription' (Integration level) Field record should already be in place (i.e. with Active set to false). We will now create its Message level counterpart.

    Your UpdateIncident Fields page should look like this:

    2) Find the incident.short_description (Integration level) Field & set Active to true.

    The empty circle icon next to the Field name turns green & contains a green 'check' (to indicate that Message level configuration exists for this Field).

    We will now configure Field records for two other Incident record field elements.

    Fields & Field Maps

    As with the CreateIncident Message and depending on your requirements, you will need to create Field records for each of the relevant Incident record field elements (see the table in Fields & Field Maps on the 'CreateIncident Fields' page for an example). For the sake of brevity, this Guide will focus on two of those. If you wish, however, you are free to configure other Field records as required.

    The table below lists the Incident record field elements we will map and the relevant Field Maps required to configure each Field record.

    Incident Field

    Field Map

    comments

    Journal field

    work_notes

    Journal field

    Copy Field Maps

    If you haven't already, you will need to copy the relevant additional Field Maps for the UpdateIncident Field records as follows:

    • Journal field

    See Copy Field Maps (on the 'CreateIncidentReceipt Fields' page) for details.

    Field: incident.comments

    From the UpdateIncident Message, navigaate to Message > Fields & click New.

    The fields to be configured for our incident.comments New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'UpdateIncident'

    3

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The incident's comments'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.comments' New Field modal should look like this:

    7) Submit the record.

    You will be redirected back to the Fields page of the UpdateIncident Message.

    Field: incident.work_notes

    Because the incident.work_notes Field record is the same 'type' (IG Journal field) & the majority of the settings are the same as the previously configured Field, it will be quicker to copy the incident.comments Field & make a few minor changes.

    8) Click the ellipsis next to the incident.comments Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    #

    Field

    Description

    Value

    9

    Element

    The field on the source/target table this Field record is mapped to.

    'Work notes'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    10

    *This field is automatically populated.

    Your Copy Field modal should look like this:

    11) Click Copy.

    You will be redirected to the Details page of the newly created incident.work_notes Field record.

    Build

    Now that we’ve configured the Field records for the UpdateIncident message, we are ready to build our message scripts.

    To quickly navigate to the UpdateIncident Message from the Details page of the newly created incident.work_notes Field record…

    ...click the 'Preview' icon to the left of the Message field.

    From the UpdateIncident message, navigate to Message > Fields.

    The following Field records should now be in place for your UpdateIncident messsage:

    12) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    13) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    We are now ready to Test our UpdateIncident Message.

    The Field Maps we shall use for our CreateIncidentReceipt Field records are:
    • Message Header

    • Receipt Status

    To copy the Message Header Field Map, navigate to the 'Field Maps' icon.

    1) Click on the ellipsis to the right of the Message Header Field Map & then click Copy.

    Copy Field Map Modal

    The fields to edit for the Copy Field Map modal are as follows:

    #

    Field

    Description

    Value

    2

    Name*

    The name of your field map. (If left unedited, it will append the word 'Copy' to the existing name.)

    <Your Name>

    3

    Integration

    The integration this field map is associated with.

    <Your Integration>

    *Name: We have chosen to prefix the existing Field Map Name with the initials of our Integration (you are free to choose any appropriate means of identifying/differentiating).

    Your Copy Field Map modal should look like this:

    4) Click Copy.

    You will be redirected to the Details page of the newly created Field Map.

    Repeat the process for the Receipt Status Field Map.

    Field: message.message_header

    From the CreateIncidentReceipt Message, navigate to Message > Fields. Click New.

    The fields to be configured for our message_header New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncidentReceipt'

    5

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The protocol message header'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'message_header' New Field modal should look like this:

    10) Submit the record.

    You will be redirected back to the Fields page of the CreateIncidentReceipt Message.

    Field: message.transaction_details

    Click New.

    The fields to be configured for our transaction_details New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    (automatically populated)

    11

    Description

    Describe what this field is for and any specific details that might help you in future.

    'Used to send and receive transaction process errors'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'transaction_details' New Field modal should look like this:

    16) Submit the record.

    You will be redirected back to the Fields page of the CreateIncidentReceipt Message.

    Build

    Now that we’ve configured the Field records for the CreateIncidentReceipt message, we are ready to build our message scripts.

    The following Field records should now be in place for your CreateIncidentReceipt messsage:

    Feature Alert: In the picture above you will notice that a 'Build Integration' button has appeared in the banner at the top of the page. Whenever a change is made to a Field record that is associated to a Message (whether that is being created, updated, or deleted) the button will be available and acts as a visual reminder that changes have been made and Message Script(s) need to be built. We will talk more about this feature in the Build Integration Level page.

    17) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    18) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    Stage to Target:

    The code we had previously added when configuring our Message as per the 'CreateIncidentReceipt Message' page is still in place and can be seen after the End Comment.

    The code in the ‘Stage to Target’ script field should look like this:

    We are now ready to configure our CreateIncident Message.

    Relative path

    The path of this resource relative to the base API path. Can contain templatized path parameters such as /{id}.

    '/' (Automatically populated)

    7

    Script

    The script that implements the resource.

    Replace the contents of the script field with your REST API code, substituting your Process API name (see below). E.g. var helper = new x_snd_eb.RestHelper('incident_guide');

    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.

    New Poll Processor

    In Unifi Integration Designer, 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:

    2) 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 Setup script field is to be configured as follows:

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

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

    fields: The table API will return all the data by default, so we choose to deliberately limit what is returned to the fields listed in this variable. Instead of hardcoding them into the script, we have chosen to substitute Connection Variables containing those values.

    query: Instead of querying all the records on the remote instance, we deliberately limit the query to those active records where the correlation id is empty (i.e. it's not bonded), that have been assigned to a specific Assignment group and haven't been updated by the Authentication user (i.e. not created by our system), and that were also updated since 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 variables in for the uri query and fields. This value is appended to the existing endpoint url in the active connection before being added to the Poll Request.

    Your Setup Script form should look like this:

    4) 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 Request script field is to be configured as follows:

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

    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:

    6) Navigate to Response Script.

    Response Script

    The Response Script is used to process the information returned from the remote system. We will pass this data to Unifi to process.

    The Response script field is to be configured as follows:

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

    Response script: This script parses the response into a body object to contain the result, (returning if it doesn't contain anything). It then sets up some objects to help us (including the essential PollHelper() function which we initialise from the poll_request). After that it loops through each of the returned tickets; for each it sets up a payload object and the options for submitting it to Unifi before calling the processInbound() method. It then checks whether the ticket was updated later than the last update time; if so, it sets and stores the last update time as that 'sys_updated_on' value (this 'last_update_time' is what the Setup script checks against when defining what the Poll will do).

    After looping through all the records, the results are logged to the Response status field of the Poll Request.

    Essential code: the following lines of code must be included in the Response script to send the data to Unifi

    Your Response Script form should look like this:

    8) Save the Poll Processor.

    Now let's move on and configure the Poller.

    CreateIncident Message

    The CreateIncident Message will create a ticket on the target table of the integrated system.

    As previous, after clicking the 'Messages' icon, you will see the following screen (note: both the previously configured messages are now visible in the list):

    1) Click New.

    New Message Modal

    The fields to be configured for the CreateIncident New Message modal are as follows:

    2.0 Release Notes

    Here you will find details of what's changed in this release, including new features & improvements, depracated features and general fixes.

    Introduction

    Welcome to the release notes for Unifi - Version 2.0. Please have a read through to see new features and fixes that have been added.

    // Configure the new Poll Request record
    (function(poll_request, poller, params) {
    
        var gdt = new GlideDateTime();
        gdt.addSeconds(-1800);
    
        var connection = poller.getIntegration().getActiveConnection();
        var user = connection.getBasicAuthUser();
        var time = connection.getData('last_update_time', (gdt + ''));
    
        var fields = 'sys_id,number,correlation_id,short_description,description,sys_updated_on,sys_updated_by';
    
        var query = [
            'correlation_idISNOTEMPTY',
            'sys_updated_by!=' + user,
            'sys_updated_on>' + time
        ];
    
        var uri_query = query.map(function(c) {
            return encodeURIComponent(c);
        }).join('%5E');
    
        poll_request.endpoint_url += '?sysparm_query=' + uri_query +
            '&sysparm_fields=' + encodeURIComponent(fields) + '&sysparm_limit=10';
    
    })(poll_request, poller, params);
    // 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);
    // 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) {
    
        var body = JSON.parse(response);
    
        // Process the result
        var conn = poller.getIntegration().getActiveConnection();
        var cvars = conn.getVariables();
    
        var poll_helper = new x_snd_eb.PollHelper(poll_request);
        var info = [];
    
        if ( body.result.length == 0 ) {
            status = 'No Incident found';
            poll_request.response_status = status + '\n\n' + JSON.stringify(body,null,2);
            return;
        }
    
        body.result.forEach(function(inc){
    
            // Set up the payload object
            var pl = {
                message : {
                    name: 'UpdateIncidentInbound',
                    source_reference: inc.sys_id
                },
                detail : {
                    short_description : inc.short_description,
                    description : inc.description
                }
            };
    
            // Set up the options object for message submission
            var opts = {
                //message_name: 'UpdateIncidentInbound',
                payload : JSON.stringify(pl)
            };
    
            poll_helper.processInbound(opts);
    
            var inc_time = inc.sys_updated_on;
            info.push('Incident : ' + inc.number + ' (' + inc_time + ')');
    
            // Set last update time (if later)
            var conn_time = conn.getData('last_update_time');
            if ( inc_time > conn_time ) {
                conn.setData('last_update_time',inc_time);
            }
    
        });
    
        poll_request.response_status = info.join('\n') + '\n\n' + JSON.stringify(body,null,2);
    
    })(poll_request, poller, response, params);
    var poll_helper = new x_snd_eb.PollHelper(poll_request);
    poll_helper.processInbound(opts);
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    
    
    if (x_snd_eb.ws_console.hasError()) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    bond.setOpen();

    &sysparm_display_value=true: Adding this parameter means that reference data will return an object containing the 'display_value' element instead of the 'value' element. We will talk more about the relevance of this when mapping the caller_id field on the 'CreateIncidentInbound Fields' page.

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

    params: The params object is passed through to the subsequent scripts (and on to further Pollers, if required).

    processInbound()
    : Having 'poll_helper.processInbound(opts);' inside the loop means that an update message will be generated for each updated ticket.

    Payload object: We have chosen to structure the payload object (var pl) as we have. There is no obligation to keep the same structure. Yours can be defined to suit your requirements.

    Payload options: In the payload options (var opts), we have commented out //message_name: 'UpdateIncidentInbound',. This is because we have chosen to include the message name in the structure of the payload object.

    Message name: Unifi needs to know the message name in order to know how to process the inbound request. We can either set it in the payload (as we have), or in the options (as per the commented out line).

    #

    Field

    Description

    Value

    1

    Name

    The name of the Processor.

    <Your Name>

    #

    Field

    Description

    Value

    3

    Setup script

    The script to setup the Poll Request record.

    Update the code in the Setup script field so that it looks like the code below

    #

    Field

    Description

    Value

    5

    Request script

    The script that executes the request.

    Update the code in the Request script field so that it looks like the code below

    #

    Field

    Description

    Value

    7

    Response script

    The script that processes the response to the request.

    Update the code in the Response script field so that it looks like the code below

    #

    Field

    Description

    Value

    2

    Message name

    The message name that is unique for this integration.

    'CreateIncident'

    3

    Type

    The primary purpose of the message.

    'Create'

    4

    Direction

    Your CreateIncident New Message modal should look like this:

    5) Submit and view to further configure the Message.

    Response Fields

    Navigate to Message > Response.

    The Response fields to be configured are as follows:

    #

    Field

    Description

    Value

    6

    Response

    The immediate synchronous response to this message.

    <lookup: 'Response'>

    *

    Async

    Turn this option on if you want inbound processing to occur asynchronously or this message is the first of an asyncronous message pair.

    <true>

    7

    *This field is automatically defaulted to true.

    Your Response form should look like this:

    8) Navigate to Message > Bond.

    Bond Fields

    The Bond fields to be configured are as follows:

    #

    Field

    Description

    Value

    *

    Bond ownership

    Determine if the sender should own the bond or not in order for this message to be processed? Use 'Ignore' to process regardless of the owner flag. (Choices: Ignore, Must own, Must not own.)

    'Ignore'

    *

    Bond condition type

    The type of conditional check made on the bond. (None: no checks are made. State: checks against the state are made using the conditional checkboxes. Scripted: the 'Bond condition' script is used.)

    'State'

    9

    *These fields are automatically populated.

    Your Bond form should look like this:

    10) Navigate to Outbound > Trigger.

    Outbound Trigger Fields

    The Outbound Trigger fields to be configured (as required)* are as follows:

    #

    Field

    Description

    Value

    11

    Outbound condition*

    The condition that the ServiceNow record must meet to trigger this message being processed.

    Update the Outbound condition script field with the code below

    *Outbound condition (as required):

    It is not necessary for you to enter a condition. The value given is an example. You may create any condition (or not) to align with your business process requirements.

    The code in the 'Outbound condition' script field should look like this:

    This is an example of data-driving the trigger condition. This script checks whether the integration that this message belongs to is listed in a custom field on the assignment group which references the integration.

    Your Outbound Trigger form should look like this:

    12) Navigate to Outbound > Settings.

    Outbound Settings Fields

    The Outbound Settings fields to be configured are as follows:

    #

    Field

    Description

    Value

    13

    Action method

    The SOAP Action or the REST Method to use for this message. If this field is empty the SOAP Action will default to the message name and the REST Method will default to POST.

    'POST'

    Your Outbound Settings form should look like this:

    14) Navigate to Inbound > Settings.

    Inbound Settings Fields

    The Inbound Settings fields to be configured are as follows:

    #

    Field

    Description

    Value

    *

    Bond reference method

    Method of searching for and validating an existing bond for incoming messages.

    'External'

    15

    Reference lookup script

    The script containing functions for extracting internal and external references from the request payload.

    Update the code in the Reference lookup script field so that it looks like the code below

    *This field is automatically populated & not editable.

    Bond reference method:

    Internal - lookup using the internal reference only.

    External - lookup using the external reference only.

    Both - lookup using both the internal and external references.

    Bond reference method: The perspective of the available choices is in relation to the receiving instance i.e. Internal (internal reference) means the bonded ticket in our instance and External (external reference) means the bonded ticket in their instance.

    Primarily used in relation to create and update type messages, these settings define which values to lookup against to search for and validate whether or not a bond already exists.

    In the case of a create type message, we use 'External' because there is not yet a bonded ticket in the receiving instance to reference (if we were to receive a create type message which referenced a bond that already existed it would be rejected because we don't want to create another bond for a record we've already seen ).

    In the case of an update type message, we use 'Both' because it's a more accurate method of validating updates are being sent to/received from the correct bonded records.

    The code in the 'Reference lookup script' field should look like this:

    Your Inbound Settings form should look like this:

    16) Navigate to Advanced > Script Editor.

    Script Editor Fields

    As previously stated, as well as being the place where Bond state & ownership are set, the Scripts are where the request processing and data mapping occurs.

    Click on View > Inbound.

    The Script Editor fields to be configured are as follows:

    #

    Field

    Description

    Value

    17

    Stage to Target (Inbound)

    The script to run.

    Replace the commented out instructions with the following code: bond.setOpen();

    Scripts

    In the current release, there is no OOTB Field Map record with which we can set the state on the Bond. We shall, therefore, script that manually. For more information, see the 'Fields' & 'Field Maps' pages in our technical documentation.

    The code in the 'Stage to Target' script field should look like this:

    Your Script Editor fields should now look like this:

    18) Click Save.

    19) Close the Script Editor to navigate back to the Message.

    We are now ready to configure the Fields for our CreateIncident Message.

    Upgrade Notice

    Please note that this is a major release which may not be entirely compatible with your existing integrations. While we do everything to make sure you won't have to fix your integrations when upgrading, we strongly encourage all our customers to perform full end-to-end tests of their integrations before upgrading Unifi in Production.

    Feedback and Reviews

    We really appreciate feedback on what we're doing - whether it's right or wrong! We take feedback very seriously, so if you feel you'd give us anything less than a 5 star rating, we'd love to hear from you so we can find out what we need to do to improve!

    If you would rate us 5 stars, and haven't left a review on the ServiceNow Store yet, we'd really appreciate you heading over there to leave us your feedback. It only takes a few minutes and really does help us a lot. Go on, you know you want to leave a 5-star review on the Store!

    Release Overview

    The following items are the major talking points for this release.

    Service Portal Interface

    Now that Unifi has a solid and proven foundation for building and running integrations, we have built a new Service Portal interface to make it simpler and easier than ever to build an integration. This new interface has been developed from the ground up to be scalable, intuitive and capable of supporting advanced features.

    Unifi version 2.0 marks the first release of the portal, with the ability to build Processes, Integrations and Messages, but we will be adding to it in future releases.

    Also of importance is the new Dashboard which gives a clear overview of what is happening in your instance right now. A live view of the last 20 transactions to be processed and the bonds that have been worked on today really helps you to see what's going on.

    Madrid Ready

    Unifi is tested to be compatible with all current ServiceNow releases: Kingston, London and Madrid.

    Queue Management

    A lot of effort has been put into upgrading the queue management options that are available. Things like replaying Transactions and Requests now use brand new technology which allows them to be much more robust and as close to a clone of the original as possible. It's also now possible to repair all the outstanding Transactions directly from the Integration with the click of a button.

    Field Mapping

    This release introduces the concept of Field Maps. These allow you to configure your messages with Fields and reusable Field Maps which then automatically generate all your scripts, so you don't need to write any code.

    Field Maps have no negative performance impact - in fact, they might be slightly faster - because all the logic to be executed is copied into the Message Scripts when the integration is built. Any existing code in your Message Scripts is retained so you always have the option of doing things manually.

    Activity Logs

    Anyone that's used Unifi knows that a major benefit of building integrations in Unifi is the logging and profiling capability. We've now expanded this capability to make it more easily and widely accessible, so even background processes have complex logs available to see.

    With the introduction of the Activity Log table, this becomes your first port of call when trying to looking for issues.

    Features

    [UN-124] - Add description to connection variables to allow explanation of their use

    It is now possible to add a description to the Connection Variable (up to 4000 characters) so notes or explanations can be stored.

    [UN-127] - Replay All errored transactions

    The Integration record now features a 'Repair' button which will automatically batch process all errored transactions. A background process is executed and with status being displayed through a progress bar.

    [UN-152] - Sending attachments

    • This is a breaking change

    Some improvements have been made to the attachment sending.

    Two new fields are now available on Message:

    • Send attachments [true/false]

    • Send attachments max [Integer - default 1]

    In addition to these new fields, the method AttachmentHandler#getAttachmentsToSend(message, transaction) now takes two arguments where previously it took one. It is this method modification that may break some existing installations that manually call this method (e.g. in a UI Macro or Script Include). Please check usage of this before upgrading.

    [UN-170] - Add reprocess/resend to HTTP requests

    Replaying an HTTP Request now works properly for both inbound and outbound requests. Previously, complexities with the process prevented this from being fully implemented.

    [UN-178] - Activity Log

    Unifi has a very smart profiling and logging tool called console which allows detailed logs to be attached to contextually relevant records. While this has been incredibly useful it fell short in two areas. The first is that it would add lots of attachments to the database over time, and the second is that it wasn't easily possible to log non-record generating processes, such as background clean-up jobs.

    This update addresses both of these issues through the addition of a new table called Activity Log. The table means that attachments are no longer needed because all transactions are automatically logged. It also means that background processes can be tracked because they do not need a record to belong to. The logs are stored in the table and rendered without needing to download or open an attachment.

    Activity Logs will also track (where possible) the integration they belong to and the contextual record it is about. Related lists have been added in places like Bond, Transaction and Request so that Activity Logs can be easily referenced.

    By default, Activity Logs are stored for 7 days.

    [UN-210] - Dynamic Stage object so we don’t need to extend

    Traditionally, local staging tables have been required for each process to capture data at a point in time. This data would then be available to process accurately, but it was also providing a log for future reference. The problem was a new Stage table would need to be created before the Process could be created. Then, any time a data point was needed, a new field would have to be added to the custom stage table.

    Dynamic Stage does away with the need for custom stages per process and removes the need to create fields by storing data dynamically as you use it. New Processes only need to reference the Unifi Stage table, and Dynamic Stage will take care of everything else.

    • This change is fully backwards compatible with the traditional one stage table per process.

    Start using Dynamic Stage in your Message Scripts by assigning to and from the $stage object instead of stage. It is possible to add not only strings to $stage, but also complex objects and arrays. Just make sure that things like field objects are coerced to strings (or use getValue()) otherwise you'll see something like [object Object] instead of the string value you expect.

    • Custom stage tables will work with Dynamic Stage, but you will need to add the Stage Data Render formatter to the form layout.

    [UN-266] - Clone cleanup should disable all non-instance specific connections

    By default, the Integrations Enabled system property (x_snd_eb.active) is disabled when an instance is cloned. This update also disables all Connections to prevent accidental connection to the wrong endpoint.

    [UN-268] - Add automatic domain setting for Bond and Transaction stack

    The domain field is now automatically set for transactional records using the following logic:

    • Bond domain comes from Target domain (e.g. Incident).

    • Transaction domain comes from Bond domain.

    • Stage domain comes from Transaction domain.

    • HTTP Request domain comes from Transaction domain.

    • Bonded Attachment domain comes from Bond domain.

    [UN-269] - Modify response action override message

    The response action error message has been modified to be more descriptive.

    e.g. Socket timeout handled by response action "Default 0 Script Errors"

    [UN-272] - Add indexes

    All tables have been indexed according to the data and queries being used. This should improve performance, especially when loading/searching lists.

    [UN-276] - Allow multiple ignore and ignore from right click (Transaction)

    Transactions can now be ignored from the list context menu and by a list button.

    [UN-299] - Add description fields to configuration records

    Add description field to all configuration type records.

    • Process

    • Integration

    • Message

    • Response Action

    • Poller

    • Poll Processor

    [UN-304] - Break out GlideRecord#operation() to Model method

    It is now possible to check the record operation from the Unifi Model class.

    [UN-307] - Add link to app log

    The System Log module has been updated to point to the scoped log rather than the system log.

    [UN-309] - Update sync overdue transaction job BR on integration

    The business rule that generates the overdue transaction jobs for each integration is now wrapped so it appears in the Activity Log.

    [UN-317] - Refine Message.processOutbound

    The Message.processOutbound() method has been improved to be more efficient and provide better visibility of processing.

    [UN-318] - Add method to console for executing a function

    A new method ws_console.execute() wraps an inline function in console logic and prevents errors from leaking (as errors are captured by the Activity Log and automatically put in gs.error()).

    It should be used in all business rules and scheduled jobs, and anywhere else a script runs in Unifi.

    [UN-320] - Add cleanup job for pollers

    A scheduled job has been added run every hour and uses a new cleanup field on the Poller record to determine how many days to keep Poll Requests for.

    [UN-326] - Poll Requests module should filter by created on today

    Viewing Poll Requests from the application navigator will now filter to show only those created today.

    [UN-340] - Sync responses do not have automatic access to internal reference

    When an inbound sync request was made, the internal stage did not get auto populated with the internal_reference field for use by the response message (e.g. to give the Incident number that was created). Unifi now checks if it has a value and if not, auto-populates it.

    [UN-352] - Copy message

    A Copy action is now available on the Message form which copies the Message and its Scripts.

    [UN-353] - Copy connection

    A Copy action is now available on the Connection form which copies the Connection and its Variables.

    [UN-354] - Add support for streaming an attachment over REST

    Unifi now supports sending a whole attachment as the request instead of having it sent as part of the body. This method streams the attachment rather than embedding it which means attachments larger than the string limit (5MB) can now be sent.

    To use this feature, simply set the payload of the request to be sys_attachment:<sys_id> and Unifi will automatically sent the specified attachment.

    [UN-355] - Improve environment objects for identify_message script

    The Identify message script on the Integration is now provided with integration and connection GlideRecord objects. The objects now available are payload, headers, integration, connection and variables.

    [UN-361] - Add link parsing to console

    Console logs now replace text in the format table.sys_id with a link to the record in HTML format. If the record is found then the table label and record display value are also shown. This allows users to easily open records used during the process.

    [UN-363] - Add link to broken transactions on integration

    A View broken transactions related link is now available on the integration to easily view all transactions that are errored or timed out.

    [UN-366] - Process stage table should be default to x_snd_eb_stage.

    With the introduction of Dynamic Stage, new Process records default to use the Unifi Stage table.

    UN-367] - Allow request error to show in Transaction instead of 'Final retry failed.'

    The "Final retry failed" error shown in transactions was not helpful and has now been replaced with the error generated by the latest request that failed.

    [UN-368] - If transaction is ignored, prevent in flight request from sending

    Ignoring a transaction midway through a request being processed would not prevent the request from being sent. Requests now check if the transaction is cancelled just before sending and will automatically cancel themselves if the transaction is cancelled.

    [UN-374] - Remove irrelevant debug statements

    Irrelevant debug statements have been tidied up so they either do not show or only show when trace logging is enabled.

    [UN-376] - Replace snd_console with ws_console

    When Unifi was first created, snd_console was also created to be used for profiling and debugging. With the company transitioning from the old name SN Developer to Whitespace Studios, we have replaced snd_console with ws_console. You might even see ws_console become available for your own apps in future!

    • This change is backwards compatible. snd_console still exists in Unifi so any code in your instance that uses this method will still work.

    [UN-377] - Message path should allow ${} variable format

    The Path on Message would only allow inline scripts using the {} format, but this is inconsistent with the rest of ServiceNow so it now accepts ${} or {} to define inline scripts. e.g.

    /upload?id={variables.uid}

    or

    /upload?id=${variables.uid}

    Fixes

    [UN-150] - Replay request/transaction needs to run as the original creator.

    When replaying requests or transactions, the replay would run as the logged in user instead of the original user. It now runs as the original user to allow functionality that relies on the identity of the user to run correctly.

    [UN-228] - Overhaul pending transactions counter

    It is possible for Pending transactions counter on the Bond record to get out of sync. Pending transactions are now calculated differently to try to prevent this from happening.

    [UN-257] - Message processOutbound is processing messages for inactive integrations

    Integrations that were inactive were still being processed for messages to send when an insert/update was made to a record. This fix prevents inactive integrations from having their messages processed.

    [UN-260] - Payload object is not automatically converted to JSON for Stage to Request

    Integrations using JSON payloads had to manually stringify the payload object in the Stage to Request script. You can now just set the global variable payload to your payload object and it will automatically convert it to JSON.

    [UN-274] - Poller doesn't check for integration off property

    Pollers would still run even if the integration was disabled. This fix means Pollers will not run if the integration is disabled.

    [UN-275] - RestHelper wraps with 'result'

    • This is a breaking change

    When using a scripted REST API with the Unifi RestHelper, ServiceNow automatically wrap any non-streamed response in a result object which makes it difficult to integrate with other systems that have specific response requirements. This fix uses the streaming method to send the response payload which means the message controls the whole response and no result wrapper is added.

    [UN-283] - ITIL users cannot see the message names when viewing bond/transactions.

    Security rules have been created to allow ITIL users to see the names of the messages that have been used when viewing from transactional data such as bonds and transactions.

    [UN-285] - Attachment added can only be true on one message

    Previously, only one message per integration could be configured with the 'Attachment added' trigger condition. This update allows one message per table per integration instead.

    [UN-289] - Attachment business rule does not run on update

    Some processes will update attachment records and these updates were not captured by Unifi. This fix addresses that so updates to attachments will check integrations.

    [UN-290] - REST XML does not work

    This fix allows XML to work properly with scripted REST API's using the Unifi RestHelper.

    [UN-303] - When getting the bond need to order by created at ascending

    This fix addresses issues finding the correct bond for integrations that can create more than one bond per ticket and see transactions spread between different (incorrect) bonds.

    [UN-306] - ITIL users cannot see the integration names when viewing bond/transactions.

    Security rules have been created to allow ITIL users to see the names of the integrations that have been used when viewing from transactional data such as bonds and transactions.

    [UN-308] - Data Store checkOrphans method causing errors for empty table name

    The scheduled orphan record checker for Data Stores would cause errors when the record that owner the data store was deleted. This would cause the getRefRecord() method to fail.

    [UN-314] - Receiving errors in processing poll requests due to string being too big

    Pollers that return strings that are outside the string size limit (usually > 5MB for scoped applications) will generate an exception. A try/catch has been added to help avoid the exception and allow the script to keep running and gracefully exit.

    [UN-319] - Repeating an inbound create request causes multiple bonds

    When replaying an inbound create request, it would run as the user who replayed the request. Unifi saw this as a new create as it wasn't created by the Integration User. This has been fixed by replaying using a scheduled job that runs as the user that created the original request.

    [UN-328] - Outbound attachment sending loop

    Sending an outbound attachment that is rejected could result in the attachment being picked up with the next transaction which could also fail, thus causing an infinite loop. Bonded attachments are now only picked up in the Ready state where previously it was Ready or Rejected.

    [UN-334] - Sync integration doesn't update bond external reference from stage, but async does.

    The External reference on the Bond had to be written to manually for a synchronous message, where it happened automatically for an asynchronous message. It now works automatically for both types of message.

    [UN-343] - Multi-table attachment processing

    If an integration belonged to a process which pointed to a different table to the attachment sending message, the attachment listener on sys_attachment would not find the message. This is fixed with an option being passable to Message.processOutbound so the table hierarchy will be searched.

    [UN-348] - Affected CI logic updating incident is causing double updates

    A caching issue meant it was possible for a work note to be added to the Incident whenever a CI was added/removed from the form. This has been fixed with a more intelligent mechanism of referencing the target record.

    [UN-350] - Unifi message name header needs to be case insensitive

    Message identification can be done by the request passing a specific header that Unifi recognises rather than adding the message name to the payload. However, headers in ServiceNow Scripted REST are always converted to lowercase which meant the Unifi header name, which used uppercase characters, did not work. This has been fixed by using case-insensitive matching on the Unifi message name header.

    [UN-351] - Inbound user should not be mandatory

    The Inbound user field on Connection is no longer mandatory. This is important for outbound-only integrations which do not require or permit any inbound requests.

    [UN-356] - Add condition to the sys_attachment Unifi trigger

    There were scenarios where Unifi log attachments could be sent by Unifi via the integration. Additional conditions on the sys_attachment business rule now prevent this from happening.

    [UN-375] - Request URL's have duplicate host

    If an integration required two endpoints (such as a ServiceNow Table API integration which also uses the Attachment API), the secondary host defined in a connection variable would not replace the host defined on the connection. The resulting URL had the connection endpoint followed by the variable endpoint.

    e.g. Connection URL: https://test.service-now.com/api/now/table Connection Variable value (attachment_api): https://test.service-now.com/api/now/attachment Message path: {variables.attachment_api} Resulting URL: https://test.service-now.com/api/now/tablehttps://test.service-now.com/api/now/attachment

    The workaround was to put both hosts in variables, but it has now been fixed so that the message path is pre-processed first and then the connection path is prepended if the resulting URL does not contain a schema (i.e. ://).

    [UN-379] - Inbound attachment does not trigger outbound attachments for other bonds

    In the multi-bond scenario where one ticket is bonded to many integrations, an inbound attachment will automatically create Bonded Attachment records for all the other Bonds. The problem was it didn't trigger the outbound message processing so those attachments didn't get sent automatically. This is now fixed so the outbound messages are processed when the bonded attachments are created.

    Active

    Set to true to use this Field record for processing.

    <true>

    5

    Field map

    The Field Map this Field record is linked with.

    'IG Choice'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    6

    Element

    The field on the source/target table this Field record is mapped to.

    'Resolution code'

    7

    Path

    Where in the payload the data will be placed.

    'detail'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    8

    Mandatory

    Set to true to make mandatory.

    <true>

    Description

    The description of this Field record.

    'The incident's Resolution notes (Close notes in ServiceNow)'

    Active

    Set to true to use this Field record for processing.

    <true>

    4

    Field map

    The Field Map this Field record is linked with.

    'IG Journal field'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    5

    Element

    The field on the source/target table this Field record is mapped to.

    'Additional comments'

    6

    Path

    Where in the payload the data will be placed.

    'detail'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The incident's work notes'

    Active

    Set to true to use this Field record for processing.

    <true>

    6

    Field map

    The Field Map this Field record is linked with.

    'IG Message Header'**

    7*

    Map to field

    Use this Field record to represent a field on a source/target table.

    <false>

    8

    Path

    Where in the payload the data will be placed.

    'message'

    9

    Property

    The property in the payload the data will be written to.

    'message_header'

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    Active

    Set to true to use this Field record for processing.

    <true>

    12

    Field map

    The Field Map this Field record is linked with.

    'IG Receipt Status'**

    13*

    Map to field

    Use this Field record to represent a field on a source/target table.

    <false>

    14

    Path

    Where in the payload the data will be placed.

    'message'

    15

    Property

    The property in the payload the data will be written to.

    'transaction_details'

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    UpdateIncident Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the UpdateIncident Message.

    Field: incident.short_description

    The 'incident.short_desccription' (Integration level) Field record should already be in place (i.e. with Active set to false). Creating the Message level counterpart is now easier than ever.

    From the UpdateIncident page, navigate to Message > Fields.

    1) Find the incident.short_description (Integration level) Field & set Active to true.

    The 'Build Integration' button becomes visible in the banner and the empty circle icon next to the Field name turns green & contains a green 'check' (to indicate that Message level configuration exists for this Field).

    By simply setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart. The Integration level record still exists (and can be seen when you click on the 'Fields' icon to navigate to the Fields page), but is no longer visible in the list view on the Message because the Message level record has been created.)

    Hints & Tips: Unifi automatically creates Integration level Fields when we first create the Message level equivalent records; those Integration level Fields are visible on the Fields list of the Messages we subsequently create. Therefore, if a Field is required for multiple Messages, create it once for the first Message and then simply set active to true for its Integration level counterpart from the Fields list of each of the relevant Messages that Field is required on.

    We will now configure Field records for two other Incident record field elements.

    Fields & Field Maps

    The table below lists the Incident fields above and the relevant Field Maps required to configure each Field record.

    We have chosen String type here because we are integrating with the table API. This will return the contents of those fields as a string value. If we were integrating Unifi to Unifi we may use a Journal field type which would return an array of comments objects with "text", "created_on", "created_by" & "published" elements.

    *Field map: Values may vary (dependent on your configuration of the copies). Choose the copy Field Maps you created earlier.

    Field: incident.comments

    Because the incident.comments Field record is the same 'type' (IS - String) & the majority of the settings are the same as the previously configured Field, it will be quicker to copy the incident.short_description Field & make a few minor changes.

    2) Click the ellipsis next to the incident.short_description Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    *This field is automatically populated.

    Your Copy Field modal should look like this:

    5) Click Copy.

    You will be redirected to the Details page of the newly created incident.comments Field record.

    Field: incident.work_notes

    It will again be quicker to copy the previously configured incident.comments Field & make a few minor changes.

    To quickly navigate back to the UpdateIncident Message, click the 'Preview' icon next to the Message field on the Details page of newly created incident.comments Field record.

    Navigate to Message > Fields.

    6) Click the ellipsis next to the incident.comments Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    *This field is automatically populated.

    Your Copy Field modal should look like this:

    9) Click Copy.

    You will be redirected to the Details page of newly created incident.work_notes Field record.

    Build

    Now that we’ve configured the Field records for the UpdateIncident message, we are ready to build our message scripts.

    Navigate to the UpdateIncident Message, then navigate to Message > Fields.

    The following Field records should now be in place for your UpdateIncident messsage:

    10) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    11) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    We will now examine our new, auto-generated Message Scripts.

    Source to Stage:

    Stage to Request:

    We are now ready to Test the UpdateIncident Message.

    // Configure the new Poll Request record
    (function(poll_request, poller, params) {
    
        var gdt = new GlideDateTime();
        gdt.addSeconds(-1800);
    
        var connection = poller.getIntegration().getActiveConnection();
        var cvar = connection.getVariables();
    
        var user = connection.getBasicAuthUser();
        var time = connection.getData('last_update_time', (gdt + ''));
        var group = cvar.external_group + ''; //Poller Integration Support 
        var fields = cvar.base_fields + ',' + cvar.data_fields;
    
        var query = [
            'active=true',
            'correlation_idISEMPTY',
            'assignment_group=' + group,
            'sys_updated_by!=' + user,
            'sys_updated_on>' + time,
            'ORDERBYsys_updated_on'
        ];
    
        var uri_query = query.map(function(c) {
            return encodeURIComponent(c);
        }).join('%5E');
    
        poll_request.endpoint_url += '?sysparm_query=' + uri_query +
            '&sysparm_fields=' + encodeURIComponent(fields) + '&sysparm_display_value=true' + '&sysparm_limit=10';
    
    })(poll_request, poller, params);
    // 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);
    // 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) {
    
        var body = JSON.parse(response);
    
        // Process the result
        var conn = poller.getIntegration().getActiveConnection();
        var cvars = conn.getVariables();
    
        var poll_helper = new x_snd_eb.PollHelper(poll_request);
        var info = [];
    
        if (body.result.length == 0) {
            status = 'No Incident found';
            poll_request.response_status = status + '\n\n' + JSON.stringify(body, null, 2);
            return;
        }
    
        body.result.forEach(function(inc) {
    
            // Set up the payload object
            var pl = {
                message: {
                    name: 'CreateIncidentInbound',
                    source_reference: inc.sys_id
                },
                detail: {
                    caller_id: inc.caller_id,
                    short_description: inc.short_description,
                    description: inc.description,
                    state: inc.state,
                    impact: inc.impact,
                    urgency: inc.urgency
                }
            };
    
            // Set up the options object for message submission
            var opts = {
                //message_name: 'CreateIncidentInbound',
                payload: JSON.stringify(pl)
            };
    
            poll_helper.processInbound(opts);
    
            var inc_time = inc.sys_updated_on;
            info.push('Incident : ' + inc.number + ' (' + inc_time + ')');
    
            // Set last update time (if later)
            var conn_time = conn.getData('last_update_time', "");
            info.push('Conn Time : ' + conn_time);
            if (inc_time > conn_time) {
                conn.setData('last_update_time', inc_time);
            }
    
        });
    
        poll_request.response_status = info.join('\n') + '\n\n' + JSON.stringify(body, null, 2);
    
    })(poll_request, poller, response, params);
    var poll_helper = new x_snd_eb.PollHelper(poll_request);
    poll_helper.processInbound(opts);
    current.assignment_group && String(current.assignment_group.u_unifi_integrations).indexOf(message.integration) != -1
    var answer = {};
    
    answer.getExternalMessageID = function (payload, request) {
      return '' + (payload.message.source_id || '');
    };
    
    answer.getInternalMessageID = function (payload, request) {
      return '' + (payload.message.target_id || '');
    };
    bond.setOpen();
    ws_console.execute('Business rule: Do something', function () {
     // run some code
     // errors will be caught and logged in the Activity Log and System Log
    });
    Message.processOutbound(current, {parent_tables: true});

    Describe what this field is for and any specific details that might help you in future.

    'The incident's comments'

    Describe what this field is for and any specific details that might help you in future.

    'The incident's work notes'

    Incident Field

    Field Map

    comments

    'IS String'*

    work_notes

    'IS String'*

    #

    Field

    Description

    Value

    3

    Element

    The field on the source/target table this Field record is mapped to.

    Additional comments

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    4

    #

    Field

    Description

    Value

    7

    Element

    The field on the source/target table this Field record is mapped to.

    'Work notes'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    8

    Description

    Description

    The direction(s) this message is configured to support.

    'Bidirectional'

    Async receipt

    The asynchronous receipt to this message.

    <lookup: 'CreateIncidentReceipt'>

    Bond new

    Process this message when a new bond is required.

    <true>

    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.

    Icons

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.comments [x_snd_eb_field.do?sys_id=dc2bf992db399010853c561bdc9619aa]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.comments = '' + (source.comments || default_value);
      } else if (source.comments != '') {
        $stage.comments = '' + source.comments;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=c8cc6ddedbb59010853c561bdc96195f]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.short_description = '' + (source.short_description || default_value);
      } else if (source.short_description != '') {
        $stage.short_description = '' + source.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.work_notes [x_snd_eb_field.do?sys_id=72e19adadb799010853c561bdc9619d8]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.work_notes = '' + (source.work_notes || default_value);
      } else if (source.work_notes != '') {
        $stage.work_notes = '' + source.work_notes;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.comments [x_snd_eb_field.do?sys_id=dc2bf992db399010853c561bdc9619aa]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.comments = '' + $stage.comments;
      } else if ($stage.comments) {
        $payload.comments = '' + $stage.comments;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=c8cc6ddedbb59010853c561bdc96195f]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.short_description = '' + $stage.short_description;
      } else if ($stage.short_description) {
        $payload.short_description = '' + $stage.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.work_notes [x_snd_eb_field.do?sys_id=72e19adadb799010853c561bdc9619d8]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.work_notes = '' + $stage.work_notes;
      } else if ($stage.work_notes) {
        $payload.work_notes = '' + $stage.work_notes;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    Before continuing we would again like to remind you of the relevant icons that are visible down the left hand navigation strip of the Unifi Integration Designer.

    The icons are:

    a) 'Integration' icon: Opens the current integration's Details page.

    b) 'Messages' icon: Opens the current integration's Messages page.

    c) 'Fields' icon: Opens the current integration's Fields page.

    d) 'Field Maps' icon: Opens the current integration's Field Maps page.

    e) 'Pollers' icon: Opens the current integration's Pollers page.

    f) 'Poll Processors' icon: Opens the current integration's Poll Processors page.

    New Poll Processor

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

    Click the 'Poll Processors' icon & then New.

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

    #

    Field

    Description

    Value

    1

    Name

    The name of the Processor.

    <Your Name>

    Your New Poll Processor modal should look like this:

    2) 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:

    #

    Field

    Description

    Value

    3

    Setup script

    The script to setup the Poll Request record.

    Update the code in the Setup script field so that it looks like the code below

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

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

    fields: The table API will return all the data by default, so we choose to deliberately limit what is returned to the fields listed in this variable.

    query: Instead of querying all the records on the remote instance, we deliberately limit the records to those where the correlation id is not empty (i.e. it's bonded), that haven't been updated by the Authentication user (our system) and that were updated since 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 variables in for the uri query and fields. 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.)

    params: The params object is passed through to the subsequent scripts (and on to further Pollers, if required).

    Your Setup Script form should look like this:

    4) 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:

    #

    Field

    Description

    Value

    5

    Request script

    The script that executes the request.

    Update the code in the Request script field so that it looks like the code below

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

    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:

    6) Navigate to Response Script.

    Response Script

    The Response Script is used to process the information returned from the remote system. We will pass this data to Unifi, telling it which Message to use to process the data.

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

    #

    Field

    Description

    Value

    7

    Response script

    The script that processes the response to the request.

    Update the code in the Response script field so that it looks like the code below

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

    Response script: This script parses the response into a body object to contain the result, (returning if it doesn't contain anything).

    It then sets up some objects to help us; these include the essential PollHelper() function (which we initialise from the poll_request) along with two other functions: get_bond() to find the Bond for an Incident & get_message_name() to work out the message type to send to Unifi based upon the change of state.

    After that it loops through each of the returned tickets. For each ticket, it logs the incident number & time, finds the bond & returns any previous data stored on the bond, decides which Message to use, sets up a payload object and submits it to Unifi by calling the processInbound() method. It then saves the current incident as the previous incident for the next poll & checks whether the ticket was updated later than the last update time; if so, it sets and stores the last update time as that 'sys_updated_on' value (this 'last_update_time' is what the Setup script checks against when defining what the Poll will do).

    After looping through all the records (processing each result), the results are logged to the Response status field of the Poll Request.

    Essential code: the following lines of code must be included in the response script to enable Unifi

    processInbound(): Having the 'poll_helper.processInbound()' function inside the loop means that an update message will be generated for each updated ticket.

    Payload object: We have chosen to structure the payload object (var payload) as we have. There is no obligation to keep the same structure. Yours can be defined to suit your requirements.

    Message name: Unifi needs to know the message name in order to know how to process the inbound request. We can either set it in the payload (as we have), or declare a variable that sets it which is passed into the processInbound() function along with the payload. (Unifi will always check processInbound() first. If no Message name is set here it will use the 'Identify message script' on the Integration).

    Your Response Script form should look like this:

    8) Save the Poll Processor.

    Now let's move on and configure the Poller.

    Edit CreateIncident Message

    Here we will deal with the configuration changes that need to be made to our CreateIncident Message to facilitate identifying and returning data from bonded records.

    CreateIncident Message

    Now that we've configured the remote system's Incident form to display our bonded ticket number as the correlation id, we need to update our CreateIncident Message to send it.

    To ensure that our CreateIncident Message is sending the relevant data we need to configure a new Field record that will send the Incident number as the correlation id. We will make use of the previously copied String Field Map record.

    Field: incident.number

    In Unifi Integration Designer, from the CreateIncident Message, navigate to Message > Fields. Click New.

    The fields to be configured for our incident.number New Field modal are as follows:

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.number' New Field modal should look like this:

    6) Submit the record.

    You will be redirected back to the Fields page of the CreateIncident Message.

    Field: incident.description

    It is not necessary to configure this Field record to facilitate identifying and returning data from bonded records. It is only included here to facilitate the sending of data in the Description field of the Incident when testing our Integration. You may choose to ignore this if you wish. Similarly, if you had already configured the incident.description Field record for the CreateIncident Message (when completing the 'Outbound incident' Guide), you can ignore this.

    The ‘incident.description’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we created the Message level record when configuring the Fields for the UpdateIncidentInbound Message. We will now create its Message level counterpart for the CreateIncident Message.

    From the CreateIncident Message, navigate to Message > Fields.

    Your CreateIncident Fields page should look like this:

    7) Find the incident.description (Integration level) Field & set Active to true.

    The empty circle icon next to the Field name turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field) when we set Active to true. (The ‘Build Integration’ button became visible in the banner when we created the 'incident.number' Field record.)

    By setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart.

    8) Click to open the incident.description (Message level) Field to make a few minor changes.

    The incident.description Field record opens to the Details page.

    9) Navigate to Field > Settings.

    Edit the incident.description Field record as follows:

    Your 'incident.description' Field record should look like this:

    13) Save the record.

    Build

    Now that we’ve configured the Field records for the CreateIncident message, we are ready to build our message scripts.

    To quickly navigate to the CreateIncident Message from the Details page of the newly created incident.description Field record...

    ...click the 'Preview' icon to the left of the Message field.

    The following Field records should now be in place for your CreateIncident Message:

    14) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    15) Navigate to Advanced > Script Editor > View > Outbound to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The new auto-generated code (mapping the incident number to the correlation id & mapping the Incident description) will appear between the Begin & End Comment along with the code that was already there (which we had previously created using the Outbound Incident Guide). Your code may differ, depending on which Field records you created to satisfy your mapping requirements.

    Source to Stage:

    Stage to Request:

    We have now completed the configuration and are ready to move on to Test our Update Scenario.

    // Configure the new Poll Request record
    (function(poll_request, poller, params) {
    
        var gdt = new GlideDateTime();
        gdt.addSeconds(-1800);
    
        var connection = poller.getIntegration().getActiveConnection();
        var user = connection.getBasicAuthUser();
        var time = connection.getData('last_update_time', (gdt + ''));
    
        var fields = 'sys_id,number,correlation_id,short_description,description,state,close_code,close_notes,sys_updated_on,sys_updated_by';
    
        var query = [
            'correlation_idISNOTEMPTY',
            'sys_updated_by!=' + user,
            'sys_updated_on>' + time
        ];
    
        var uri_query = query.map(function(c) {
            return encodeURIComponent(c);
        }).join('%5E');
    
        poll_request.endpoint_url += '?sysparm_query=' + uri_query +
            '&sysparm_fields=' + encodeURIComponent(fields) + '&sysparm_limit=10';
    
    })(poll_request, poller, params);
    // 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);
    // 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) {
    
        var body = JSON.parse(response);
    
        // Nothing to do if no results were returned
        if ( body.result.length == 0 ) {
            poll_request.response_status = 'No Incidents returned\n\n' + JSON.stringify(body,null,2);
            return;
        }
    
        // Sample result
    /*
    {
      "result": [
        {
          "sys_id": "0ecc4865db734010c3ebde82ca961960",
          "number": "INC0010107",
          "correlation_id": "INC0010345",
          "short_description": "Demo two - Fixing request",
          "description": "A long description",
          "state":"2",
          "sys_updated_on": "2020-04-02 14:00:00",
          "sys_updated_by": "a.user"
        },
        {
          ... next Incident
        }
      ]
    }    
    */
    
        // Establish the environment
        var integration = poller.getIntegration();
        var config = integration.getConfig();
        var conn   = integration.getActiveConnection();
        var cvars  = conn.getVariables();
    
        var poll_helper = new x_snd_eb.PollHelper(poll_request);
        var info = [];
    
        // Use Unifi code to find the Bond for an Incident
        function get_bond(inc) {
            var bond = new x_snd_eb.Bond(config);
            bond.locateReference(integration,inc.correlation_id,inc.sys_id);
            if ( !bond.isValidRecord() ) { return null; }
            return bond; 
        }
    
        // Work out the message type to send to Unifi based upon the change of state
        function get_message_name(curr,prev) {
    
            // Default message type is an update
            var message_name = 'UpdateIncidentInbound';
    
            // Use the default type if we have no previous state
            if ( !prev || !prev.state ) { 
                return message_name; 
            }
    
            // Use the default type if there is no change in state
            if ( curr.state == prev.state ) { 
                return message_name; 
            }
    
            // We know the state has changed, check if it is Resolved (6)
            if ( curr.state == '6' ) {
                message_name = 'ResolveIncidentInbound';
            }
    
            return message_name;
        }
    
        function process_incident(inc) {
    
            // Log the incident number and time
            var inc_time = inc.sys_updated_on;
            info.push('Incident : ' + inc.number + ' (' + inc_time + ')');
    
            // Find the bond on which the previous data is stored
            var bond = get_bond(inc);
    
            // If no bond was found, ignore this incident
            if ( !bond ) {
                info.push('- Bond not found - Incident ignored');
                return;
            }
    
            // Get the data stored for the incident by a previous poll
            var previous_inc = bond.getDataObject('previous_inc',{ state : '2' });
    
            // Work out the message type to send into Unifi 
            var message_name = get_message_name(inc,previous_inc);
            info.push('- Message name: ' + message_name);
    
            // Set up the payload object for passing into Unifi
            var payload = {
                message : {
                    name: message_name,
                    source_reference: inc.sys_id,
                },
                detail : {
                    short_description : inc.short_description,
                    description : inc.description,
                    state : inc.state,
                    close_code : inc.close_code,
                    close_notes : inc.close_notes
                }
            };
    
            // Submit the message into Unifi
            poll_helper.processInbound({
                payload : JSON.stringify(payload)
            });
    
            // Save the current incident as the previous incident for the next poll
            bond.setDataObject('previous_inc',inc);
    
            // Update last update time (if later)
            var conn_time = conn.getData('last_update_time');
            if ( inc_time > conn_time ) {
                conn.setData('last_update_time',inc_time);
            }
    
        }
    
        // Process each result
        body.result.forEach(function(inc){
            process_incident(inc);
        });
    
        poll_request.response_status = info.join('\n') + '\n\n' + JSON.stringify(body,null,2);
    
    })(poll_request, poller, response, params);

    Set to true to use this Field record for processing.

    <true>

    2

    Field map

    The Field Map this Field record is linked with.

    'IS - String'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    3

    Element

    The field on the source/target table this Field record is mapped to.

    'Number'

    4*

    Property

    The property in the payload the data will be written to.

    'correlation_id'

    5*

    Inbound

    Set to true to use for inbound Messages.

    <false>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    Set to true to use for outbound Messages.

    <true>

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncident'

    1

    Description

    The description of this Field record.

    'The incident number sent as the correlation id'

    *

    #

    Field

    Description

    Value

    10

    Path

    Where in the payload the data will be placed.

    [Blank]

    11

    Inbound

    Set to true to use for inbound Messages.

    <false>

    12

    Active

    Outbound

    UpdateIncidentInbound Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the UpdateIncidentInbound Message.

    Copy Field Maps

    It is worth copying all relevant OOTB Field Maps as are necessary for your integration before using any of them in your Field Records - thereby mitigating the risk of any potential issues with future upgrades.

    Some Field Maps should already have been copied for this Integration whilst following the Outbound Incident Guide. Those that aren't will need to be copied. The Field Maps we shall use for our UpdateIncidentInbound Field records are:

    • Message Header

    • String

    To copy the Message Header Field Map, navigate to the 'Field Maps' icon.

    1) Click on the ellipsis to the right of the Message Header Field Map & then click Copy.

    Copy Field Map Modal

    The fields to edit for the Copy Field Map modal are as follows:

    *Name: We have chosen to prefix the existing Field Map Name with the initials of our Integration (you are free to choose any appropriate means of identifying/differentiating).

    Your Copy Field Map modal should look like this:

    3) Click Copy.

    You will be redirected to the Details page of the newly created Field Map.

    If necessary, repeat the process for the String Field Map.

    Field records can represent the handling of two categories of data: either a data object which carries transaction specific data (e.g. name, time stamp, source id etc.), or a field element on the bonded record (e.g. Short description). We will begin by configuring a Field record to deal with the transaction specific data.

    Field: message.header

    Back in the UpdateIncidentInbound Message, navigate to Message > Fields. Click New.

    The fields to be configured for our message_header New Field modal are as follows:

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'message.header' New Field modal should look like this:

    10) Submit the record.

    You will be redirected back to the Fields page of the UpdateIncidentInbound Message.

    Fields & Field Maps

    Depending on your requirements, you will need to create Field records for each of the relevant Incident record field elements you wish to map. As we have only chosen to include the short_description & description elements in both the Setup script & Response script of the Poll Processor, this Guide will focus on those two. If you wish, however, you are free to configure other Field records as required (ensuring you also define them in both the Setup Script & Response script of the Poll Processor).

    For a full description of the available Field Maps, please see the relevant page in our .

    The table below lists the Incident record field elements we will map and the relevant Field Maps required to configure each Field record.

    *Field map: Values may vary (dependent on your configuration of the copies). Choose the copy Field Maps you created earlier.

    Field: incident.short_description

    The ‘incident.short_description’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we first created the Message level record when completing the Outbound Incident Guide. We will now create its Message level counterpart.

    From the UpdateIncidentInbound Message, navigate to Message > Fields.

    Your UpdateIncidentInbound Fields page should look like this:

    11) Find the incident.short_description (Integration level) Field & set Active to true.

    The empty circle icon next to the Field name turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field) when we set Active to true. (The ‘Build Integration’ button became visible in the banner when we created the 'message.header' Field).

    By setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart.

    12) Click to open the incident.short_description (Message level) Field to make a few minor changes.

    The incident.short_description Field record opens to the Details page.

    13) Navigate to Field > Settings.

    Edit the incident.short_description Field record as follows:

    Your incident.short_description Field record should look like this:

    17) Save the record.

    Field: incident.description

    Because the incident.description Field record is the same ‘type’ (IS - String) & the majority of the settings are the same as the previously configured Field, it will be quicker to copy the incident.short_description Field & make a few minor changes.

    To quickly navigate to the UpdateincidentInbound Message from the Details page of the incident.short_description Field record...

    ...click the 'Preview' icon to the left of the Message field.

    From the UpdateIncidentInbound Message, navigate to Message > Fields.

    18) Click the ellipsis next to the incident.short_desscription Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    *This field is automatically populated.

    Your 'incident.description' Copy Field modal should look like this:

    21) Click Copy.

    You will be redirected to the Details page of the newly created incident.description Field record.

    Build

    Now that we’ve configured the Field records for the UpdateIncidentInbound message, we are ready to build our message scripts.

    To quickly navigate to the UpdateIncidentInbound message from the Details page of the newly created incident.description Field record…

    ...click the 'Preview' icon to the left of the Message field.

    The following Field records should now be in place for your UpdateIncidentInbound messsage:

    22) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    23) Navigate to Advanced > Script Editor > View > Inbound to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The Message Scripts reflect the mappings as per this Guide. Your scripts might differ depending on which Fields you chose to map (& defined in the payload). We will look at the Message Scripts in turn.

    Payload to Stage:

    Your Payload to Stage Message Script should look like this:

    Stage to Target:

    Your Stage to Target Message Script should look like this:

    Before we test, we need to make a few changes. The first is to our Integration - to allow for inbound Message Identification.

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=f23b349edb359010853c561bdc961989]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.caller_id = '' + (source.caller_id || default_value);
      } else if (source.caller_id != '') {
        $stage.caller_id = '' + source.caller_id;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=009447071b0214105830db9ebd4bcb22]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.description = '' + (source.description || default_value);
      } else if (source.description != '') {
        $stage.description = '' + source.description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.number [x_snd_eb_field.do?sys_id=e75407071b0214105830db9ebd4bcbf7]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.number = '' + (source.number || default_value);
      } else if (source.number != '') {
        $stage.number = '' + source.number;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=548efc12db759010853c561bdc961918]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.short_description = '' + (source.short_description || default_value);
      } else if (source.short_description != '') {
        $stage.short_description = '' + source.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=b5e1c9d2db759010853c561bdc961929]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var field_choice;
      var is_mandatory = false;  
    
      if (!source.state.nil()) {
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',         '=', 'incident');
        field_choice.addQuery('element',       '=', 'state');
        field_choice.addQuery('integration',   '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message', '=', '');
        field_choice.addQuery('direction',     '=', 'Outbound');
        field_choice.addQuery('value',         '=', source.state);
        field_choice.addQuery('active',        '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          $stage.state = '' + field_choice.external_value;
        }
      } 
    
      if (!$stage.state) {
        $stage.state = '' + (source.state || '');
      }
    
      if (is_mandatory) {
        $stage.state = '' + (source.state || '');
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=f23b349edb359010853c561bdc961989]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.caller_id = '' + $stage.caller_id;
      } else if ($stage.caller_id) {
        $payload.caller_id = '' + $stage.caller_id;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=009447071b0214105830db9ebd4bcb22]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.description = '' + $stage.description;
      } else if ($stage.description) {
        $payload.description = '' + $stage.description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.number [x_snd_eb_field.do?sys_id=e75407071b0214105830db9ebd4bcbf7]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.correlation_id = '' + $stage.number;
      } else if ($stage.number) {
        $payload.correlation_id = '' + $stage.number;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=548efc12db759010853c561bdc961918]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.short_description = '' + $stage.short_description;
      } else if ($stage.short_description) {
        $payload.short_description = '' + $stage.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=b5e1c9d2db759010853c561bdc961929]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      var $payload = payload;
    
      var is_mandatory = false;  
    
      if (is_mandatory) {
        $payload.state = $stage.state;
      } else if ($stage.state) {
        $payload.state = $stage.state;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    var poll_helper = new x_snd_eb.PollHelper(poll_request);
    poll_helper.processInbound({
                payload : JSON.stringify(payload)
            });

    Set to true to use this Field record for processing.

    <true>

    5

    Field map

    The Field Map this Field record is linked with.

    'IS - Message Header'**

    6*

    Map to field

    Use this Field record to represent a field on a source/target table.

    <false>

    7

    Path

    Where in the payload the data will be placed.

    'message'

    8

    Property

    The property in the payload the data will be written to.

    'header'

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    9*

    Outbound

    Set to true to use for outbound Messages.

    <false>

    Set to true to use for outbound Messages.

    <false>

    Describe what this field is for and any specific details that might help you in future.

    'The incident's description'

    #

    Field

    Description

    Value

    2

    Name*

    The name of your field map. (If left unedited, it will append the word 'Copy' to the existing name.)

    <Your Name>

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'UpdateIncidentInbound'

    4

    Description

    Describe what this field is for and any specific details that might help you in future.

    ‘The protocol message header’

    *

    Incident Field

    Field Map

    short_description

    'IS - String'*

    description

    'IS - String'*

    #

    Field

    Description

    Value

    14

    Path

    Where in the payload the data will be placed.

    ‘detail’

    15

    Inbound

    Set to true to use for inbound Messages.

    <true>

    16

    #

    Field

    Description

    Value

    19

    Element

    The field on the source/target table this Field record is mapped to.

    'Description'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    20

    technical documentation

    Active

    Outbound

    Description

    ResolveIncident Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the ResolveIncident Message.

    The 'incident.comments', 'incident.work_notes' and 'incident.short_description' Field records are already in place because they were also copied when we copied the Message. We can choose to include, or exclude as many of those and the Integration level ones that are available depending on our requirements (by either activating or deactivating the relevant Fields). We will choose to keep the existing Message level Fields and add the available incident.state (Integration level) Field.

    Field: incident.state (Message level)

    By simply setting the Active flag to true on the Integration level Field record listed on the Message, Unifi will automatically create the Message level counterpart.

    Navigate to Message > Fields.

    Your ResolveIncident Message Fields page should look like this:

    1) Find the incident.state (Integration level) Field & set Active to true.

    The empty circle icon next to the Field name turns green & contains a green 'check' (to indicate that Message level configuration exists for this Field).

    We will now configure Field records for the two remaining Incident record field elements which are required.

    Fields & Field Maps

    The table below lists the Incident record field elements we will map and the relevant Field Maps required to configure each Field record.

    *Field map: Values may vary (dependent on your configuration of the copies). Choose the copy Field Maps you created earlier.

    Field: incident.close_code (Message level)

    There is no need to 'Generate field choices' for Message level Field records because the Field Map always looks for them on an Integration level Field which has the same name.

    As with 'incident.state' the 'incident.close_code' Field record is a Choice 'type' Field. We will, therefore, configure the choices once at the Integration level. We'll first configure the Message level Field and then move on to configure the choices on its Integration level counterpart.

    From the Fields page, click New.

    The fields to be configured for our incident.close_code (Message level) New Field modal are as follows:

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.close_code' (Message level) New Field modal should look like this:

    7) Submit the record.

    You will be redirected back to the Fields page of the ResolveIncident Message.

    Field: incident.close_code (Integration level)

    We will need to 'Generate field choices' for this Integration level Choice 'type' Field.

    Navigate to the 'Fields' icon to open the Fields page.

    8) Click to open the incident.close_code (Integration level) Field record (the one where Message is empty).

    The incident.close_code Field record opens to the Details page.

    9) Navigate to Field > Field Choices.

    10) Click Generate field choices.

    11) Click Generate on the 'Generate field choices' modal which displays.

    The Field Choices are generated & now visible in the list.

    Field: incident.close_notes

    Because the incident.close_notes Field record is the same 'type' (IS - String) & the majority of the settings are the same as the incident.work_notes Field, it will be quicker to copy that Field & make a few minor changes.

    From the ResolveIncident Message, navigate to Message > Fields.

    12) Click the ellipsis next to the incident.work_notes Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    *This field is automatically populated.

    Your 'incident.close_notes' Copy Field modal should look like this:

    15) Click Copy.

    You will be redirected to the Details page of the newly created incident.close_notes Field record.

    Navigate to Field > Settings.

    16) Set Mandatory to true.

    17) Click Save.

    Build

    Now that we’ve configured the Field records for the ResolveIncident message, we are ready to build our message scripts.

    Navigate to the ResolveIncident message, then navigate to Message > Fields.

    The following Field records should now be in place for your ResolveIncident messsage:

    18) Click on Build.

    You will see the 'Message build successful' Info Message.

    19) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    We will now examine our new, auto-generated Message Scripts.

    Source to Stage:

    Stage to Request:

    We are now ready to Test the ResolveIncident Message.

    ResolveIncidentInbound Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the ResolveIncidentInbound Message.

    Field records can represent the handling of two categories of data: either a data object which carries transaction specific data (e.g. name, time stamp, source id etc.), or a field element on the bonded record (e.g. Short description).

    The 'message.header', 'incident.description' and 'incident.short_description' Field records are already be in place because they were also copied when we copied the Message. We will now configure Field records for the remaining field elements we have chosen to map.

    Fields & Field Maps

    Depending on your requirements, you will need to create Field records for each of the relevant Incident record field elements you wish to map. As we have chosen to include the state

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=ca8a9a761b42d0105830db9ebd4bcbe9]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $payload.description == undefined) {
        throw 'Mandatory field description was not provided';
      } else {
        $stage.description = $payload.description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=6098f5761bce90105830db9ebd4bcb11]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $payload.short_description == undefined) {
        throw 'Mandatory field short_description was not provided';
      } else {
        $stage.short_description = $payload.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping message.header [x_snd_eb_field.do?sys_id=d0cdedba1b8e90105830db9ebd4bcb42]", function () {
      log.debug("Field map: IS - Message Header [x_snd_eb_field_map.do?sys_id=9e0d1d7a1b4e90105830db9ebd4bcb5f]");
      payload = payload || {};
      payload.message = payload.message || {};
      var $payload = payload.message;
    
      // Messge identifiers
      $stage.$message_name = $payload.name;
      $stage.$time_stamp   = $payload.time_stamp;
    
      // Task references
      stage.internal_reference = $payload.target_reference || '';
      stage.external_reference = $payload.source_reference || '';
    
      // Transaction identifiers
      transaction.external_message_id = $payload.source_id || '';
    
    
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=ca8a9a761b42d0105830db9ebd4bcbe9]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.description == '') {
        throw 'Mandatory field description was not provided';
      } else {
        target.description = '' + ($stage.description || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=6098f5761bce90105830db9ebd4bcb11]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.short_description == '') {
        throw 'Mandatory field short_description was not provided';
      } else {
        target.short_description = '' + ($stage.short_description || default_value);
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//

    Set to true to use this Field record for processing.

    <true>

    3

    Field map

    The Field Map this Field record is linked with.

    'IS Choice'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    4

    Element

    The field on the source/target table this Field record is mapped to.

    'Resolution code'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    5*

    Inbound

    Set to true to use for inbound Messages.

    <false>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    6

    Mandatory

    Set to true to make mandatory.

    <true>

    The description of this Field record.

    'The incident's Resolution notes (Close notes in ServiceNow)'

    Incident Field

    Field Map

    close_code

    'IS Choice'*

    close_notes

    'IS String'*

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'ResolveIncident'

    2

    Description

    The description of this Field record.

    'The incident's Resolution code (Close code in ServiceNow)'

    *

    #

    Field

    Description

    Value

    13

    Element

    The field on the source/target table this Field record is mapped to.

    'Resolution notes'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    14

    Active

    Description

    ,
    close_notes
    &
    close_code
    elements in both the Setup script & Response script of the Poll Processor, this Guide will focus on those three only. If you wish, however, you are free to configure other Field records as required (ensuring you also define them in both the Setup Script & Response script of the Poll Processor).

    For a full description of the available Field Maps, please see the relevant page in our technical documentation.

    The table below lists the Incident record field elements we will map and the relevant Field Maps required to configure each Field record.

    Incident Field

    Field Map

    state

    'IS - Choice'*

    close_notes

    'IS - String'*

    close_code

    'IS - Choice'*

    *Field map: Values may vary (dependent on your configuration of the copies). Choose the copy Field Maps you created earlier.

    Field: incident.state (Message level)

    Unifi created the incident.state (Integration level) Field when we first created the Message level record whilst following the Outbound Incident Guide. It is, therefore, displayed in the Fields list on the ResolveIncidentInbound Message with Active set to false.

    From the ResolveIncidentInbound Message, navigate to Message > Fields.

    Your ResolveIncident Message Fields page should look like this:

    1) Find the incident.state (Integration level) Field & set Active to true.

    The empty circle icon next to the Field name turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field) when we set Active to true. (The ‘Build Integration’ button became visible in the banner when we copied the UpdateIncidentInbound Message).

    By simply setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has created the Message level counterpart.

    2) Click to open the newly created incident.state (Message level) Field record for further editing.

    The incident.state Field record opens to the Details page.

    3) Navigate to Field > Settings.

    The fields to be changed to configure the incident.state (Message level) Field record are as follows:

    #

    Field

    Description

    Value

    4

    Path

    Where in the payload the data will be placed.

    'detail'

    5

    Inbound

    Set to true to use for inbound Messages.

    <true>

    6

    Your incident.state (Message level) Settings form should look like this:

    7) Save the record.

    Field: incident.close_notes

    As with incident.state, Unifi created the incident.close_notes (Integration level) Field when we first created the Message level record whilst following the Outbound Incident Guide. We will now create the Message level counterpart for the ResolveIncidentInbound Message.

    To quickly navigate to the ResolveIncidentInbound Message from the Details page of the incident.state Field record...

    ...click the ‘Preview’ icon to the left of the Message field.

    From the ResolveIncidentInbound Message, navigate to Message > Fields.

    8) Find the incident.close_notes (Integration level) Field & set Active to true.

    9) Click to open the newly created incident.close_notes (Message level) Field record for further editing.

    The incident.close_notes Field record opens to the Details page.

    10) Navigate to Field > Settings.

    The fields to be changed to configure the incident.close_notes (Message level) Field record are as follows:

    #

    Field

    Description

    Value

    11

    Path

    Where in the payload the data will be placed.

    'detail'

    12

    Inbound

    Set to true to use for inbound Messages.

    <true>

    13

    Your 'incident.close_notes' (Message level) Settings form should look like this:

    15) Save the record.

    Field: incident.close_code

    Again, Unifi created the incident.close_code (Integration level) Field when we first created the Message level record whilst following the Outbound Incident Guide. We will also create the Message level counterpart for the ResolveIncidentInbound Message.

    As with 'incident.state' the 'incident.close_code' Field record is a Choice 'type' Field. We have already configured the choices at the Integration level, so there's no need to 'Generate field choices' for this Message level record because the Field Map always looks for them on an Integration level Field which has the same name.

    From the ResolveIncidentInbound Message, navigate to Message > Fields.

    16) Find the incident.close_code (Integration level) Field & set Active to true.

    17) Click to open the newly created incident.close_code (Message level) Field record for further editing.

    The incident.close_code Field record opens to the Details page.

    18) Navigate to Field > Settings.

    The fields to be changed to configure the incident.close_code (Integration level) Field record are as follows:

    #

    Field

    Description

    Value

    19

    Path

    Where in the payload the data will be placed.

    'detail'

    20

    Inbound

    Set to true to use for inbound Messages.

    <true>

    21

    Your ‘incident.close_code’ (Message level) Field record should look like this:

    23) Save the record.

    Build

    Now that we’ve configured the Field records for the ResolveIncidentInbound message, we are ready to build our message scripts.

    From the ResolveIncidentInbound message., navigate to Message > Fields.

    The following Field records should now be in place for your ResolveIncidentInbound messsage:

    24) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    25) Navigate to Advanced > Script Editor > View > Inbound to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The Message Scripts reflect the mappings as per this Guide. Your scripts might differ depending on which Fields you chose to map (& defined in the payload). We will look at the Message Scripts in turn.

    Payload to Stage:

    Your Payload to Stage Message Script should look like this:

    Stage to Target:

    Your Stage to Target Message Script should look like this:

    Because we have already made a few changes to allow for inbound Message & Bond Identification in our earlier 'Incident Update Poller' Guide, we can now move on to Testing.

    CreateIncident Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the CreateIncident Message.

    Fields & Field Maps

    Depending on your requirements, you will need to create Field records for each of the relevant Incident record field elements (see the table below for an example). For the sake of brevity, this Guide will focus on a select few. If you wish, however, you are free to continue & configure the remaining Field records. The table below lists an example of the Incident record field elements you may wish to map and the relevant Field Maps required to configure each Field record. For a fuller definition of available Field Maps, please see the relevant page in our .

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.close_code [x_snd_eb_field.do?sys_id=02a6db6adbf9d01094dbd7795e961979]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var field_choice;
      var is_mandatory = true;  
    
      if (!source.close_code.nil()) {
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',         '=', 'incident');
        field_choice.addQuery('element',       '=', 'close_code');
        field_choice.addQuery('integration',   '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message', '=', '');
        field_choice.addQuery('direction',     '=', 'Outbound');
        field_choice.addQuery('value',         '=', source.close_code);
        field_choice.addQuery('active',        '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          $stage.close_code = '' + field_choice.external_value;
        }
      } 
    
      if (!$stage.close_code) {
        $stage.close_code = '' + (source.close_code || '');
      }
    
      if (is_mandatory) {
        $stage.close_code = '' + (source.close_code || '');
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.close_notes [x_snd_eb_field.do?sys_id=b613ef62db3dd01094dbd7795e9619b7]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = true;
    
      if (is_mandatory) {
        $stage.close_notes = '' + (source.close_notes || default_value);
      } else if (source.close_notes != '') {
        $stage.close_notes = '' + source.close_notes;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.comments [x_snd_eb_field.do?sys_id=658c5a16dbb99010853c561bdc961975]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.comments = '' + (source.comments || default_value);
      } else if (source.comments != '') {
        $stage.comments = '' + source.comments;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=298c5a16dbb99010853c561bdc961973]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.short_description = '' + (source.short_description || default_value);
      } else if (source.short_description != '') {
        $stage.short_description = '' + source.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=5c69baeedb79d01094dbd7795e961952]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var field_choice;
      var is_mandatory = false;  
    
      if (!source.state.nil()) {
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',         '=', 'incident');
        field_choice.addQuery('element',       '=', 'state');
        field_choice.addQuery('integration',   '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message', '=', '');
        field_choice.addQuery('direction',     '=', 'Outbound');
        field_choice.addQuery('value',         '=', source.state);
        field_choice.addQuery('active',        '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          $stage.state = '' + field_choice.external_value;
        }
      } 
    
      if (!$stage.state) {
        $stage.state = '' + (source.state || '');
      }
    
      if (is_mandatory) {
        $stage.state = '' + (source.state || '');
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.work_notes [x_snd_eb_field.do?sys_id=e18c5a16dbb99010853c561bdc961971]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.work_notes = '' + (source.work_notes || default_value);
      } else if (source.work_notes != '') {
        $stage.work_notes = '' + source.work_notes;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.close_code [x_snd_eb_field.do?sys_id=02a6db6adbf9d01094dbd7795e961979]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      var $payload = payload;
    
      var is_mandatory = true;  
    
      if (is_mandatory) {
        $payload.close_code = $stage.close_code;
      } else if ($stage.close_code) {
        $payload.close_code = $stage.close_code;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.close_notes [x_snd_eb_field.do?sys_id=b613ef62db3dd01094dbd7795e9619b7]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = true;
    
      if (is_mandatory) {
        $payload.close_notes = '' + $stage.close_notes;
      } else if ($stage.close_notes) {
        $payload.close_notes = '' + $stage.close_notes;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.comments [x_snd_eb_field.do?sys_id=658c5a16dbb99010853c561bdc961975]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.comments = '' + $stage.comments;
      } else if ($stage.comments) {
        $payload.comments = '' + $stage.comments;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=298c5a16dbb99010853c561bdc961973]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.short_description = '' + $stage.short_description;
      } else if ($stage.short_description) {
        $payload.short_description = '' + $stage.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=5c69baeedb79d01094dbd7795e961952]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      var $payload = payload;
    
      var is_mandatory = false;  
    
      if (is_mandatory) {
        $payload.state = $stage.state;
      } else if ($stage.state) {
        $payload.state = $stage.state;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.work_notes [x_snd_eb_field.do?sys_id=e18c5a16dbb99010853c561bdc961971]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.work_notes = '' + $stage.work_notes;
      } else if ($stage.work_notes) {
        $payload.work_notes = '' + $stage.work_notes;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.close_code [x_snd_eb_field.do?sys_id=35018df71bce54105830db9ebd4bcb46]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      var is_mandatory = true;  
    
      if (is_mandatory && $payload.close_code == undefined) {
        throw 'Mandatory field close_code was not provided';
      } else {
        $stage.close_code = $payload.close_code;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.close_notes [x_snd_eb_field.do?sys_id=e258f76f1bca54105830db9ebd4bcb57]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = true;
    
      if (is_mandatory && $payload.close_notes == undefined) {
        throw 'Mandatory field close_notes was not provided';
      } else {
        $stage.close_notes = $payload.close_notes;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=3838d96fdb0a5410e1cb45e813961978]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $payload.description == undefined) {
        throw 'Mandatory field description was not provided';
      } else {
        $stage.description = $payload.description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=3438d96fdb0a5410e1cb45e813961972]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $payload.short_description == undefined) {
        throw 'Mandatory field short_description was not provided';
      } else {
        $stage.short_description = $payload.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=7057a927db4a5410e1cb45e8139619c6]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      var is_mandatory = false;  
    
      if (is_mandatory && $payload.state == undefined) {
        throw 'Mandatory field state was not provided';
      } else {
        $stage.state = $payload.state;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping message.header [x_snd_eb_field.do?sys_id=b838d96fdb0a5410e1cb45e813961976]", function () {
      log.debug("Field map: IS - Message Header [x_snd_eb_field_map.do?sys_id=9e0d1d7a1b4e90105830db9ebd4bcb5f]");
      payload = payload || {};
      payload.message = payload.message || {};
      var $payload = payload.message;
    
      // Messge identifiers
      $stage.$message_name = $payload.name;
      $stage.$time_stamp   = $payload.time_stamp;
    
      // Task references
      stage.internal_reference = $payload.target_reference || '';
      stage.external_reference = $payload.source_reference || '';
    
      // Transaction identifiers
      transaction.external_message_id = $payload.source_id || '';
    
    
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.close_code [x_snd_eb_field.do?sys_id=35018df71bce54105830db9ebd4bcb46]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var is_mandatory = true;  
    
      if (is_mandatory && $stage.close_code == undefined) {
        throw 'Mandatory field close_code was not provided';
      } else {
        var field_choice;
    
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',          '=', 'incident');
        field_choice.addQuery('element',        '=', 'close_code');
        field_choice.addQuery('integration',    '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message',  '=', '');
        field_choice.addQuery('direction',      '=', 'Inbound');
        field_choice.addQuery('external_value', '=', $stage.close_code);
        field_choice.addQuery('active',         '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          target.close_code = field_choice.value;
        } else {
          target.close_code = $stage.close_code;
        }
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.close_notes [x_snd_eb_field.do?sys_id=e258f76f1bca54105830db9ebd4bcb57]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = true;
    
      if (is_mandatory && $stage.close_notes == '') {
        throw 'Mandatory field close_notes was not provided';
      } else {
        target.close_notes = '' + ($stage.close_notes || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=3838d96fdb0a5410e1cb45e813961978]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.description == '') {
        throw 'Mandatory field description was not provided';
      } else {
        target.description = '' + ($stage.description || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=3438d96fdb0a5410e1cb45e813961972]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.short_description == '') {
        throw 'Mandatory field short_description was not provided';
      } else {
        target.short_description = '' + ($stage.short_description || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=7057a927db4a5410e1cb45e8139619c6]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var is_mandatory = false;  
    
      if (is_mandatory && $stage.state == undefined) {
        throw 'Mandatory field state was not provided';
      } else {
        var field_choice;
    
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',          '=', 'incident');
        field_choice.addQuery('element',        '=', 'state');
        field_choice.addQuery('integration',    '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message',  '=', '');
        field_choice.addQuery('direction',      '=', 'Inbound');
        field_choice.addQuery('external_value', '=', $stage.state);
        field_choice.addQuery('active',         '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          target.state = field_choice.value;
        } else {
          target.state = $stage.state;
        }
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//

    Field Map

    caller_id*

    String

    short_description

    String

    description

    String

    category

    Choice

    impact

    Choice

    urgency

    Choice

    state

    Choice

    comments

    String

    worknotes

    String

    *caller_id: we have chosen String type here because we are integrating with the table API. This will return the sys id of the caller as a string value. Note: If we were integrating Unifi to Unifi we may use a Reference type which would return the caller as an object with "value", "link" & "display_value" elements.

    The Field records we will focus on will be for Caller (String), Short description (String) and State (Choice).

    Copy Field Maps

    If you haven't already, you will need to copy the relevant additional Field Maps for the CreateIncident Field records as follows:

    • String

    • Choice

    See Copy Field Maps (on the 'CreateIncidentResponse Fields' page) for details.

    Field: incident.caller_id

    In Unifi Integration Designer, from the CreateIncident page, navigate to Message > Fields. Click New.

    The fields to be configured for the 'incident.caller_id' New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncident'

    1

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The caller on this incident'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.caller_id' New Field modal should look like this:

    5) Submit the record.

    You will be redirected back to the Fields page of the CreateIncident Message.

    Field: incident.short_description

    Because the incident.short_description Field record is the same 'type' (IS - String) & the majority of the settings are the same as the previously configured Field, it will be quicker to copy the incident.caller_id Field & make a few minor changes.

    Feature Alert: The 'result.sys_id' Field is visible and inactive. It is an integration level Field which was automatically created by Unifi at the time we created the Message level record (in CreateIncidentResponse Fields). We'll talk in more detail about this feature in the following section.

    6) Click the ellipsis next to the incident.caller_id Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    #

    Field

    Description

    Value

    7

    Element

    The field on the source/target table this Field record is mapped to.

    'Short description'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    8

    Your Copy Field modal should look like this:

    9) Click Copy.

    You will be redirected to the Details page of the newly created incident.short_description Field record.

    Field: incident.state

    Field records can exist at both the Integration and the Message level (a Field record exists at the Integration level if it isn't linked to a Message i.e. the 'Message' field element is left blank). We noted previously that an Integration level Field record is automatically created when we create one at the Message level. We will utilise and configure both when mapping 'incident.state'.

    The 'incident.state' Field record is a Choice 'type' Field. These are used when you’re mapping choice field elements with static values that don't change per Message (e.g. State, Impact, Urgency) i.e. you're not going to have one set of choices/values for create and another for update.

    Rather than configure choices for each Message, configure choices once at the Integration level. This means we only need define them once. The Field Map will take care of it and any 'incident.state' Field records that are set at the Message level (i.e. with a value in the 'Message' field) would use the choices configured at the Integration level.

    We'll first configure the Message level Field and then move on to configure the choices on its Integration level counterpart.

    Field: incident.state (Message level)

    There is no need to 'Generate field choices' for Message level Field records because the Field Map always looks for them on an Integration level Field which has the same name.

    To quickly navigate to the CreateIncident Message from the Details page of the newly created incident.short_description Field record...

    ...click the 'Preview' icon to the left of the Message field.

    From the CreatIncident Message, navigate to Message > Fields. Click New.

    The fields to be configured for our 'incident.state' (Message level) New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncident'

    10

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The incident lifecycle state'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.state' (Message level) New Field modal should look like this:

    14) Submit the record.

    You will be redirected back to the Fields page of the CreateIncident Message.

    Field: incident.state (Integration level)

    We will need to 'Generate field choices' for this Integration level Choice 'type' Field.

    Navigate to the 'Fields' icon to open the Fields page.

    15) Click to open the incident.state (Integration level) Field record (the one where Message is empty).

    The incident.state Field record opens to the Details page.

    16) Navigate to Field > Field Choices.

    17) Click Generate field choices.

    18) Click Generate on the 'Generate field choices' modal which displays.

    The Field Choices are generated & now visible in the list.

    At this stage, you could carry on and configure the remaining Field records for the rest of the Incident fields (as per the table at the top of this section). However, we will now run the Build process to auto-generate our Message Scripts.

    Build

    Now that we’ve configured the Field records for the CreateIncident message, we are ready to build our message scripts.

    From the CreateIncident Message, navigate to Message > Fields.

    The following Field records should now be in place for your CreateIncident messsage:

    19) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    20) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    We will now examine our new, auto-generated Message Scripts.

    Source to Stage:

    Stage to Request:

    We are now ready to Test our CreateIncident Message.

    technical documentation

    Incident Field

    Outbound

    Set to true to use for outbound Messages.

    <false>

    Outbound

    Set to true to use for outbound Messages.

    <false>

    14

    Mandatory

    Set to true to make mandatory.

    <true>

    Outbound

    Set to true to use for outbound Messages.

    <false>

    22

    Mandatory

    Set to true to make mandatory.

    <true>

    CreateIncident Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the CreateIncident Message.

    Field: message.message_header

    The ‘message.message_header’ Field record is visible and inactive. It is an Integration level Field which was automatically created by Unifi at the time we created the Message level record (as per the 'CreateIncidentReceipt Fields' page). We’ll talk more about Integration level & Message level Fields in the '

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=2e3f564ddb7d985094dbd7795e961930]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.caller_id = '' + (source.caller_id || default_value);
      } else if (source.caller_id != '') {
        $stage.caller_id = '' + source.caller_id;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=aa75199ddbb5d85094dbd7795e9619d5]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $stage.short_description = '' + (source.short_description || default_value);
      } else if (source.short_description != '') {
        $stage.short_description = '' + source.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=7c78295ddbf5d85094dbd7795e9619fd]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var field_choice;
      var is_mandatory = false;  
    
      if (!source.state.nil()) {
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',         '=', 'incident');
        field_choice.addQuery('element',       '=', 'state');
        field_choice.addQuery('integration',   '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message', '=', '');
        field_choice.addQuery('direction',     '=', 'Outbound');
        field_choice.addQuery('value',         '=', source.state);
        field_choice.addQuery('active',        '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          $stage.state = '' + field_choice.external_value;
        }
      } 
    
      if (!$stage.state) {
        $stage.state = '' + (source.state || '');
      }
    
      if (is_mandatory) {
        $stage.state = '' + (source.state || '');
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=2e3f564ddb7d985094dbd7795e961930]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.caller_id = '' + $stage.caller_id;
      } else if ($stage.caller_id) {
        $payload.caller_id = '' + $stage.caller_id;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=aa75199ddbb5d85094dbd7795e9619d5]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      var $payload = payload;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory) {
        $payload.short_description = '' + $stage.short_description;
      } else if ($stage.short_description) {
        $payload.short_description = '' + $stage.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=7c78295ddbf5d85094dbd7795e9619fd]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      var $payload = payload;
    
      var is_mandatory = false;  
    
      if (is_mandatory) {
        $payload.state = $stage.state;
      } else if ($stage.state) {
        $payload.state = $stage.state;
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    ' section.

    It is now easier than ever to create a Message level Field record for its Integration level counterpart.

    From the CreateIncident Message, navigate to Message > Fields.

    1) Find the message.message_header (Integration level) Field & set Active to true.

    Feature Alert: The ‘Build Integration’ button becomes visible in the banner and the empty 'circle icon' (next to the Field name) turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field). Note: the empty 'circle icon' indicates that the Integration level Field is available to add to the Message.

    By simply setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart. The Integration level record still exists (and can be seen when you click on the ‘Fields’ icon to navigate to the Fields page), but is no longer visible in the list view on the Message because the Message level record has been created.)

    Hints & Tips: Unifi automatically creates Integration level Fields when we first create the Message level equivalent records; those Integration level Fields are visible on the Fields list of the Messages we subsequently create. Therefore, if a Field is required for multiple Messages, create it once for the first Message and then simply set active to true for its Integration level counterpart from the Fields list of each of the relevant Messages that Field is required on.

    We will now configure Field records for a select few Incident record field elements.

    Fields & Field Maps

    Depending on your requirements, you will need to create Field records for each of the relevant Incident record field elements (see the table below for an example). For the sake of brevity, this Guide will focus on a select few. If you wish, however, you are free to continue & configure the remaining Field records. The table below lists an example of the Incident record field elements you may wish to map and the relevant Field Maps required to configure each Field record. For a fuller definition of available Field Maps, please see the relevant page in our technical documentation.

    Incident Field

    Field Map

    caller_id

    Reference

    short_description

    String

    description

    String

    category

    Choice

    impact

    Choice

    The Field records we will focus on will be for Caller (Reference), Short description (String) and State (Choice).

    Copy Field Maps

    If you haven't already, you will need to copy the relevant additional Field Maps for the CreateIncident Field records as follows:

    • Reference

    • String

    • Choice

    See Copy Field Maps (on the 'CreateIncidentReceipt Fields' page) for details.

    Field: incident.caller_id

    From the CreateIncident Message, navigate to Message > Fields. Click New.

    The fields to be configured for the incident.caller_id New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncident'

    2

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The caller on this incident'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.caller_id' New Field modal should look like this:

    6) Submit the record.

    You will be redirected back to the Fields page of the CreateIncident Message.

    Field: incident.short_description

    Click New.

    The fields to be configured for the incident.short_description New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncident'

    7

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The short description of the incident'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.short_description' New Field modal should look like this:

    11) Submit the record.

    You will be redirected back to the Fields page of the CreateIncident Message.

    Field: incident.state

    Field records can exist at both the Integration and the Message level (a Field record exists at the Integration level if it isn't linked to a Message i.e. the 'Message' field element is left blank). We noted previously that an Integration level Field record is automatically created when we first create one at the Message level. We will utilise and configure both when mapping 'incident.state'.

    The 'incident.state' Field record is a Choice 'type' Field. These are used when you’re mapping choice field elements with static values that don't change per Message (e.g. State, Impact, Urgency) i.e. you're not going to have one set of choices/values for create and another for update.

    Rather than configure choices for each Message, configure choices once at the Integration level. This means you only need define them once. The Field Map will take care of it and any 'incident.state' Field records that are set at the Message level (i.e. with a value in the 'Message' field) would use the choices configured at the Integration level.

    We'll first configure the Message level Field and then move on to configure the choices on its Integration level counterpart.

    Field: incident.state (Message level)

    There is no need to 'Generate field choices' for Message level Field records because the Field Map always looks for them on an Integration level Field which has the same name.

    From the CreatIncident Message, navigate to Message > Fields. Click New.

    The fields to be configured for our incident.state (Message level) New Field modal are as follows:

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncident'

    12

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The incident lifecycle state'

    *

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.state' (Message level) New Field modal should look like this:

    16) Submit the record.

    You will be redirected back to the Fields page of the CreateIncident Message.

    Field: incident.state (Integration level)

    We will need to 'Generate field choices' for this Integration level Choice 'type' Field.

    Navigate to the 'Fields' icon to open the Fields page.

    17) Click to open the incident.state (Integration level) Field record (the one where Message is empty).

    The incident.state Field record opens to the Details page.

    18) Navigate to Field > Field Choices.

    19) Click Generate field choices.

    20) Click Generate on the 'Generate field choices' modal which displays.

    The Field Choices are generated & now visible in the list.

    At this stage, you could carry on and configure any remaining Field records for the rest of the Incident record field elements (as per your requirements - see the Fields & Field Maps table at the top of this section). However, we will now run the Build process to auto-generate our Message Scripts.

    Build

    Now that we’ve configured the Field records for the CreateIncident message, we are ready to build our message scripts.

    From the CreateIncident message, navigate to Message > Fields.

    The following Field records should now be in place for your CreateIncident messsage:

    21) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    22) Navigate to Advanced > Script Editor to view the auto-generated code.

    Your Script Editor fields should look like this:

    The newly auto-generated code will appear between a Begin & End Comment immediately prior to any code that was already there.

    Stage to Target:

    The code we had previously added when configuring our Message as per the 'CreateIncident Message' page is still in place and can be seen after the End Comment.

    The code in the ‘Stage to Target’ script field should look like this:

    We are now ready to Test our CreateIncident Message.

    Field: incident.state

    Active

    Set to true to use this Field record for processing.

    <true>

    2

    Field map

    The Field Map this Field record is linked with.

    'IS - String'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident '[incident]

    3

    Element

    The field on the source/target table this Field record is mapped to.

    'Caller'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    4*

    Inbound

    Set to true to use for inbound Messages.

    <false>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The short description of this incident'

    Active

    Set to true to use this Field record for processing.

    <true>

    11

    Field map

    The Field Map this Field record is linked with.

    'IS Choice'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    12

    Element

    The field on the source/target table this Field record is mapped to.

    'State'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    13*

    Inbound

    Set to true to use for inbound Messages.

    <false>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    (New auto-generated code will appear here)
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    (Old pre-existing code will appear here)
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=09f77d201b469010e645311d1e4bcb00]", function () {
      log.debug("Field map: IG Reference [x_snd_eb_field_map.do?sys_id=2a41c28edbcdd850853c561bdc96193c]");
    
      var default_value = (function () {
        return '';
      })();
    
      if (false && $stage.caller_id == undefined) {
        throw 'Mandatory field caller_id was not provided';
      } else {
        var table = target.caller_id.getReferenceTable(),
            ref,
            gr,
            value;
    
        value = $stage.caller_id.value || default_value;
    
        if (value != '') {
          gr = new GlideRecord(table);
          gr.addQuery('sys_id', '=', value);
          gr.query();
    
          if (gr.next()) {
            target.caller_id = gr.sys_id;
          } else {
            target.setDisplayValue("caller_id", $stage.caller_id.display_value);
            ref = target.caller_id.getRefRecord();
    
            if (!ref.isValidRecord()) {
              target.caller_id = ''; 
              throw 'Related record for field caller_id with value ' 
                + $stage.caller_id.display_value + ' not found.';
            }
          }
        }
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=b33a02241b869010e645311d1e4bcb91]", function () {
      log.debug("Field map: IG String [x_snd_eb_field_map.do?sys_id=f8d1068edbcdd850853c561bdc9619e7]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.short_description == '') {
        throw 'Mandatory field short_description was not provided';
      } else {
        target.short_description = '' + ($stage.short_description || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=db7bb2601b4a9010e645311d1e4bcb73]", function () {
      log.debug("Field map: IG Choice [x_snd_eb_field_map.do?sys_id=0b81068edbcdd850853c561bdc9619e3]");
    
      var default_value = (function () {
        return '';
      })();
    
      var is_mandatory = false;  
    
      if (is_mandatory && $stage.state == undefined) {
        throw 'Mandatory field state was not provided';
      } else {
        var field_choice;
    
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',          '=', 'incident');
        field_choice.addQuery('element',        '=', 'state');
        field_choice.addQuery('integration',    '=', '679011eedb781050853c561bdc9619cf');
        field_choice.addQuery('field.message',  '=', '');
        field_choice.addQuery('direction',      '=', 'Inbound');
        field_choice.addQuery('external_value', '=', $stage.state);
        field_choice.addQuery('active',         '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          target.state = field_choice.value;
        } else {
          target.state = $stage.state;
        }
      }
    
    });
    
    if (x_snd_eb.ws_console.has_error) {
      var errors = x_snd_eb.ws_console.get({type: 'error'});
      if (errors.length) {
        throw errors[0];
      }
    }
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    bond.setOpen();

    urgency

    Choice

    state

    Choice

    comments

    Journal field

    work_notes

    Journal field

    Active

    Set to true to use this Field record for processing.

    <true>

    3

    Field map

    The Field Map this Field record is linked with.

    'IG Reference'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    4

    Element

    The field on the source/target table this Field record is mapped to.

    'Caller'

    5

    Path

    Where in the payload the data will be placed.

    'detail'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    Active

    Set to true to use this Field record for processing.

    <true>

    8

    Field map

    The Field Map this Field record is linked with.

    'IG String'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    9

    Element

    The field on the source/target table this Field record is mapped to.

    'Short description'

    10

    Path

    Where in the payload the data will be placed.

    'detail'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    Active

    Set to true to use this Field record for processing.

    <true>

    13

    Field map

    The Field Map this Field record is linked with.

    'IG Choice'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    14

    Element

    The field on the source/target table this Field record is mapped to.

    'State'

    15

    Path

    Where in the payload the data will be placed.

    'detail'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    *

    Outbound

    Set to true to use for outbound Messages.

    <true>

    CreateIncidentInbound Fields

    We will utilise the Field & Field Map records to configure the Message Scripts for the CreateIncidentInbound Message.

    Copy Field Maps

    It is worth copying all relevant OOTB Field Maps as are necessary for your integration before using any of them in your Field Records - thereby mitigating the risk of any potential issues with future upgrades

    Some Field Maps should already have been copied for this Integration whilst following the Outbound Incident Guide and the previous two Poller Guides. There is one more that will need to be copied. The remaining Field Map we shall use for our CreateIncidentInbound Field record is:

    • Reference

    To copy the Reference Field Map, navigate to the 'Field Maps' icon.

    1) Click on the ellipsis to the right of the Reference Field Map & then click Copy.

    Copy Field Map Modal

    The fields to edit for the Copy Field Map modal are as follows:

    *Name: We have chosen to prefix the existing Field Map Name with the initials of our Integration (you are free to choose any appropriate means of identifying/differentiating).

    Your Copy Field Map modal should look like this:

    3) Click Copy.

    You will be redirected to the Details page of the newly created Field Map.

    Hints & Tips: Unifi automatically creates Integration level Fields when we first create the Message level equivalent records; those Integration level Fields are visible on the Fields list of the Messages we subsequently create. Therefore, a number of Fields already exist at the Integration level and are available to be added to the CreateIncidentInbound Message. In order to create the Message level records all we need to do is to set Active to 'true' for each of the relevant Integration level records and Unifi will create the Message level record for us. However, there may still be a few minor configuration changes to make, dependent on whether their Integration level configuration matches the requirements for this Message.

    The relevant Integration level Fields that should already be in place are as follows: message.header, incident.short_description, incident.description

    Field records can represent the handling of two categories of data: either a data object which carries transaction specific data (e.g. name, time stamp, source id etc.), or a field element on the bonded record (e.g. Short description). We will begin by configuring a Field record to deal with the transaction specific data.

    Field: message.header

    The ‘message.header’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we first created the Message level record when completing the Incident Update Poller Guide. We will now create its Message level counterpart.

    From the CreateIncidentInbound Message, navigate to Message > Fields.

    Your CreateIncidentInbound Fields page should look like this:

    1) Find the message.header (Integration level) Field & set Active to true.

    As before, when we set Active to true the ‘Build Integration’ button becomes visible in the banner (which acts as a visual reminder that Field configuration has changed and the Message Scripts need to be built) and the empty circle icon next to the Field name turns green & contains a green ‘check’ (to indicate that Message level configuration exists for this Field).

    (The empty 'circle icon' indicates that the Integration level Field is available to add to the Message.).

    By setting the Active flag to true on the Integration level Field record listed on the Message, Unifi has automatically created the Message level counterpart. There is no need to edit the settings any further for this Message level Field as the ones copied from the Integration level record already match our requirements.

    Fields & Field Maps

    Depending on your requirements, you will need to create Field records for each of the relevant Incident record field elements you wish to map. As we have only chosen to include the caller_id, short_description, description, state, impact & urgency elements in both the Setup script & Response script of the Poll Processor, this Guide will focus on those six. If you wish, however, you are free to configure other Field records as required (ensuring you also define them in both the Setup Script & Response script of the Poll Processor).

    For a full description of the available Field Maps, please see the relevant page in our .

    The table below lists the Incident record field elements we will map and the relevant Field Maps required to configure each Field record.

    *Field map: Values may vary (dependent on your configuration of the copies). Choose the copy Field Maps you created.

    Field: incident.caller_id

    Important: Although the ‘incident.caller_id’ (Integration level) Field record is already in place (automatically created by Unifi when we first created the Message level record when completing the Outbound Incident Guide), we will NOT be using it to create the Message level counterpart for the CreateIncidentInbound Message. This is because that is a String 'type' Field. Instead, we shall create a new Reference 'type' Field record.

    The reason for using different Field 'types' for inbound & outbound for the Caller field is because of the requirements of integrating with the ServiceNow table API. Sending to the table API requires the value whereas pulling from the table API gives us an object which contains the value. This is the reason we use a String Field Map for sending and a Reference Field Map for receiving.

    Note: This would apply to all reference fields (not just caller_id).

    From the CreateIncidentInbound Message, navigate to Message > Fields. Click New.

    The fields to be configured for the 'incident.caller_id' New Field modal as follows:

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.caller_id' New Field modal should look like this:

    7) Click Submit and view to further configure the Field record.

    The incident.caller_id Field record opens to the Details page.

    Defaults

    Returning data from reference fields poses some challenges. When dealing with referential data, values in each system would need to match (this would apply whether we were receiving actual or display values). The ways of dealing with that fall outside of the scope and purpose of this Guide.

    We have configured the endpoint so that the table API is returning the display_value element for reference data objects. This means that we can set a default value to ensure that the Caller field on the Incident is populated with a meaningful value should it not find a matching record (instead of throwing a process error).

    Navigate to Field > Defaults.

    The fields to be configured for the Defaults page are as follows:

    The code in the 'Default inbound' script field should look like this:

    Your Defaults page should look like this:

    9) Save the record.

    Field: incident.short_description

    The ‘incident.short_description’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we first created the Message level record when completing the Outbound Incident Guide. We will now create its Message level counterpart.

    To quickly navigate back to the CreateIncidentInbound Message, from the Details page of the incident.caller_id Field record...

    ...click the ‘Preview’ icon to the left of the Message field.

    From the CreateIncidentInbound Message, navigate to Message > Fields.

    Your CreateIncidentInbound Fields page should look like this:

    10) Find the incident.short_description (Integration level) Field & set Active to true.

    11) Click to open the incident.short_description (Message level) Field to make a few minor changes.

    The incident.short_description Field record opens to the Details page.

    Navigate to Field > Settings.

    Edit the incident.short_description Field record as follows:

    Your incident.short_description Field record should look like this:

    15) Save the record.

    Field: incident.description

    The ‘incident.description’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we first created the Message level record when completing the Outbound Incident Guide. We will now create its Message level counterpart.

    To quickly navigate back to the CreateincidentInbound Message from the Details page of the incident.short_description Field record...

    ...click the 'Preview' icon to the left of the Message field.

    From the CreateIncidentInbound Message, navigate to Message > Fields.

    Your CreateIncidentInbound Fields page should look like this:

    16) Find the incident.description (Integration level) Field & set Active to true.

    17) Click to open the incident.description (Message level) Field to make a few minor changes.

    The incident.description Field record opens to the Details page.

    Navigate to Field > Settings.

    Edit the incident.description Field record as follows:

    Your 'incident.description' Field record should look like this:

    21) Save the record.

    If you had previously completed the Incident Update Poller Guide, then the Settings may already match because the Integration level Field record would have been updated when configuring the Fields for the UpdateIncidentinbound Message. Confirm that the settings match those above.

    Field: incident.state

    The ‘incident.state’ (Integration level) Field record should already be in place (i.e. with Active set to false). This was automatically created by Unifi when we first created the Message level record when completing the Outbound Incident Guide. We will now create its Message level counterpart.

    To quickly navigate back to the CreateincidentInbound Message from the Details page of the incident.description Field record...

    ...click the 'Preview' icon to the left of the Message field.

    From the CreateIncidentInbound Message, navigate to Message > Fields.

    Your CreateIncidentInbound Fields page should look like this:

    22) Find the incident.state (Integration level) Field & set Active to true.

    23) Click to open the incident.state (Message level) Field to make a few minor changes.

    The incident.state Field record opens to the Details page.

    Navigate to Field > Settings.

    Edit the incident.state Field record as follows:

    Your 'incident.state' Field record should look like this:

    27) Save the record.

    Field: incident.impact (Message level)

    There is no need to 'Generate field choices' for Message level Field records because the Field Map always looks for them on an Integration level Field which has the same name.

    As with 'incident.state' the 'incident.impact' Field record is a Choice 'type' Field. These are used when you’re mapping choice field elements with static values that don't change per Message (e.g. State, Impact, Urgency). We'll first configure the Message level Field and then move on to configure the choices on its Integration level counterpart.

    To quickly navigate back to the CreateincidentInbound Message from the Details page of the incident.state Field record...

    ...click the 'Preview' icon to the left of the Message field.

    From the CreateIncidentInbound Message, navigate to Message > Fields. Click New.

    The fields to be configured for the incident.impact (Message level) New Field modal are as follows:

    *These fields are automatically defaulted to true, or automatically populated.

    **Field map: Value may vary. Choose the copy Field Map you created for your Integration.

    Your 'incident.impact' (Message level) New Field modal should look like this:

    33) Submit the record.

    You will be redirected back to the Fields page of the CreateIncidentInbound Message.

    Field: incident.impact (Integration level)

    We will need to 'Generate field choices' for this Integration level Choice 'type' Field.

    Navigate to the 'Fields' icon to open the Fields page.

    34) Click to open the incident.impact (Integration level) Field record (the one where Message is empty).

    The incident.impact Field record opens to the Details page.

    35) Navigate to Field > Field Choices.

    36) Click Generate field choices.

    37) Click Generate on the 'Generate field choices' modal which displays.

    The Field Choices are generated & now visible in the list.

    Field: incident.urgency (Message level)

    There is no need to 'Generate field choices' for Message level Field records because the Field Map always looks for them on an Integration level Field which has the same name.

    Because the incident.urgency Field record is the same ‘type’ (IS - Choice) & the majority of the settings are the same as the previously configured Field, it will be quicker to copy the incident.impact Field & make a few minor changes.

    Navigate back to the CreateIncidentInbound Message, then navigate to Message > Fields.

    Your CreateIncidentInbound Fields page should look like this:

    38) Click the ellipsis next to the incident.impact Field record & click Copy.

    The fields to edit for the Copy Field modal are as follows:

    *This field is automatically populated.

    Your 'incident.urgency' Copy Field modal should look like this:

    41) Click Copy.

    You will be redirected to the Details page of the newly created incident.urgency Field record.

    Field: incident.urgency (Integration level)

    We will need to 'Generate field choices' for this Integration level Choice 'type' Field.

    Navigate to the 'Fields' icon to open the Fields page.

    42) Click to open the incident.urgency (Integration level) Field record (the one where Message is empty).

    The incident.urgency Field record opens to the Details page.

    43) Navigate to Field > Field Choices.

    44) Click Generate field choices.

    45) Click Generate on the 'Generate field choices' modal which displays.

    The Field Choices are generated & now visible in the list.

    Build

    Now that we’ve configured the Field records for the CreateIncidentInbound message, we are ready to build our message scripts.

    Navigate back to the CreateIncidentInbound Message, then navigate to Message > Fields.

    The following Field records should now be in place for your CreateIncidentInbound messsage:

    46) Click on Build Message.

    You will see the 'Message build successful' Info Message.

    47) Navigate to Advanced > Script Editor > View > Inbound to view the auto-generated code.

    Your Script Editor fields should look like this:

    Message Scripts

    The Message Scripts reflect the mappings as per this Guide. Your scripts might differ depending on which Fields you chose to map (& defined in the payload). We will look at the Message Scripts in turn.

    Payload to Stage:

    Your Payload to Stage Message Script should look like this:

    Stage to Target:

    The code we had previously added when configuring our Message on the '' page is still in place and can be seen after the End Comment.

    Your Stage to Target Message Script should look like this:

    Before we test, let's take a quick look at running Build at the Integration level.

    &
    incident.state
    . We will deal with each in turn in the subsequent sections, detailing any changes that are needed to their configuration. For speed, you may wish to set Active to 'true' for each of them.

    'IS - Choice'*

    Set to true to use this Field record for processing.

    <true>

    3

    Field map

    The Field Map this Field record is linked with.

    'IS - Reference'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident '[incident]

    4

    Element

    The field on the source/target table this Field record is mapped to.

    'Caller'

    5

    Path

    Where in the payload the data will be placed.

    ‘detail’

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    6*

    Outbound

    Set to true to use for outbound Messages.

    <false>

    Set to true to use for outbound Messages.

    <false>

    Set to true to use for outbound Messages.

    <false>

    Set to true to use for outbound Messages.

    <false>

    Set to true to use this Field record for processing.

    <true>

    29

    Field map

    The Field Map this Field record is linked with.

    'IS - Choice'**

    *

    Map to field

    Use this Field record to represent a field on a source/target table.

    <true>

    *

    Table

    The primary source/target table that this Field record is mapped to.

    'Incident' [incident]

    30

    Element

    The field on the source/target table this Field record is mapped to.

    'Impact'

    31

    Path

    Where in the payload the data will be placed.

    'detail'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    *

    Inbound

    Set to true to use for inbound Messages.

    <true>

    32*

    Outbound

    Set to true to use for outbound Messages.

    <false>

    Describe what this field is for and any specific details that might help you in future.

    'The urgency of the incident.'

    #

    Field

    Description

    Value

    2

    Name*

    The name of your field map. (If left unedited, it will append the word 'Copy' to the existing name.)

    <Your Name>

    Incident Field

    Field Map

    caller_id

    'IS - Reference'*

    short_description

    'IS - String'*

    description

    'IS - String'*

    state

    'IS - Choice'*

    impact

    'IS - Choice'*

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncidentInbound'

    2

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The caller on this incident. Used for inbound messages from the table API.'

    *

    #

    Field

    Description

    Value

    8

    Default inbound

    Generate a default value that can be used when an inbound request does not contain a value for this field.

    Update the Default inbound script field so that it looks like the code below

    #

    Field

    Description

    Value

    12

    Path

    Where in the payload the data will be placed.

    ‘detail’

    13

    Inbound

    Set to true to use for inbound Messages.

    <true>

    14

    #

    Field

    Description

    Value

    18

    Path

    Where in the payload the data will be placed.

    ‘detail’

    19

    Inbound

    Set to true to use for inbound Messages.

    <true>

    20

    #

    Field

    Description

    Value

    24

    Path

    Where in the payload the data will be placed.

    ‘detail’

    25

    Inbound

    Set to true to use for inbound Messages.

    <true>

    26

    #

    Field

    Description

    Value

    *

    Message

    The Message this Field record is linked with.

    'CreateIncidentInbound'

    28

    Description

    Describe what this field is for and any specific details that might help you in future.

    'The impact of the incident.'

    *

    #

    Field

    Description

    Value

    39

    Element

    The field on the source/target table this Field record is mapped to.

    'Urgency'

    *

    Property

    The property in the payload the data will be written to.

    Automatically populated

    40

    technical documentation
    CreateIncidentInbound Message

    urgency

    Active

    Outbound

    Outbound

    Outbound

    Active

    Description

    var default_value = (function () {
      return gs.getUserID();
    })();
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.checkpoint("MessageScript")
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=efffbde2db2e981041f945e8139619aa]", function () {
      log.debug("Field map: IS - Reference [x_snd_eb_field_map.do?sys_id=3f082d2adbea981041f945e8139619a3]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      if (false && $payload.caller_id == undefined) {
        throw 'Mandatory field caller_id was not provided';
      } else {
        $stage.caller_id = $payload.caller_id;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=938dece1dbead41041f945e8139619fe]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $payload.description == undefined) {
        throw 'Mandatory field description was not provided';
      } else {
        $stage.description = $payload.description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.impact [x_snd_eb_field.do?sys_id=6424c9e1db2ed41041f945e81396191d]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      var is_mandatory = false;  
    
      if (is_mandatory && $payload.impact == undefined) {
        throw 'Mandatory field impact was not provided';
      } else {
        $stage.impact = $payload.impact;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=64788264dba2541041f945e8139619b3]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $payload.short_description == undefined) {
        throw 'Mandatory field short_description was not provided';
      } else {
        $stage.short_description = $payload.short_description;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=eae5b0a1db2ed41041f945e813961905]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      var is_mandatory = false;  
    
      if (is_mandatory && $payload.state == undefined) {
        throw 'Mandatory field state was not provided';
      } else {
        $stage.state = $payload.state;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.urgency [x_snd_eb_field.do?sys_id=1c9f4921db6ed41041f945e8139619d3]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
      payload = payload || {};
      payload.detail = payload.detail || {};
      var $payload = payload.detail;
    
      var is_mandatory = false;  
    
      if (is_mandatory && $payload.urgency == undefined) {
        throw 'Mandatory field urgency was not provided';
      } else {
        $stage.urgency = $payload.urgency;
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping message.header [x_snd_eb_field.do?sys_id=55bde1acdb62541041f945e813961997]", function () {
      log.debug("Field map: IS - Message Header [x_snd_eb_field_map.do?sys_id=9e0d1d7a1b4e90105830db9ebd4bcb5f]");
      payload = payload || {};
      payload.message = payload.message || {};
      var $payload = payload.message;
    
      // Messge identifiers
      $stage.$message_name = $payload.name;
      $stage.$time_stamp   = $payload.time_stamp;
    
      // Task references
      stage.internal_reference = $payload.target_reference || '';
      stage.external_reference = $payload.source_reference || '';
    
      // Transaction identifiers
      transaction.external_message_id = $payload.source_id || '';
    
    
    
    });
    
    var error = x_snd_eb.ws_console.findCheckpointError("MessageScript");
    if (error) throw error;
    
    //===== [ws] End Unifi Auto Generated Code =====//
    //===== [ws] Begin Unifi Auto Generated Code =====//
    
    /*
     * This code (between the Begin and End comments) is generated from the
     * Field and Field mapping records which are configured as part of the integration.
     *
     * All code either above or below the comments will be automatically maintained
     * through the build cycle.
     *
     * WARNING: Do not edit the Begin or End comments.
     */
    
    x_snd_eb.ws_console.checkpoint("MessageScript")
    
    x_snd_eb.ws_console.execute("Mapping incident.caller_id [x_snd_eb_field.do?sys_id=efffbde2db2e981041f945e8139619aa]", function () {
      log.debug("Field map: IS - Reference [x_snd_eb_field_map.do?sys_id=3f082d2adbea981041f945e8139619a3]");
    
      var default_value = (function () {
        return gs.getUserID();
      })();
    
      if (false && $stage.caller_id == undefined) {
        throw 'Mandatory field caller_id was not provided';
      } else {
        var table = target.caller_id.getReferenceTable(),
            ref,
            gr,
            value;
    
        value = $stage.caller_id.value || default_value;
    
        if (value != '') {
          gr = new GlideRecord(table);
          gr.addQuery('sys_id', '=', value);
          gr.query();
    
          if (gr.next()) {
            target.caller_id = gr.sys_id;
          } else {
            target.setDisplayValue("caller_id", $stage.caller_id.display_value);
            ref = target.caller_id.getRefRecord();
    
            if (!ref.isValidRecord()) {
              target.caller_id = ''; 
              throw 'Related record for field caller_id with value ' 
                + $stage.caller_id.display_value + ' not found.';
            }
          }
        }
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.description [x_snd_eb_field.do?sys_id=938dece1dbead41041f945e8139619fe]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.description == '') {
        throw 'Mandatory field description was not provided';
      } else {
        target.description = '' + ($stage.description || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.impact [x_snd_eb_field.do?sys_id=6424c9e1db2ed41041f945e81396191d]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var is_mandatory = false;  
    
      if (is_mandatory && $stage.impact == undefined) {
        throw 'Mandatory field impact was not provided';
      } else {
        var field_choice;
    
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',          '=', 'incident');
        field_choice.addQuery('element',        '=', 'impact');
        field_choice.addQuery('integration',    '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message',  '=', '');
        field_choice.addQuery('direction',      '=', 'Inbound');
        field_choice.addQuery('external_value', '=', $stage.impact);
        field_choice.addQuery('active',         '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          target.impact = field_choice.value;
        } else {
          target.impact = $stage.impact;
        }
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.short_description [x_snd_eb_field.do?sys_id=64788264dba2541041f945e8139619b3]", function () {
      log.debug("Field map: IS - String [x_snd_eb_field_map.do?sys_id=006de8cddbf5985094dbd7795e96191e]");
    
      var default_value = (function () {
        return '';
      })();
    
      // Determines whether this instance of the field map is for a mandatory field
      var is_mandatory = false;
    
      if (is_mandatory && $stage.short_description == '') {
        throw 'Mandatory field short_description was not provided';
      } else {
        target.short_description = '' + ($stage.short_description || default_value);
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.state [x_snd_eb_field.do?sys_id=eae5b0a1db2ed41041f945e813961905]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var is_mandatory = false;  
    
      if (is_mandatory && $stage.state == undefined) {
        throw 'Mandatory field state was not provided';
      } else {
        var field_choice;
    
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',          '=', 'incident');
        field_choice.addQuery('element',        '=', 'state');
        field_choice.addQuery('integration',    '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message',  '=', '');
        field_choice.addQuery('direction',      '=', 'Inbound');
        field_choice.addQuery('external_value', '=', $stage.state);
        field_choice.addQuery('active',         '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          target.state = field_choice.value;
        } else {
          target.state = $stage.state;
        }
      }
    
    });
    
    
    x_snd_eb.ws_console.execute("Mapping incident.urgency [x_snd_eb_field.do?sys_id=1c9f4921db6ed41041f945e8139619d3]", function () {
      log.debug("Field map: IS - Choice [x_snd_eb_field_map.do?sys_id=a58d2401db39985094dbd7795e9619fd]");
    
      var default_value = (function () {
        return '';
      })();
    
      var is_mandatory = false;  
    
      if (is_mandatory && $stage.urgency == undefined) {
        throw 'Mandatory field urgency was not provided';
      } else {
        var field_choice;
    
        field_choice = new GlideRecord('x_snd_eb_field_choice');
        field_choice.addQuery('table',          '=', 'incident');
        field_choice.addQuery('element',        '=', 'urgency');
        field_choice.addQuery('integration',    '=', '642bd074dbb9585094dbd7795e9619a7');
        field_choice.addQuery('field.message',  '=', '');
        field_choice.addQuery('direction',      '=', 'Inbound');
        field_choice.addQuery('external_value', '=', $stage.urgency);
        field_choice.addQuery('active',         '=', 'true');
        field_choice.query();
    
        if (field_choice.next()) {
          target.urgency = field_choice.value;
        } else {
          target.urgency = $stage.urgency;
        }
      }
    
    });
    
    var error = x_snd_eb.ws_console.findCheckpointError("MessageScript");
    if (error) throw error;
    
    //===== [ws] End Unifi Auto Generated Code =====//
    
    bond.setOpen();