The following article is now DEPRECATED. Although this method will still work within the ServiceNow product, there is now a GUI based utility in ServiceNow called “REST Message”. This utility will allow you to set up a REST web service call using an interface rather than a pure coding play.

I recently came across a customer that needed to integrate with a third-party application that could only speak REST rather than the more standard and traditional SOAP web service method. Don’t get me wrong, REST has it’s followers and it’s strengths. However, because it is so simple, it often gets looked down upon as something that is unworthy of enterprise level integration.

Service-now.com doesn’t have a published API or library for dealing with REST, but it has all of the capabilities inside of it to send RESTful requests and interpret the corresponding responses.

Of course, REST allows for GET, POST, PUT, and DELETE methods. This blog entry is really just focusing on the GET method, but once you get that down, you are able to easily move into the other methods.

Since REST is really just HTTP requests, we know that Service-now can make these types of requests through Java Packages. To make things a little more concise and readable, I put my Package calls into some handy variables as seen below:

1
2
3
4
5
var httpclient = Packages.org.apache.commons.httpclient;
var HttpClient = httpclient.HttpClient;
var UsernamePasswordCredentials = httpclient.UsernamePasswordCredentials;
var AuthScope = httpclient.auth.AuthScope;
var GetMethod = httpclient.methods.GetMethod;

My demo script is going to be run within one Service-now.com demo instance to call another Service-now demo instance. This shows how Service-now can both request RESTfully and receive REST requests (though the focus for this article is to send the request).

Since Service-now instances are authenticated via Basic Authentication, we are going to use Basic Authentication in our code to connect to the main demo instance, “https://demo.service-now.com”.

1
2
3
4
var client = new HttpClient();
var authScope = new AuthScope("demo.service-now.com", 443, null)
var credentials = new UsernamePasswordCredentials("admin", "admin")
client.getState().setCredentials( authScope, credentials);

Now, really, a GET method in HTTP requests (and REST requests) contains all of the needed parameters in the URL string on the request. This differs from a POST method — so this is a place where you would diverge a bit if doing a POST method rather than a GET.

For our GET request, we are going to look for all Incidents with an Incident State of 1 and a Priority of 1. We also will be asking Service-now to return that in XML format. Here are the pieces of our URL for this GET request:

URL: https://demo.service-now.com/incident_list.do
Encoded Query Parameter: sysparm_query=incident_state%3D1%5Epriority%3D1
Format Processor Parameter: XML

The resultant javascript call looks like this:

1
var get = new GetMethod( "https://demo.service-now.com/incident_list.do?sysparm_query=incident_state%3D1%5Epriority%3D1&XML");

Next, we want to tell the GET method to automatically authenticate us using the Basic Auth information provided above.

1
get.setDoAuthentication( true );

Now that our GET method and HTTP Client objects are set up, we execute the method using the following code:

1
var status = client.executeMethod( get );

The “status” variable will receive the HTTP status code back. If we want to see the resulting data returned, we use the call: getResponseBodyAsString(). Since we are having SNC return an XML document back to us, I decided to escape the “<” characters to help view the result better in the browser. This is really not necessary when handling the data programmatically, but it was helpful for demo reasons.

1
2
var result = (status + "\n" + get.getResponseBodyAsString()).replace(/</g, "&"+"lt;");
gs.print(result);

When you are done, don’t forget to release the GET connection:

1
get.releaseConnection();

Since the response in this exercise was in the XML format, we could easily send that to the XMLDocument() class so that we could run XPATH queries on the response and handle the data accordingly. If we requested a JSON response, then we could easily convert the JSON response to javascript objects and continue on to do some interesting things.

Another thing you could do is verify the response by reviewing the Response Headers. Your code would go just after the execute method and would look something like this:

1
2
3
4
var headers = get.getResponseHeaders();
for (var i=0;i<headers.length;i++){
  gs.print(headers[i].getName() + ":"+headers[i].getValue());
}

Also, if you needed to use the POST method, your code would change slightly at the point where you originally declared the “Get” method, you would define a “Post” method instead. You would also need to individually add the various parameters rather than include them in your URL string. Here is a sample snippet:

1
2
3
4
var PostMethod = httpclient.methods.PostMethod;
var post = new PostMethod("https://demo.service-now.com/incident_list.do");
post.addParameter("sysparm_query", "incident_state%3D1%5Epriority%3D1");
post.addParameter("xml", "");

If you were to need Service-now.com to be a full-fledged REST provider (meaning 3rd party apps are calling into SNC through REST), you have the tools at your disposal to easily provide query responses. However, if it were required for REST calls to be made that enacted changes in the SN instance, you would probably create a Processor to handle those REST calls and react accordingly. That, however, is a discussion for another day!

Below you will find the entire code that was used for this example. Feel free to plug it into your instance and run it against SNC’s demo instance to see what kind of response you get.

The Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var httpclient = Packages.org.apache.commons.httpclient;
var HttpClient = httpclient.HttpClient;
var UsernamePasswordCredentials = httpclient.UsernamePasswordCredentials;
var AuthScope = httpclient.auth.AuthScope;
var GetMethod = httpclient.methods.GetMethod;

var client = new HttpClient();
var authScope = new AuthScope("demo.service-now.com", 443, null)
var credentials = new UsernamePasswordCredentials("admin", "admin")
client.getState().setCredentials( authScope, credentials);
       
        // create a GET method that reads a file over HTTPS,
        // we know that this file requires basic
        // authentication
var get = new GetMethod( "https://demo.service-now.com/incident_list.do?sysparm_query=incident_state%3D1%5Epriority%3D1&XML");
       
        // Tell the GET method to automatically handle authentication. The
        // method will use any appropriate credentials to handle basic
        // authentication requests.  Setting this value to false will cause
        // any request for authentication to return with a status of 401.
        // It will then be up to the client to handle the authentication.
get.setDoAuthentication( true );
       
                  // execute
var status = client.executeMethod( get );
           
                  //Print out the GET Headers
var headers = get.getResponseHeaders();
for (var i=0;i<headers.length;i++){
  gs.print(headers[i].getName() + ":"+headers[i].getValue());
}
            // print the status and response
var result = (status + "\n" + get.getResponseBodyAsString()).replace(/</g, "&"+"lt;");
gs.print(result);
           

            // release any connection resources used by the method
get.releaseConnection();