ServiceNowにおいてJavaScriptによるコーディングを伴う機能、すなわちClient-side scripting(クライアントサイドスクリプト)であるClient Script(クライアントスクリプト)、UI Policy(UIポリシー)などや、Server-side scripting(サーバーサイドスクリプト)であるBusiness Rule(ビジネスルール)、Script Include(スクリプトインクルード)などについて、各機能のイメージ、概要、使い分けについて解説します。
基本
まずは、ServiceNowのScriptingにおける基本的な事項を説明します。
その前に、「そもそもServiceNowってノーコードなんじゃないの?コード書けなきゃいけないの?」という方は、下記の記事に書いた、ServiceNowにおける開発とは何か、をご覧いただければと思います。
Client-side scripting(クライアントサイドスクリプト)とServer-side scripting(サーバーサイドスクリプト)
ServiceNowはクライアントサーバシステムですので、クライアントサイド=ウェブブラウザからのアクセスを受けて、サーバーサイド=インスタンスがウェブページを返します。開発者は、クライアントサイドとサーバーサイドにおいて、様々なタイミング、条件で任意の処理を行うためのスクリプトを書くことができます。
スクリプトはJavaScript + ServiceNowのAPI(クラスライブラリ)で書く
ServiceNowにおけるスクリプティングでは、JavaScriptとServiceNowのAPIを組み合わせて処理を記載します。
ServiceNowには様々なAPIがあり、APIと聞いて恐らく多くの方がイメージするWeb APIもあるのですが、スクリプティングで使うAPIはクラスライブラリに近いです。例えば、GlideRecord APIはデータベース操作のためのラッパークラスです。このAPI=クラスを用いることで、SQLを書くことなく、JavaScriptの文法を用いてデータベースを操作することができます。
// データベースを操作するためのGlideRecord API = クラスのインスタンスを生成(対象は'incident'テーブル)
var incident = new GlideRecord('incident');
// query()メソッドで'incident'テーブルのレコードをクエリ(取得)
incident.query();
なお、クライアントサイドだろうがサーバーサイドだろうが、どちらもJavaScriptです。
JavaScriptのサポートバージョン
クライアントサイドスクリプトの場合は、JavaScriptのサポートバージョンはクライアント=ウェブブラウザに依存します。
サーバーサイドスクリプトの場合は、2022年リリースのTokyoバージョンよりECMAScript 2021 (ES12)が標準でサポートされるようになりました。それ以前のバージョンではES5までしかサポートされていなかったため、ServiceNowの多くの標準のスクリプトはconstによる定数の宣言、letによる変数の宣言, アロー関数などが使われていない古い文法で書かれたものになっています。
ソースファイルという概念はなく設定画面の所定の位置にスクリプトを書く
コーディング・スクリプティングと聞くとソースファイルを作るイメージを持つ方も多いかもしれませんが、ServiceNowにおけるスクリプティングはソースファイルを作るのではなく、ウェブブラウザから設定画面にアクセスし、決まった項目にコードを書きます。
このように、ServiceNowにはいくつかの「スクリプトを用いてユーザが任意の処理を組み込むことのできる機能」が用意されており、これらの機能の中でスクリプトを書きます。そのため、システムのソースコードを書き替えて根本からつくりかえてしまう、といったことはできません。とはいえ、このように制約はあるものの、様々な機能やAPI(クラス)が存在していて、創意工夫を凝らす余地はあるのでご安心ください。
ここからは、具体的な「スクリプトを用いてユーザが任意の処理を組み込むことのできる機能」の種類とそれらのイメージ・概要・使い分けについて説明します。
Client-side scripting(クライアントサイドスクリプト)
クライアントサイド=ウェブブラウザで動作するスクリプトを組み込むことのできる機能について紹介します。クライアントサイドスクリプトは一般的なJavaScriptの使われ方に近く、ブラウザ上でフォームの項目を表示/非表示にしたり、バリデーションによって警告メッセージを出すなど、画面上に何らかの変化を起こすために使われます。
クライアントサイドスクリプトでは、ユーザが画面上に入力した情報や画面上で行った操作を利用した処理ができますが、サーバ側にある情報は基本的に利用できません(クライアントサイド⇔サーバーサイド間での情報のやり取りについては後述します)。
Client Script
Client Scriptを用いることで、フォームやリストに次のような処理を埋め込むことができます。
- ある項目の値が変更されたとき、入力された値をチェックし、不適当な値の場合はエラーメッセージを表示
- フォームが送信されたとき、複数の項目の値の整合性をチェックし、必要に応じてエラーメッセージを表示しフォーム送信を中断する
UI Policy(Script)
Client Scriptを用いることで、フォームやリストに次のような処理を埋め込むことができます。
- セレクトボックス型の「カテゴリ」項目で”その他”が選ばれたとき、テキスト型の「その他詳細」項目を表示して入力を必須にする
- ある項目の値が削除された(空になった)とき、別のある項目の値も削除する
UI Policyは、基本的にはノーコードで条件に応じた項目の表示/非表示などを制御するための機能であり、上述の例のような処理であればノーコードで実装できますが、スクリプトを書いてClient Scriptと同様の複雑な処理を実装することもできます。
(発展)Client ScriptとUI Policyの使い分け
Client Scriptの機能はUI Policy(Script)の機能を包含しており、UI Policy(Script)の機能はUI Policy(no-code)の機能を包含しているため、やりたいことに対してどちらでも実装できることがあります。これらの使い分けについて、私の経験上、次の方針で使い分けるのがよいです。
- UI Policy(no-code)実装できるものはすべてUI Policyで実装する
- それ以外はすべてClient Scriptで実装する。つまりUI Policy(Script)は使わない
理由は次の2点です。
(方針1の理由)ノーコードよりもスクリプトを書く方がバグを埋め込みやすい
(方針2の理由)UI PolicyでScriptを書くことを許容すると、Scriptでしか実装できない要望に対して、Client ScriptとUI Policyのどちらで実装したかが探さないとわからなくなり、保守性が下がる
UI Action(Client-side)
UI Actionは、フォームやリスト上に”ボタン”や”リンク”を表示し、それが押下されたときに実行されるスクリプトを埋め込むための機能です。UI Actionは、クライアントサイドスクリプトもサーバーサイドスクリプトも埋め込むことができますが、クライアントサイドスクリプトとしては、次のような処理を埋め込むことができます。
- “削除”ボタンが押下されたときに、「本当に削除しますか?」というポップアップを表示する
UI Script
UI Scriptはクライアントサイドスクリプトの共通処理を再利用可能なパッケージ化(共通化)するための機能です。上述のクライアントサイドスクリプトを埋め込む機能の中から呼び出すことができます。
Server-side scripting(サーバーサイドスクリプト)
サーバーサイド=インスタンスで動作するスクリプトを組み込むことのできる機能について紹介します。サーバーサイドスクリプトは、インスタンス上で動作するため、データベースに対する操作が可能になります。特定のレコードが更新された際に、関連するレコードを連鎖的に更新する、といった処理を行うために使われます。
サーバーサイドスクリプトはデータベースを操作できる一方で、ユーザが画面上に入力したがまだサーバに送信されていない情報を利用することはできません。(クライアントサイド⇔サーバーサイド間での情報のやり取りについては後述します)。
Business Rule
Business Ruleは、主にデータベース操作の前後で動作するスクリプトで、SQLでいうTriggerのようなものです。Business Ruleを用いることで、次のような処理を埋め込むことができます。
- 「担当者」項目が設定された際に、ServiceNow上でその担当者の上長に設定されているユーザを「承認者」項目に自動で設定する
- レコードが挿入される前にレコードのチェックを行い、問題があればエラーメッセージを表示し、レコードの挿入を中止する
- レコードが更新されたとき、そのレコードに紐づく別のレコードを連鎖的に更新する
Business RuleはUI Policyと同じく簡単な処理であればノーコードで実装することができますが、多くの場合スクリプトを伴います。
UI Action(Server-side)
前述のように、UI Actionは、フォームやリスト上に”ボタン”や”リンク”を表示し、それが押下されたときに実行されるスクリプトを埋め込むための機能で、クライアントサイドスクリプトもサーバーサイドスクリプトも埋め込むことができます。サーバーサイドスクリプトとしては、次のような処理を埋め込むことができます。
- ボタンが押下されたときに、フォームに入力された内容をデータベースの指定のテーブルに挿入する
- ボタンが押下されたときに、外部システムとの連携を行い、フォームに入力された内容を送信する
標準で用意されている、”Submit(送信)”ボタン、”Update(更新)”ボタン、”Delete(削除)”ボタンはUI Actionで作られています。
Script Action
特定のイベントが発生した場合に処理を起動したい場合に使います。イベントは、ServiceNowの標準で定義されていて特定の条件を満たすと自動で生成されるものと、ユーザが定義しサーバーサイドスクリプト内で生成したものがあります。
Script Actionを用いて、次のような処理を埋め込むことができます。
- ログイン失敗のイベントが発生したとき、ログイン連続失敗回数を1つ増やす(標準の例)
Scheduled Job
Scheduled Jobは名前の通り予め設定されたタイミングで処理を実行する機能です。タイミングは、オンデマンド(運用者が実行ボタンを押したときに実行)や日次・月次などの定期実行が指定可能です。
Scheduled Jobを用いて、次のような処理を埋め込むことができます。
- 日次で未承認の承認レコードをチェックし、承認者にリマインドのメール(チャット)を送信する
なお、ある処理をスケジュール実行したい場合、Flow desginerを用いて可能な限りノーコードで作るべきなので、まずはFlow designerでの実装を検討しましょう。
その他のサーバーサイドスクリプトを埋め込むことのできる機能
ここまで、特定の条件やタイミングでサーバーサイドスクリプトを実行するための機能を紹介してきましたが、上記以外にも様々な機能においてサーバーサイドスクリプトを埋め込むことができます。よく使うものを紹介します。
Access Control List(ACL)
ServiceNowのデータ操作権限を制御する仕組みであるAccess Control List(ACL)において、データへの操作(CURD)を許可する条件をスクリプトを用いて指定することができます。
詳細は下記の記事を参照ください。
Transform Map(変換マップ)
ファイルや外部システムからデータを取り込む機能であるTransform Map(変換マップ)において、スクリプトを組み込むことで、データ取り込み前にデータの形式チェックを行うことなどができます。
Reference(参照)型項目のReference qualifier(参照修飾子)
特定のテーブルから値を選択させるReference(参照)型項目において、選択肢となるレコードを絞り込む条件をスクリプトで指定することができます。
Default value(デフォルト値)の設定
項目のデフォルト値の設定において「日付型の項目に今日の日付を設定する」など、スクリプトを用いて動的にデフォルト値を設定することができます。
Incident(テーブル)を始めとしたTask(タスクテーブル)のNumber(番号)項目の自動採番も、Default valueに設定されたスクリプトによって行われています。
Flow designer
ワークフローを作成する機能であるFlow designerは、基本的にノーコードで自動化ワークフローを作成するための機能ですが、必要に応じてワークフロー中の任意の個所にスクリプトを埋め込むことができます。
Script Include
UI Scriptはサーバーサイドスクリプトの共通処理を再利用可能なパッケージ化(共通化)するための機能です。上述のサーバーサイドスクリプトを埋め込む機能の中から呼び出すことができます。
クライアントサイドスクリプトの共通化機能であるUI Scriptと異なる点は、一つのScript Includeは一つのクラスとして定義されるという点です。
Script Includeについては下記の記事で詳しく説明しています。
(発展)UI ActionとBusiness RuleとClient Script(onSubmit)の使い分け
サーバーサイドスクリプト関連で使い分けが難しいのが、フォーム送信時に入力内容のバリデーションをかけたいときにUI Actionを用いるか、Business Ruleを用いるか、もしくはClient Script(onSubmit & 後述のGlideAjaxと組み合わせ)を用いるか、です。
私の経験上、次の方針で使い分けるのがよいと考えています。
- UI Action(ボタン)でバリデーションは行わない
フォーム送信を行うUI Action = “Submit(送信)”ボタンにバリデーションを入れる場合、そのテーブルにおいてSubmitボタンを上書きする必要があり、OOTBを上書きしてしまうため、UI Actionはあくまでボタン押下をトリガとするテーブルCRUDや、その前の確認のポップアップを出す機能留める - バリデーションの結果に応じて、フォーム送信前に「〇〇ですが送信しますか?」といった警告を出したい場合は、Client Script(onSubmit)を用いる
こちらは仕組み上Business Ruleではできないため、一択になります - データの更新経路がフォーム以外もある場合はBusiness Ruleを用いる
Client Scriptはクライアント側でしか動かすことができないため、スクリプト経由でのデータの更新が考えられる場合は、Business Ruleが適しています - その他の場合はデータ更新経路、開発工数の増加量、設計方針の一貫性などを軸に判断
その他の場合は、どちらが適切な場合もあると考えます。その場合の判断軸を2つ示します。一つ目は開発工数の増加量です。Client Scriptを用いる場合、Script Includeを作ってGlideAjax呼び出す必要があるため、開発工数が増加する可能性が高いです。二つ目は設計方針の一貫性です。上述の方針2, 3を考慮して既に作成したものとの一貫性が高い方を採用するという手もあります。
Client-side⇔Server-side間でのデータのやり取り
Client-side⇔Server-side間でデータをやり取りする方法を説明します。
GlideAjax – Client-sideからServer-side scriptを呼び出す
クライアントサイドスクリプトでは、データベースの情報が参照できません。しかし、フォーム上で値が入力された場合に、データベース上の既存のデータと照合してバリデーションを行いたい場合などがあります。
このような場合は、GlideAjaxという機能を使うことで、クライアントサイドスクリプトからサーバーサイドスクリプト(Script Include)を呼び出し、その結果を用いてクライアントサイドで処理を行うことができます。
GlideAjaxについては下記の記事で詳しく説明しています。
GlideFormScratchpad – Server-sideからClient-sideに値を渡す
GlideAjaxと比べると利用頻度は落ちますが、やりたいことにぴったりフィットすることがあるので紹介します。サーバからクライアントにウェブページを送信する際にGlideFormScratchpad(g_scratchpad)と呼ばれるデータ領域に予めサーバーサイドスクリプトからデータを格納しておくことで、クライアントサイドスクリプトからそのデータを参照することができます。
GlideAjaxと比べ、サーバサイドへのアクセスが不要になるため、画面の応答性が向上します。
GlideSessionのset/put/getClientValue() – ページを跨いでセッション中維持されるデータ領域へアクセス
GlideSessionのsetClientValue()/putClientValue()/getClientValue()関数を用いて、ページを跨いでセッション中維持されるデータ領域へアクセスすることができます。
具体的なユースケースとしては、Business RuleやUI Actionにおいてページのリダイレクトを行い、リダイレクト先のページで用いる情報を予めセッション内に保持しておき、リダイレクト先のページのクライアントサイドスクリプトから参照する、といったことが実現できます。
(同じようなことを実現するために、一度System Propertyに保存したり、フォーム上に隠しフィールドを作る方法もあります)
(おまけ)”Glide”って何?
ServiceNowでスクリプティングをしていると、GlideForm、GlideRecord、GlideAjaxなど、API(クラス)名の頭に”Glide”が付いています。これは、ServiceNowの創業時の社名であるGlidesoftから取られたそうです。じゃあGlidesoftの由来は?というと、私が調べた限りではわかりませんでした。ご存じの方は教えてください。
以上です。
コメント