見出し画像

ServiceNow GraphQL: スキーマ公開する (準備としてカスタムアプリ作る)

スキーマ公開はIncidentを使おうかと思いましたが、もう少しコンパクトにカスタムアプリでやってみようと思います。
全データ公開とかカジュアルにやりたいのですが、incidentではデータ量が多すぎる。

アプリケーションを作る

スコープアプリと言って、固有のネームスペースを区切って共通部分や他のアプリケーションとは別に扱えるようにしたものを作ります。
一個のマイクロサービスのようなものと思ってください。

App Engine Studioなるものもあり、Excelからテーブルを起こすことができるように見えて便利そうですが、今回はただのStudioを使います。
画面左のナビゲーションの検索フィールドにstudioと入力、結果のうちSystem Applications > Studioをポチ。

Studio

[Create Application] をポチ。

Create Application

[Let's get started] をポチ。

Let's get started

よしなに埋めます。
Advanced SettingsのところはScopedにします。スコープアプリ (Scoped Application) を作るからです。
最後に右下の [Create] をポチ。

App name

次の画面はこのアプリにアクセスするユーザーのロールを作成します。
既存ロールを使ってもいいですが、今回はロールを新しく一つ作成することにします。
Create new roleから任意のロール名を指定し、左下の[Continue] をポチ。

ロール作成

どちらの画面を作りますかと聞かれたのでお好みの方を選んで [Continue] をポチ。以下の図は両方選んだところ。

画面

テーブルは既存のものを使うかどうかと聞かれたので、白いボタンの [Create new table] をポチ。

Create new table

Excelのアップロード、既存テーブルの拡張、新規作成があります。ここは新規作成 (Create table from scratch) を選択して [Continue] をポチ。

Create table from scratch

とりあえずこんな感じに作ってみます。メインのテーブルはmybooks, 参照先のテーブルはauthorsとpublishersがあります。
ちなみに作成するときは参照先のテーブルの方から作った方が面倒くさくなくていいです。メインのテーブルで参照フィールドを作成するとき、参照先テーブルがないと作れないのです。

[Add a new field] をポチ。

Add a new field

入力フィールドに必要事項を入力します。
見当たらないフィールドは右の赤枠の部分をクリックすると表示されます。

  • Field Label: 画面上のラベル名

  • Field name: フィールド名、DBテーブルの方に使うやつ

  • Field Type: データ型

  • Character Limit: 長さ

  • Display: 画面に表示するかどうか

  • Mandatory: 必須項目かどうか

フィールド作成

必要なものが全部できたら右下の [Continue] をポチ。

Table labelにテーブルの名前をつけます。
ここではIDを自動採番にしたいので、Auto-numberにチェックをつけます。
よろしければ [Continue] をポチ。
ちなみにIDであるNumber属性は指定しなくても勝手に作ってくれました。

注: 諸事情によりこのスクショとった後テーブルを「books」として作り直してます。

テーブル名

少し時間が経って成功 (Success) と出るので、[Continue] を押すとこの画面に戻りますので必要なものを作ります。
作り終わったら [Done with tables] をポチ。

Done with tables

アプリケーションのカスタマイズができる画面が出ます。特にカスタマイズはしないので、[Start] で選択して内容確認、[Create] をポチ。
二つとも終わったら [Done with Apps] をポチ。

Done with apps

そろそろおしまいです。[Done] をポチ。

Done

ここで一段落。
念のためStudio画面を開いておきたいです。
作成したアプリをポチ。

アプリ選択

もしフィールドの追加作成が必要ならStudioからできます。

データを適当に作る

Studioは別タブで開いているはずなので元のServiceNowの画面に戻り、画面をリフレッシュします。
リフレッシュ後は画面左のナビゲーションに今作ったアプリが表示されますので、適当にデータを作成します。

GraphQLのスキーマを設定する

さてここからやっとGraphQLのスキーマです。
Studioの中には設定が見当たらないので、元のServiceNowのUIの方で設定します。

今自分が作業しようとしているスコープがわかるようにする

スコープアプリを作ったんですが、他のアプリケーションとの境界線がはっきりとしています。
このアプリケーションに対してアクセスするようなものを作るには、同じスコープの中に設定を作成するか、あるいは別のスコープや共有エリア (グローバル) に作ってもいいけどそこに対して今回のアプリがアクセス権を許可するようにします。

今回は同じスコープの中に設定を作成します。

という作業をするので、「今自分がどこのアプリケーションスコープにものを作ろうとしているかがわかる」という状態が欲しいです。
画面上にアプリケーションピッカーを表示させましょう。

画面右上の歯車マークをポチ。

設定の歯車マーク

左のメニューから [Developer] を選択、右画面で [Show application picker in header] を画像の通りにするとONになります。

アプリケーションピッカー表示

画面の歯車マークの並びに自分が今作業しようとしているアプリケーションのスコープが表示されたら完了。
ここが自分のアプリケーションになっているか確認します。

アプリケーションピッカー確認

余談ですが本当にアプリケーションを開発する場合は、移行資産のパッケージ (Update Set) の設定のピッカーも表示します。
今回は不要なので割愛。

(やっと) GraphQLのスキーマを作る

設定は次の3点セット。

  • スキーマ

  • Scripted Resolver

  • Resolver Mapping

製品マニュアルにはScripted ResolverはOptionalと書いてあるように見えるのですが、どう考えてもスキーマの記述の段階では特定のテーブルに紐づいていなかったので、スクリプトは書く必要があります。多分。
念のためスキーマのプロパティに存在しないプロパティを指定してみても全くエラーは出なかった。テーブルを指定していないので当たり前です。
そのうち公式さんがマニュアル更新してくれると思います。

Scripted ResolverはDBから取り出したデータをスキーマに渡すために使用します。

スクリプトに使用するライブラリはこちら。
ServiceNowではスクリプトに使用するライブラリもAPIと呼ぶ、少し古いスタイルの「API」という言葉の使い方をするので、APIとはHTTP上を行き来するものと思っていると迷子になります。

statusがavailableな本の一覧を持ってきてみましょう。

クエリ部分。

query {
  x805160MyBooks {
    mytestschema {
      availablebooks {
        id
        number
        name
        author
        publisher
        description
        status
      }
    }
  }
}

レスポンス

{
  "data": {
    "x805160MyBooks": {
      "mytestschema": {
        "availablebooks": [
          {
            "id": "156e8e7a1b3ec110b66f55f0604bcba0",
            "number": "MYB0001002",
            "name": "BASARA",
            "author": "田村由美",
            "publisher": "小学館",
            "description": "",
            "status": "Available"
          },
          {
            "id": "3dce86f21b7ec110b66f55f0604bcb57",
            "number": "MYB0001004",
            "name": "Implementing Domain-Driven Design",
            "author": "Vaughn Vernon",
            "publisher": "Pearson Education, Inc.",
            "description": "\"For software developers of all experience levels looking to improve their results, and design and implement domain-driven enterprise applications consistently with the best current state of professional practice, Implementing Domain-Driven Design will impart a treasure trove of knowledge hard won within the DDD and enterprise application architecture communities over the last couple decades.\"\r\n\r\n–Randy Stafford, Architect At-Large, Oracle Coherence Product Development",
            "status": "Available"
          },
          {
            "id": "6bcfcef21b7ec110b66f55f0604bcba0",
            "number": "MYB0001005",
            "name": "北斗の拳",
            "author": "原哲夫",
            "publisher": "集英社",
            "description": "",
            "status": "Available"
          }
        ]
      }
    }
  }
}

ではまずはスキーマ。
プロパティのところですが、コロンの左側がAPIの中で取り扱うプロパティ名で、必ずしもデータベースのスキーマにある情報と一致しなくてもいいものです。右側 @source 以下がスクリプトの中から取り出したフィールドの名前。

schema {
    query: Query
    mutation: Mutation
}

type Query {
   availablebooks: [AvailableBooks]
}

type Mutation {
    #implement here...
}

type AvailableBooks {
	id: ID! @source(value: "sys_id.display_value")
	number: String! @source(value: "number.display_value")
	name: String @source(value: "name.display_value")
	author: String @source(value: "author.display_value")
	publisher: String @source(value: "publisher.display_value")
	description: String @source(value: "description.display_value")
	status: String @source(value: "status.display_value")
}

ServiceNow固有の部分と思いますが、スクリプトで単純にレコードを取ってくるだけだと、各フィールドの値にvalueとdisplay_valueの2つがあるので、どちらかを選択する必要あり。

スキーマ画面の下、タブ群の中から [GraphQL Scripted Resolver] タブに以下を挿入しました。

Scripted Resolver

コード部分には「x_805160_my_books_mybooksのテーブルからstatus=availableな本の一覧を全フィールド込みでください」と書いてあります。
Studioでテーブル名を指定する時に入力した名前はbooksでしたが、これはラベル扱いになっています。実際には重複を避けるためにシステム内で重複しないテーブル名が付与されており、スクリプトの中ではラベルの方ではなく重複なくつけられたTable nameを指定する必要があります。

(function process( /*ResolverEnvironment*/ env) {
	
	var books = new GlideRecord('x_805160_my_books_mybooks');
	
	books.addQuery('status', 'available');
	books.query();
	
    return books;

})(env);

最後にまたタブ群から [GraphQL Resolver Mapping] を登録します。
これはスキーマ内に定義されたavailablebooksフィールドとScripted ResolverのAvailable Resolverの関連付けをしています。

Resolver Mapping


この記事が気に入ったらサポートをしてみませんか?