WebPerformer V2.5 UIエディタでREST APIを利用する

はじめに

こんにちは。エヌデーデー関口です。
WebPerformer V2.5 の新機能「UI エディタ」についての紹介 3 回目です。
今回は「UI エディタ」から REST API を呼び出してアプリケーションを作る方法をご紹介します。

想定される読者

  • WebPerformer V2.5 での開発は未経験
  • 外部に公開されている REST API などを使ってアプリケーションを開発したい
  • JavaScript や JSON を使ったことがある

作成するアプリケーション

今回は簡易なユーザー登録画面を「UI エディタ」を利用して作ります。
住所の検索と、Slack への登録通知、データの登録が行えるようなものとします。

ユーザー一覧画面と詳細画面の UI

登録されているユーザーの一覧と、それぞれのユーザーの登録画面は次に示すような画面とします。

ユーザー一覧画面
ユーザー登録画面

利用する API について

今回の2つの UI で利用する3つの REST API について説明します。

PostcodeJP

PostcodeJPは郵便番号や住所の一部から住所入力を補助する値を返すことができる REST API サービスです。EC サイトなどで利用する想定の有料プランがありますが、開発など1日あたりの呼び出し回数が少ないようであれば無料プランで利用することが出来ます。今回は郵便番号の値を元に住所の検索を行う処理で利用します。

Slack の Web API

チャットツールで有名な Slack です。Slack は REST API を公開しており外部のサービスと連携することが比較的簡単に行えるようになっています。今回はデータが保存されたタイミングで予め用意してあるテスト用のワークスペースにボットから通知を投げるという動きにしてみましょう。

Apigee を使った カスタム API

Apigeeは Web API を管理するためのサービスとして誕生し、現在は Google Cloud Platform(GCP)に買収、統合されています。GCP に統合されてはいますが、GCP 専用の API ゲートウェイ/マネジメントサービスという訳ではなく、オンプレミスのレガシーシステムを Web API として公開したり、他のクラウドサービスの API を透過的に利用することが出来る柔軟性のあるサービスです。今回は GCP の Firebase という NoSQL データベースに値を入れる処理と、氏名で検索する処理を利用してみます。

住所検索 API の実装

PostcodeJP の仕様

PostcodeJP へのアカウント登録などは済ませておき、API を利用するためには、API キーを発行する必要があります。

PostcodeJPのAPIキー発行画面

API のリファレンスはこのページにあります。
郵便番号から住所を呼び出すには cURL コマンドの場合は、次ののような呼び出し方をします。

curl https://apis.postcode-jp.com/api/v4/postcodes/{7桁郵便番号} \
  -H "apikey: ここにAPIキーを設定"

また、そのレスポンスは JSON で次のような形式で返ってきます。(当社住所 164-0012 で検索した場合)
なお、無効な郵便番号を指定した場合は、中身が空の配列[]が返却されます。

[
  {
    "prefCode": "13",
    "cityCode": "114",
    "postcode": "1640012",
    "oldPostcode": "164",
    "pref": "東京都",
    "city": "中野区",
    "town": "本町",
    "allAddress": "東京都中野区本町",
    "hiragana": {
      "pref": "とうきょうと",
      "city": "なかのく",
      "town": "ほんちょう",
      "allAddress": "とうきょうとなかのくほんちょう"
    },
    "halfWidthKana": {
      "pref": "トウキョウト",
      "city": "ナカノク",
      "town": "ホンチョウ",
      "allAddress": "トウキョウトナカノクホンチョウ"
    },
    "fullWidthKana": {
      "pref": "トウキョウト",
      "city": "ナカノク",
      "town": "ホンチョウ",
      "allAddress": "トウキョウトナカノクホンチョウ"
    },
    "generalPostcode": true,
    "officePostcode": false,
    "location": {
      "latitude": 35.69639587402344,
      "longitude": 139.68003845214844
    }
  }
]

この呼び出し方と同じ方法を WebPerformer のユーザー詳細画面の住所検索ボタンを押した時のアクションで実装します。

ボタンのアクションフローに遷移

