Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ServiceNow/example-restclient-myworkapp-nodejs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0
Choose a base ref
...
head repository: ServiceNow/example-restclient-myworkapp-nodejs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 12 commits
  • 7 files changed
  • 4 contributors

Commits on Apr 1, 2016

  1. Update README.md

    Updating links to source from README.md
    bryanbarnard committed Apr 1, 2016
    Copy the full SHA
    793c562 View commit details
  2. Update README.md

    Typo cleanup on README.md
    bryanbarnard committed Apr 1, 2016
    Copy the full SHA
    075a435 View commit details
  3. Update README.md

    codersmith committed Apr 1, 2016
    Copy the full SHA
    a3eff58 View commit details
  4. update README.md

    Silas Smith committed Apr 1, 2016
    Copy the full SHA
    0c09276 View commit details
  5. Copy the full SHA
    cd86b5a View commit details
  6. Handle update set not installed gracefully

    Silas Smith committed Apr 1, 2016
    Copy the full SHA
    27818bd View commit details
  7. Merge pull request #1 from codersmith/master

    Handle update set not installed gracefully -BB reviewed
    bryanbarnard committed Apr 1, 2016
    Copy the full SHA
    0d85de7 View commit details

Commits on Apr 2, 2016

  1. Usage formatting

    codersmith committed Apr 2, 2016
    Copy the full SHA
    4b30fac View commit details

