ServiceNowのInbound REST Messageを作成して動作確認する

# 概要

ServiceNowではバッチ処理などを定期的にキックする仕組みがあるが、ServiceNowのスケジュール処理を使用せずに、JP1などの外部のタスクスケジュール管理ソフトから起動したい場合に、ServiceNowのInboud REST Messageを使う。例えばJP1からシェルを実行し、シェルからcurlなどのコマンドで、ServieNowのInbound REST Messageを起動するような使い方を想定する。
また、１つのURLで複数の異なる処理を呼び出し可能とするため、クエリーパラメーターのfunctionnameで処理名を設定し、POSTメッセージにその処理に渡す引数をJSONにより設定する仕様とした。

なお、準備として下記の「Sales」Table作成と、「updateProductPrice」Scrip Includeを作成しておく。

[ServiceNowでTableを作成する](https://qiita.com/sukkyxp/items/46a06665131b37ce3f2b)
[ServiceNowのScript IncludeでGlideRecordを使ってレコード一括更新を行う](https://qiita.com/sukkyxp/items/04f6308933e79e5c6a2e)

# 手順

## Inbound IntegrationsのScripted REST APIを追加

Studioを使ってCreate Application FileでInbound IntegrationsのScripted REST APIを追加する。

![AddInboundRestAPI.png](https://qiita-image-store.s3.amazonaws.com/0/197947/c5c511c6-e102-19bf-3673-936a6ee93734.png)


一旦、Nameを入力してSubmitで保存すると、Resourcesのレコードリストが表示される。
なお、このときAPP IDの値を使って、REST APIを起動時のURLのパスが生成される。生成されたURLはBASE Api pathに表示されている。

![ScriptedRestService.png](https://qiita-image-store.s3.amazonaws.com/0/197947/f735564d-2e0b-964f-9998-0b74b962c964.png)


## Query Paremeterの追加

Query Parametersタブに切り替えて、「New」をクリックで次の通りQuery Parameterを追加する。

![QueryParameterRecordList.png](https://qiita-image-store.s3.amazonaws.com/0/197947/61564007-51d5-9e73-0e5b-0d5d738b0c6f.png)

今回は、functionnameをクエリーパラメーターとして追加している。

![QueryParameterSetting.png](https://qiita-image-store.s3.amazonaws.com/0/197947/1f073fff-f4c4-c658-c865-2bbd8e045262.png)


## Scripted REST Resourceを追加

ResourcesのレコードリストのNewをクリックしてScripted REST Resourceを追加する。

次の通り入力する。

|項目 |値 |
|---|---|
|Name | callsalesapi |
|HTTP Method|POST|
|Relative Path| / |

また、こちらにもQuery Parameterを追加する。

![queryparameter_at_resource.png](https://qiita-image-store.s3.amazonaws.com/0/197947/fb9c2ce8-2184-c163-d7d2-6a6afa49120c.png)

これで、functionnameをクエリパラメーターとしてスクリプトで受け取ることが可能となる。

次にScriptに次の通り入力する。

```javascript
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

	var queryParams = request.queryParams; 
	var functionName = queryParams.functionname;
	var requestBody = request.body;
	var requestData = requestBody.data;
	
	gs.info('functionname = ' + functionName);

	
	if ( functionName == 'updateproductprice' ) {
		var updateProductPriceObj = new updateProductPrice();		
		updateProductPriceObj.update(requestData);
	}


})(request, response);
```

クエリーパラメーターのfunctionnameで分岐して呼び出す処理を決めることを想定している。
ここで、Script Includeで作成した、updateProductPrice.updateを起動している。
updateの引数には、POSTで次のようなJSONメッセージのオブジェクトを渡すことを想定している。

```javascript

{"product":"PPP","unitprice":"500"}
```

updateProductPrice.updateは引数の情報を元にSalesテーブルを一括更新する処理を実行する。

ここまでで、Inbound REST Messageの作成は完了だ。
次に作成したメッセージを実際に試して動作確認してみる。

# 動作確認手順

## 動作確認画面の起動

Script Resourceの設定画面の中段の「Related Links」の「Explorer REST API」をクリックする。

![ClickExplorerApi.png](https://qiita-image-store.s3.amazonaws.com/0/197947/95cd348a-ffb3-38ec-5ff3-139588748506.png)

この画面から作成したREST APIを起動できる。

## Explorer REST APIの設定

functionnameに「updateproductprice」を入力する。
Request Bodyの「Add a field」をクリックして次の通りPOSTメッセージを生成する。

![RequestBody.png](https://qiita-image-store.s3.amazonaws.com/0/197947/992ea546-453f-a7d8-2f21-8222ef35054a.png)

名称と値を入力していくと、自動的にPOSTするJSONメッセージが作成される。

## いよいよ実行

ここまでExplorer REST APIの設定ができたら、Sendをクリックして実行する。
確認メッセージが表示されるので、「OK」をクリックするとREST APIを起動してその応答結果が画面に表示される。
成功すれば、「200」が表示されているはずだ。失敗の場合の「500」でエラーメッセージが表示される。
下記は呼び出し成功の場合の例だ。

![LOG1.png](https://qiita-image-store.s3.amazonaws.com/0/197947/87ae33eb-b817-82e5-bb78-f88143b64243.png)

![LOG2.png](https://qiita-image-store.s3.amazonaws.com/0/197947/9b3d5cfd-f9a0-1656-7679-f3fd4a982f7a.png)

クエリーパラメーターのfunctionnameが設定されていること。
POSTメッセージにJSONメッセージが送信されていることが画面から分かる。

# 最後に

複数のREST APIを用意したい場合に、URLのパスで起動するAPIを分けるか、URLは同じで、今回のようにクエリーパラメーターで呼び分けるか、もしくは他にもっとスマートな方法がないか検討している。
今回のやり方では、APIを追加するたびに、if elseif の分岐処理を追加していく必要がある。

Javaであれば、クラス名を文字列で受け取りリフレクションを使ってクラスのインスタンスを生成することで、if文を追加せずに、起動するクラスを呼び分けることが可能だが、JavaScriptもしくはServiceNowの仕組みで同等の事が出来ないかを調べていく予定だ。