WebPerformer の開発画面に戻ります。ユーザー詳細画面のアクションタブを開き、左上のアクション選択を押して表示されるダイアログで、住所検索のボタンクリックを選択します。

入力データバインド設定

アクションフローが表示されるので、まずは「入力データバインド設定」を設定しましょう。ボタンを押した時に画面のzip_codeという項目の値をvar_zipcodeという変数に入れるということにします。

REST データ処理設定

次に左ペインから「REST データ処理」をドラッグ&ドロップします。

REST データ処理の STEP 設定を見てみましょう。

STEP設定(その1)

STEP 設定の「リクエスト」という所では、メソッドと URL を指定します。マニュアルには詳しく記載が無いのですが、URL には JavaScript で解釈できる文字列として記述しなければならないという点に注意してください。

文字列を格納した変数を直接記述してもいいですし、JavaScript として文字列を返す関数を記述してもいいのですが、少々わかりにくいので、下記に例を示します。

  • https://hogehoge.com
    • 文字列であることを表すシングルクォーテーションで囲まれていないので解釈出来ない。
  • 'https://hogehoge.com’
    • 文字列として認識する。
  • var
    • var という変数があると解釈するので、var に「https://hogehoge.com」という値が入っていればエラーにならない。
  • `https://hogehoge.com/${var}`
    • シングルクォーテーションではなく、グレイヴ・アクセントで囲むと、JavaScript のテンプレートリテラルとして、${var}の部分は変数を展開した文字列として解釈される。
  • encodeURI('https://hogehoge.com/piyo?name=たかし’)
    • 「たかし」の部分をエンコードした文字列に変換して解釈される。

それから、「HEADERS」という項目には cURL で送信したときと同様に apikey を設定しています。

最後に STEP 設定の結果として、処理の結果を出力変数addressDataに代入します。

STEP設定(その2)

REST データ処理の結果が入った出力変数は、次のような JSON 形式で返却されます。API サービスが提供している結果の JSON はdataに入っている点に注意してください。実際の値を利用する場合は、addressData.data の値を読み取る必要があります。

{
  "data": [ // レスポンスボディの値。JSON形式以外(xmlなど)の場合は文字列として格納される
    {
        "prefCode": "13",
        "cityCode": "114",
        "postcode": "1640012",
        "oldPostcode": "164",
        ・・・・・・・・・
        }
    }
  ],
  "headers": { // レスポンスヘッダーがJSON形式で格納される
        "Date": "Thu, 25 Mar 2021 06:24:35 GMT",
        "Content-Length": "970",
        "Content-Type": "application/json;charset=utf-8",
        ・・・・・・・・・
  },
  "status": 200 // HTTPステータスコードの数値
}

条件分岐設定

addressData.dataの結果が 0 件だったことを想定して条件分岐で判定を入れておきます。

分岐のフロー
分岐の条件

出力バインド設定

最後にこのフローの処理結果を「出力バインド設定」に反映します。ここでは、前段で得た出力結果addressData.dataの中身の値を UI の部品に入れるようにしています。

Slack 連携 API の実装

Slack 連携 API の仕様

Slack の API には様々な種類があるのですが、今回は特定のチャネルに Bot としてメッセージを投稿するというものを使います。Slack 側の設定などは他のサイトでも詳しく説明してあるものがありますので、「slack bot 作り方」あたりで検索してみてください。

Slack 側で Bot の設定が終わり、API を呼び出す場合、cURL コマンドの場合は次のような呼び出し方になります。

curl -X POST 'https://slack.com/api//chat.postMessage' \
--form 'token="投稿先のスペースのトークン"' \
--form 'channel="投稿したいチャネル名"' \
--form 'text="メッセージ"'

投稿後の結果は JSON で次のような形式で返ってきます。失敗している場合はokfalse で返ってきます。

