ServiceNow Table API Parameters

Using self hosted snownode docker container to replicate servicenow with Jira.
In our use case, some of the fields (e.g. comments) require the URL Parameter “sysparm_display_value” to be set to true in order to be visible in the API. Is there a way in which we can set url parameters?
e.g. Headers can be set as demonstrated How to Set Custom Headers in Communication between Exa

Great question! When integrating ServiceNow with Jira using Exalate (including self-hosted snownode containers), you sometimes need to adjust ServiceNow Table API parameters like sysparm_display_value to get certain fields (such as comments) in the desired format.

Based on the Exalate documentation, while you can set custom headers for ServiceNow connections (as you referenced), there isn’t a direct UI option to set custom URL parameters like sysparm_display_value in Basic Mode. However, if you use Script Mode, you have much more flexibility. In Script Mode, you can customize the sync rules using Groovy scripts, which allows you to control what data is sent and received—including how fields are fetched and mapped.

To leverage this flexibility:

  • Switch your connection to Script Mode (or create a new one in Script Mode).
  • In your sync rules, you can customize how fields are handled, and in some advanced cases, you can use scripting to fetch additional data from ServiceNow using custom API calls, where you can specify URL parameters like sysparm_display_value=true.

You can find more about configuring Script Mode and customizing sync rules here:

If you’re currently in Basic Mode, you’ll need to upgrade to Script Mode to achieve this level of customization.

Let me know if you need a sample script or further details on how to implement this in your sync rules!

Hi Steven!

If your case doesn’t allow Exalate to work with the internal use of Comment you can work with Httpclient calls, that will allow you to sync comments, but the problem will be the traces and ids that the comments or other fields get thru Exalate, if you need to edit/delete or do anything to the comments you will also have to work your way thru Httpclient calls

Here is an Example on how to use them

def apiUrlPath = 'PATH'
def requestHeaders = [HEADERS]

try {
                // Perform the PATCH request using httpClient.http
                def response = httpClient.http(
                    "POST", // HTTP method
                    apiUrlPath, // URL path
                    requestBody, // Request body (JSON string)
                    [:], // Query parameters (empty map)
                    requestHeaders // Headers
                ) { request, response ->
                    // This closure handles the response
                    if (response.code >= 200 && response.code < 300) {
                        return true // Indicate success
                    } else {
                        return false // Indicate failure
                    }
                }

If your case doesn’t allow the proxy user to work with comments or other fields you can use the Exalate user that will post the comment and works with the normal table api.

BR

Tomas

I was hoping to avoid the use of a lot of further scripting to get this to work and hoped for an option similar to how custom headers are injected into the connection between ServiceNow and Exalate.

e.g. a PROXY_PARAMETERS environment variable that appends URL parameters on the end of the connection string used by Exalate to query the Table API

Also,
Using the httpClient would return all comments as a single string but the commentHelper requires them to be iHubComment Objects in order for them to be merged successfully on the receiving side. Which relates back to your message about ids and traces

To anyone that is interested, this i how I’ve achieved this on the ServiceNow Exalate connection side in the Outgoing Sync.

//Comments
    //Get Comments for the entity with sysparm_display_value=true
    def entityComments = httpClient.get("/api/now/v1/table/" + entity.tableName + "?sysparm_query=number=" + entity.key + "&sysparm_display_value=true").result.comments[0]
    def items = entityComments.split(/(?=\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2} (?:AM|PM) - )/)
    items = items.collect { it.trim() }.findAll { it }
    
    def commentList = []
    def inputFormat = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss a")
    for (item in items) {
      def lines = item.split('\n')
      def header = lines[0]
      def matcher = header =~ /^(\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2} (?:AM|PM)) - ([^(]+) \(Additional comments\)$/
      def datetimeStr = matcher[0][1]
      def author = matcher[0][2].trim()
      def body = lines.length > 1 ? lines[1..-1].join('\n').trim() : ""
      def comment = new com.exalate.basic.domain.hubobject.v1.BasicHubComment()
      //Need to lookup the user in ServiceNow by the name and return the User Object
      comment.author = nodeHelper.getUserByFullName(author)
      comment.created = inputFormat.parse(datetimeStr)
      comment.body = body
      
      commentList << comment
    }
    
    //Only send the newest comment (Saves Duplicates being sent)
    replica.comments += commentList.max { it.created }

      def body = lines.length > 1 ? lines[1..-1].join('\n').trim() : ""

def comment = new com.exalate.basic.domain.hubobject.v1.BasicHubComment()

//Need to lookup the user in ServiceNow by the name and return the User Object

      comment.author = nodeHelper.getUserByFullName(author)

      comment.created = inputFormat.parse(datetimeStr)

      comment.body = body

      commentList << comment

    }

replica.comments = commentHelper.filterLocal(commentList)

This creates a BasicHubComment Object for each Comment created, and selects the newest one. Because I’m having to parse the comments via httpClient and having no presence of the id, This was the best solution I could come up with to save unnecessary duplicate comments and getting stuck in a comment loop.

Hi @steven.foxton !

Unfortunately for now that is the solution.

I will check with the team if there is any other ways but for now that is the solution

BR

Tomas