Commits on Apr 7, 2016

  1. Updated README headers & usage formatting (#3)

    * Usage formatting
    
    * Updated README headers
    codersmith committed Apr 7, 2016
    Copy the full SHA
    e36719d View commit details
  2. Update README.md

    codersmith committed Apr 7, 2016
    Copy the full SHA
    0d0534b View commit details

Commits on Apr 26, 2016

  1. Copy the full SHA
    fdeade9 View commit details
  2. Merge pull request #4 from joseph-messerschmidt/master

    Edit readme for grammar, fix doc URLs. Confirmed BB
    bryanbarnard committed Apr 26, 2016
    Copy the full SHA
    6e4b937 View commit details
Showing with 37 additions and 29 deletions.
  1. +1 −0 .gitignore
  2. +24 −25 README.md
  3. +1 −1 common/usage.js
  4. +1 −1 dispatcher/taskDispatcher.js
  5. +1 −1 public/js/taskListController.js
  6. +1 −1 public/view/task_list.html
  7. +8 −0 test/tasksTest.js
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
49 changes: 24 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Example REST Client My Work App: Node.js
This project contains source code for a [Node.js](https://nodejs.org/) web application that interacts with ServiceNow's [REST APIs](https://docs.servicenow.com/integrate/inbound_rest/concept/c_RESTAPI.html) including a [Scripted REST API](https://docs.servicenow.com/integrate/custom_web_services/concept/c_CustomWebServices.html). The simple use case is a "MyWork" application which displays a user's current tasks and allows comments to be added. This application demonstrates how to build the MyWork app using Node.js. To see the same use case implemented in iOS, see [Example REST Client My Work App: iOS](https://github.com/ServiceNow/example-restclient-myworkapp-ios).
This project contains source code for a [Node.js](https://nodejs.org/) web application that interacts with ServiceNow's [REST APIs](https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/inbound_rest/concept/c_RESTAPI.html) including a [Scripted REST API](https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/custom_web_services/concept/c_CustomWebServices.html). The simple use case is a "MyWork" application which displays a user's current tasks and allows comments to be added. This application demonstrates how to build the MyWork app using Node.js. To see the same use case implemented in iOS, see [Example REST Client My Work App: iOS](https://github.com/ServiceNow/example-restclient-myworkapp-ios).

## Architecture
Here is an overview of the MyWork application architecture. Note both this Node.js application and the iOS application are represented in the diagram.
![Architecture diagram](/images/arch_diagram.jpg "Architecture diagram")

--------------------------------------------------------------------------
---------------------------------------------------------------------------

## Prerequisites
* [Node.js](https://nodejs.org/) installed
* A ServiceNow instance ([Geneva Patch 3](https://docs.servicenow.com/release_notes/r_Geneva-Patch-3.html) or later).
* A ServiceNow instance ([Geneva Patch 3](https://docs.servicenow.com/bundle/geneva-release-notes/page/c2/geneva-patch-3-2.html) or later).
* **Don't have a ServiceNow instance?** Get one **FREE** by signing up at https://developer.servicenow.com
* Not sure what version of ServiceNow your instance is running? [Determine running version](http://wiki.servicenow.com/index.php?title=Upgrades_Best_Practices#Prepare_for_Upgrading)

@@ -30,7 +30,7 @@ Here is an overview of the MyWork application architecture. Note both this Node.
$ cd example-restclient-myworkapp-nodejs
$ npm install
```
2. Install the **MyWork Update Set** in your ServiceNow instance. This is a ServiceNow scoped application which contains the **Task Tracker API** Scripted REST API and related files. Note you must be an admin of your ServiceNow instance to install update sets.
2. Install the **MyWork Update Set** in your ServiceNow instance. This is a ServiceNow scoped application which contains the **Task Tracker API** Scripted REST API and related files. Note that you must have the admin role on your ServiceNow instance to install update sets.
1. Obtain the "My Work" update set
* Download the update set from [share.servicenow.com](https://share.servicenow.com/app.do#/detailV2/e43cf2f313de5600e77a36666144b0b4/overview)
<br/>--or--
@@ -59,19 +59,19 @@ Server listening on: http://localhost:3000

```

By default the Node application will listen for requests on localhost port 3000. Navigate your web browser to [http://localhost:3000](http://localhost:3000) and you should see the login screen for the My Work application.
By default the Node application will listen for requests on localhost port 3000. Navigate in your web browser to [http://localhost:3000](http://localhost:3000) and you should see the login screen for the My Work application.

To run the server on a different port, use the `--port=xxxx` option
```bash
$ node server.js --port=8080
Server listening on: http://localhost:8080
```

To print the usage, use --help
For more information about available options, use --help
```bash
$ node server.js --help

Usage: node server.js [ -h ] [ -p <port> ] [ -v ]
Usage: node server.js [ -h ] [ -p <port> ] [ -v ]
-h, --help Show this usage help
-p <port>, --port=<port> HTTP server listen port (default 3000)
-v, --verbose Verbose HTTP output
@@ -81,7 +81,7 @@ $
--------------------------------------------------------------------------

## About the application
In this application, the web browser is the client, which makes HTTP calls to the Node.js server 'server.js' to get task details.
In this application, the web browser is the client which makes HTTP calls to the Node.js server 'server.js' to get task details.

Server side, the Node application uses the **Task Tracker** Scripted REST API to get the list of tasks assigned to the logged-in user. Dispatchers handle interaction between Node and the ServiceNow instance.

@@ -90,15 +90,15 @@ Server side, the Node application uses the **Task Tracker** Scripted REST API to
#### 1. Login
![Login](/images/login.png)

After starting the Node.js web server, navigate your browser to http://localhost:3000. You're presented with a login page where you need to input your ServiceNow instance name (e.g. if your instance URL is https://myinstance.service-now.com, then enter `myinstance` into the Instance text box).
After starting the Node.js web server, navigate your browser to http://localhost:3000. You're presented with a login page where you need to input your ServiceNow instance name (for example, if your instance URL is https://myinstance.service-now.com, then enter `myinstance` into the Instance text box).

Enter the user ID and password for a user on the instance. This application uses Basic Authentication to manage user authentication against the ServiceNow REST API. When a user enters credentials, an HTTP POST call is made to the `/login` endpoint of the Node.js server), which internally establishes a session to the REST API.
Enter the user ID and password for a user on the instance. This application uses Basic Authentication to manage user authentication with the ServiceNow REST API. When a user enters credentials, an HTTP POST call is made to the `/login` endpoint of the Node.js server), which internally establishes a session to the REST API.

**NOTE**: The application makes all REST API calls from the Node.js server side, as opposed to client side from the web browser. You can imagine this application could also be refactored such that the API calls would be made from the client (i.e. AJAX), but that was not the intention of this example application.
**NOTE**: The application makes all REST API calls from the Node.js server side, as opposed to client side from the web browser. This application could also be refactored so that the API calls would be made from the client (such as using AJAX), but that was not the intention of this example application.

On successful login, the user is directed to the `/tasks` endpoint. On failure, the user is directed to the login page to reenter credentials.
On successful login the user is directed to the `/tasks` endpoint. On failure, the user is directed to the login page to reenter credentials.

After login, the application displays the tasks assigned to the user grouped by task type. The application is using the **Task Tracker API** to retrieve the list of tasks from ServiceNow. The logged in user must have access to view these tasks (e.g., Incidents, Problems, Tickets) for them to be returned in the REST API and subsequently displayed in the 'MyWork App'.
After login, the application displays the tasks assigned to the user grouped by task type. The application uses the **Task Tracker API** to retrieve the list of tasks from ServiceNow. The logged in user must have access to view the tasks (such as Incidents, Problems, Tickets) for these tasks to be returned in the REST API and subsequently displayed in the 'MyWork App'.

**> REST API Call:** Get user details (Table API)
```
@@ -128,26 +128,26 @@ POST /api/x_snc_my_work/v1/tracker/task/{task_id}/comment
{"comment":"Hello, world!"}
```

### Application Flow Detail
![App Flow](/images/node_flow.png)


### Client side
#### Client side
On the client side, the application uses [AngularJS](https://angularjs.org/) for client side scripting and interaction with the Node.js server. Each page is associated with an [Angular controller](https://docs.angularjs.org/guide/controller).

| Page | Controller | Details |
|---------------|-----------------------|-----------------------|
| login.html | loginController.js | Collect user instance and credentials |
| task_list.html | taskListController.js | List of tasks assigned to the user |
| task_detail.html | taskDetailController.js | Details of a single task, view and add comments |
| login.html | [loginController.js](/public/js/loginController.js) | Collect user instance and credentials |
| task_list.html | [taskListController.js](/public/js/taskListController.js) | List of tasks assigned to the user |
| task_detail.html | [taskDetailController.js](/public/js/taskDetailController.js) | Details of a single task, view and add comments |

### Server side
The Node JS server has 2 components: dispatchers and sn_api module.
#### Server side
The Node.js server has 2 components: dispatchers and sn_api module.
* Dispatchers (`<this repo>/dispatcher`)
* Dispatch calls to ServiceNow REST API endpoints using the sn_api module. The 2 dispatchers used by this app are detailed below
* **sn_api** module (`<this repo>/sn_api`)
* Encapsulate the details of sending REST API calls to ServiceNow

`loginDispatcher.js`: handles user authentication. The dispatcher handles call reaching /login endpoint of Node.js server.
`loginDispatcher.js`: handles user authentication. The dispatcher handles calls reaching /login endpoint of Node.js server.

|Node endpoint| HTTP Method |Details|
|--------|--------|--------|
@@ -161,8 +161,7 @@ The Node JS server has 2 components: dispatchers and sn_api module.
| /tasks/:task/comments| GET | Uses the REST Table API to query for a task's work notes from the sys_journal_field table (`GET /api/now/v2/table/sys_journal_field`) |
| /tasks/:task/comments | POST | Uses the **Task Tracker** Scripted REST API to add a comment (work note) to a task (`POST /api/x_snc_my_work/v1/tracker/task/{task_id}/comment`) |


### Session management
#### Session management
Two types of sessions are managed by the application, between:
* Browser and Node.js web application
* Node.js server and ServiceNow instance
@@ -185,9 +184,9 @@ Here is an equivalent sample curl request. It saves the response cookies in a ne
$ curl --verbose --request GET \
--header "Accept: application/json" \
--user "john.doe:password" --cookie cookies.txt --cookie-jar cookies.txt \
"https://myinstance.service-now.com/api/now/table/sys_user?user_name=john.doe&sysparm_fields=user_name,first_name,last_name,sys_id"
"https://myinstance.service-now.com/api/now/v2/table/sys_user?user_name=john.doe&sysparm_fields=user_name,first_name,last_name,sys_id"
> GET /api/now/table/sys_user?user_name=john.doe&sysparm_fields=user_name,first_name,last_name,sys_id HTTP/1.1
> GET /api/now/v2/table/sys_user?user_name=john.doe&sysparm_fields=user_name,first_name,last_name,sys_id HTTP/1.1
> Authorization: Basic am9obi5kb2U6cGFzc3dvcmQ=
> Host: myinstance.service-now.com
> Accept: application/json
2 changes: 1 addition & 1 deletion common/usage.js
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ module.exports = {
processArgs: function(filename) {
// helper function for printing usage info
function printUsageAndExit() {
console.log("\nUsage: node " + filename + " [ -h ] [ -p <port> ] [ -v ]");
console.log("\nUsage: node " + filename + " [ -h ] [ -p <port> ] [ -v ]");
console.log(" -h, --help Show this usage help");
console.log(" -p <port>, --port=<port> HTTP server listen port (default 3000)");
console.log(" -v, --verbose Verbose HTTP output");
2 changes: 1 addition & 1 deletion dispatcher/taskDispatcher.js
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ module.exports = {
// the successful body message should contain all the tasks as a JSON message.
serverResponse.status(response.statusCode).send(body);
} else if (response.statusCode == 400) {
serverResponse.status(response.statusCode).send('Task service is not found installed on instance');
serverResponse.status(response.statusCode).send('The Task Tracker API is not found on this instance. Did you install the "My Work" Update Set?');
} else {
serverResponse.status(response.statusCode).send(
'Error occured while communicating with ServiceNow instance. ' + response.statusMessage);
2 changes: 1 addition & 1 deletion public/js/taskListController.js
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ myTasksControllers.controller('taskListCtrl', ['$scope', '$rootScope', '$window'
$scope.loadingTasks = false;
}).error(function(data, status, headers, config) {
$scope.loadingTasks = false;
$location.url("/login");
$scope.errorMessage = data;
$scope.$apply();
});
}
2 changes: 1 addition & 1 deletion public/view/task_list.html
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ <h4>My Tasks</h4>
</div>

<!-- if there are no tasks displays an info message -->
<div ng-show="!loadingTasks">
<div ng-show="!loadingTasks && !errorMessage">
<div class="row" ng-if="tasks|isEmpty">
<div class="col-md-12 alert alert-info text-center " role="alert ">
Nice Job! It looks like you don't have any tasks in your queue
8 changes: 8 additions & 0 deletions test/tasksTest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/*
Copyright © 2016 ServiceNow, Inc.
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/*
* This is a test script which shows how to use ServiceNow api, from a client code to communicate
* with a ServiceNow instance.