{
  "ok": true,
  "channel": "XXXXXXXXXXXX",
  "ts": "1616658769.000200",
  "message": {
    "bot_id": "XXXXXXXXXXXX",
    "type": "message",
    "text": "こんにちは世界!",
    "user": "XXXXXXXXXXXX",
    "ts": "1616658769.000200",
    "team": "XXXXXXXXXXXX",
    "bot_profile": {
      "id": "XXXXXXXXXXXX",
      "deleted": false,
      "name": "Bot Service",
      "updated": 1616560454,
      "app_id": "XXXXXXXXXXXX",
      "icons": {
        "image_36": "https://a.slack-edge.com/80588/img/plugins/app/bot_36.png",
        "image_48": "https://a.slack-edge.com/80588/img/plugins/app/bot_48.png",
        "image_72": "https://a.slack-edge.com/80588/img/plugins/app/service_72.png"
      },
      "team_id": "XXXXXXXXXXXX"
    }
  }
}

POST データの送信について

Slack 連携 API は画面の「保存」を押した時のアクションとして定義します。Slack 連携 API の場合も、住所検索 API と作り方は基本的に差はありません。ただし、今回は GET ではなく POST ですのでそのやり方について説明します。
ちなみに、アクションフローは下図の様になります。

STEP の設定を見てみましょう。
「リクエスト」の「HTTP メソッド」をPOSTにします。「BODY」タブをクリックし POST で送る内容が Form 送信なので「Content type」をx-www-form-urlencodedにします。続いてパラメータとその値(文字列)を入力します。

なお、「Content type」には次の項目を選択できるので、送信内容に応じて切り替えてください。

  • application/json : json 形式の文字列(変数の json オブジェクトは JSON.stringify して送信する点に注意です)
  • x-www-form-urlencoded : param=value 形式の送信データ
  • text/plain : 上記以外の形式で送信する文字列データ
  • multipart/form-data : ファイルを送信する場合

Apigee 経由で GCP Firestore にデータを登録

Apigee の設定について書いていくと、それだけでこの記事以上のボリュームになるので今回は省きますが、オンプレにある API や他のサービスの API に認証機能を加えたり、呼び出し制限をかけたりすることが出来るため非常に便利です。こちらも開発用途で利用する程度であれば無料で利用出来ますので、試してみてはいかがでしょうか。
Apigee の呼び出し、Slack 連携 API も加えた最終的なフローは下図のようになりました。

アプリの動作確認

Apigee で検索機能なども加えた状態でアプリの動作を確認してみましょう。

検索機能の動作

名前の前方一致で検索出来るようにしてみました。

新規保存の動作

郵便番号から API を呼び出して住所を検索し、入力項目に貼り付けることができています。
保存したときに新たに Firestore にレコードが追加されていることがわかるでしょうか。
また、Slack への投稿も行われています。

更新の動作

こちらも保存したとき Firestore の内容が変更されているのがわかるでしょうか。
Slack への投稿も新規保存と同様に行われています。

おまけ

必須入力の仕様

ところで、UI 入力項目部品で「必須」のチェックを入れているものがありますが、画面上に複数のボタンがあり、それぞれのアクションで必須の捉え方が違うケースがあります。
今回の画面のケースであれば、「住所検索」の場合に「氏名」は必須ではありませんし、「保存」の場合は「必須」設定してる部品は全て必須としたいはずです。
では、ボタンを押した時の必須の判断はどのようになっているかというと、アクションフロー側の「入力バインド設定」で変数にバインドしているか否かで判断しています。
本来は考えられないのですが、「住所検索」ボタンのアクションで、入力バインドに「郵便番号」と「メールアドレス」の二つを設定した場合はどうなるのか見てみましょう。

上記の状態でアプリを生成して、メールアドレスが空欄のまま「住所検索」を押してみます。

このようにエラーメッセージが表示されました。
入力項目の必須チェックは、アクション時の入力バインドで指定されているものに掛かるということを覚えておきましょう。

まとめ

従来 WebPerformer で開発されてきた方は気づいたかも知れませんが、今回ご紹介した SPA 対応のアプリは REST API を使うことで、BP や DM を一切利用せずに開発しています。
このように、世の中に公開されている便利な API をうまく組み合わせることで、オンプレミスのデータベースに縛られることなく、新機能をスピーディに公開することができます。

個人的には、まだまだ SPA 対応アプリの機能には追加して欲しい機能や設定もありますが、今のうちに小規模なアプリケーション開発からチャレンジしておけば、将来的な機能改善、機能追加へもすぐに対応できるのではないでしょうか。