Help us understand the problem. What is going on with this article?

ThingWorx から外部サービスを REST で呼ぶ

はじめに

対象読者
この記事は、下記の知識・スキルを持っている人を対象としています。

  • ThingWorx 開発の基礎値基礎
  • JavaScript の基礎知識

対象バージョン

この記事は、ThingWorx 8.x で有効です。おそらく 6.5 以降で共通の仕組みを使っているので古いバージョンでも動くはずですが、Composer のスクリーンショットを 8.3 以降の New Composer で取得していますので、あらかじめご承知おきを。

ThingWorxと外部サービス接続

ThingWorxから外部のサービスへ接続してデータを取得する際、よく使われるプロトコルが JDBC と REST です。JDBC 経由でデータベースからデータを取得したり、REST API を備える外部サービスへ接続したりします。この記事では、REST API を備える外部サービスへ ThingWorx から接続する方法と簡単なサンプルを紹介します。

ThingWorx マッシュアップで郵便番号検索をしてみる

では早速 ThingWorx から外部サービスへ接続する具体的な方法を見ていきましょう。今回は、IW3 Projectが提供しているZIP SEARCH API SERVICE JIS X0404 対応版を利用して、ThingWorx マッシュアップに「郵便番号から住所を検索する」機能を追加してみます。完成形は下図のようになります。

image.png

データシェイプを作る

まず最初にデータシェイプを作ります。なぜデータシェイプが必要かというと、外部サービスから戻される JSON の構造を ThingWorx のマッシュアップビルダーに教えるためです。マッシュアップビルダーで外部サービスから戻された JSON の内部データを他のウィジェットのプロパティにバインドするには、JSON のデータを INFOTABLE へと変換する必要があります。(その方が使い勝手が良いのです)。INFOTABLE には各列のデータ型を指定するデータシェイプが必要ですので、最初にそれを作ります。

ZIP SEARCH API SERVICE のドキュメントをみて、かつ Postman で実際に REST API を叩いてみた限り、このサービスは次の形式の JSON を返すようです。

output.json
{
    "state":"14",
    "stateName":"神奈川県",
    "city":"鎌倉市",
    "street":"西御門"
}

下図は Postman での REST API を呼び出した様子。

image.png

今回はこの JSON の構造をそのまま使いましょう。

ThingWorx のマッシュアップビルダーで、新しいデータシェイプを作ります。

image.png

ここではデータシェイプの名前を "PostalCode"としました。"state" プロパティを Integer で、その他の "stateName", "city", "street" の各プロパティは String 型で作成しています。

プロパティを追加し終えたら、忘れずに "Save" ボタンをクリックしておくようにしましょう。

Thing を作る

image.png

外部サービスへ接続する Thing を新しくひとつ作ります。ここでは名前を PostalCodeSearch としました。"Base Thing Template" に GenericThing を選択します。その他は特に設定の必要はありません。(プロジェクトやタグの設定はお好みで)。

一旦、緑色の "Save" ボタンをクリックして、ThingWorx サーバー側に Thing を作成させます。その後、"Services" タブへ移動します。

”Service" タブで新しいサービスを追加します。黒い "Add" ボタンをクリックします。

新しいサービスを定義する画面が表示されますので、まずサービスの名前を決めます。ここでは "SearchAddress" としました。
image.png

つぎに、SearchAddress サービスが受け取るパラメタを指定します。郵便番号を受け取るので、頭3桁と下4桁を受け取れるように、Number 型の入力パラメタ upperCode と lowerCode を定義します。

image.png

さらに、SearchAddress サービスが戻すデータを "Output" に指定します。JSON を戻してもいいのですが、今後の使い勝手を考えて今回は INFOTABLE を選択し、データ型として先ほど作成した "PostalCode" データシェイプを指定します。

image.png

つづいて、いよいよ JavaScript のコーディング部分です。まず最初に、先ほど定義した入力パラメタを受け取るコードを書きます。コードエディタに次のように JavaScript のコードを書きます。

code.js
var zip_main = ('000' + upperCode).slice(-3);
var zip_sub = ('0000' + lowerCode).slice(-4);

コードエディタでは下図のように表示されます。

image.png

これ、少しわかりづらいのですが、入力パラメタが Number 型なので、たとえばユーザーが "0001" を入力しても、数値の 1 が渡されてしまいます。しかしこれだと郵便番号としては不十分です。郵便番号は "0001" でなければなりません。そこで、受け取った数値の桁数を強制的に合わせ、先頭に 0 をパディングするためにこうしたコードになっています。

次に、"Snippets" の "Resources" グループで "ContentLoaderFunctions" を探して、"GetJSON" サービスの右側にある黒い矢印をクリックします。そうすると、コードエディタにコードの断片(スニペット)が挿入されます。

image.png

自動で挿入されたコードの断片を編集します。

code.js
var params = {
    proxyScheme: undefined /* STRING */,
    headers: undefined /* JSON */,
    ignoreSSLErrors: undefined /* BOOLEAN */,
    useNTLM: undefined /* BOOLEAN */,
    workstation: undefined /* STRING */,
    useProxy: undefined /* BOOLEAN */,
    withCookies: undefined /* BOOLEAN */,
    proxyHost: undefined /* STRING */,
    //
    // 次の行を編集する
    // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    url: "http://api.thni.net/jzip/X0401/JSON/" + zip_main + "/" + zip_sub + ".js" /* STRING */,
    timeout: undefined /* NUMBER */,
    proxyPort: undefined /* INTEGER */,
    password: undefined /* STRING */,
    domain: undefined /* STRING */,
    username: undefined /* STRING */
};

// result: JSON
// 次の行の return を json に書き換える
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
var json = Resources["ContentLoaderFunctions"].GetJSON(params);

変更点は、"url" に外部サービスの URL をセットすることと、戻された JSON を受け取る変数を result ではなく json という名前に変えているところです。ThingWorx はサービスの最後で result を評価した結果をサービスの出力として扱います。外部サービス呼び出しで戻ってきた JSON をそのまま戻すわけではないので(INFOTABLE を返す)、ここでは result ではなく json という別の変数に格納しているんですね。

それでは受け取った JSON 形式のデータを INFOTABLE へと変換していきましょう。

コードエディタ上でカーソルが最終行にあることを確認して、"Snippets" の "Resources" グループから "InfoTable Functions" を探し、"CreateInfoTableFromDataShape" の右側にある黒い矢印をクリックします。そうするとコードエディタに JavaScript のコード断片が挿入されます。

image.png

挿入される JavaScript のコードを次のように書き換えます。

code.js
// params という変数の名前が衝突するので、params2 に変更
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
var params2 = {
    infoTableName: undefined /* STRING */,
    // dataShapeName に先の手順で作った PostalCode を指定。
    // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    dataShapeName: "PostalCode" /* DATASHAPENAME */
};


// result: INFOTABLE
// こちらも忘れずに params という変数の名前を、params2 に変更
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params2);

これで SearchAddress サービスが返す INFOTABLE オブジェクトを作成できました。しかし、まだ箱を作っただけで肝心のデータをセットしていません。

つづいて、コードエディタのカーソルが最終行にあることを確認して、"Snippets" の "Code Snippets" から "Infotable" を辿り、"Create infotable entry from..." というサービスの右側にある矢印をクリックします。"Create infotable entry from datashape" という画面が立ち上がりますので、セレクトボックスから "PostalCode" を選択して "Insert Code Snippet" をクリックします。

image.png

挿入された JavaScript コードの断片を編集します。下記のようになれば大丈夫です。

code.js
// PostalCode entry object
var newEntry = new Object();

// 外部サービスから戻された JSON の各フィールドを INFOTABLE の各フィールドに代入する
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
newEntry.stateName = json.stateName; // STRING
newEntry.city = json.city; // STRING
newEntry.street = json.street; // STRING
newEntry.state = json.state; // INTEGER

// 返却用の INFOTABLE に上記のオブジェクト "newEntry" を追加する
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓
result.AddRow(newEntry);

これでサービスの準備は完了です。忘れずに "Save" をクリックして、編集をサーバー側で確定させてください。
コードの全体は下記になります。

code.js
var zip_main = ('000' + upperCode).slice(-3);
var zip_sub = ('0000' + lowerCode).slice(-4);

var params = {
    proxyScheme: undefined /* STRING */,
    headers: undefined /* JSON */,
    ignoreSSLErrors: undefined /* BOOLEAN */,
    useNTLM: undefined /* BOOLEAN */,
    workstation: undefined /* STRING */,
    useProxy: undefined /* BOOLEAN */,
    withCookies: undefined /* BOOLEAN */,
    proxyHost: undefined /* STRING */,
    url: "http://api.thni.net/jzip/X0401/JSON/" + zip_main + "/" + zip_sub + ".js" /* STRING */,
    timeout: undefined /* NUMBER */,
    proxyPort: undefined /* INTEGER */,
    password: undefined /* STRING */,
    domain: undefined /* STRING */,
    username: undefined /* STRING */
};

// result: JSON
var json = Resources["ContentLoaderFunctions"].GetJSON(params);


var params2 = {
    infoTableName: undefined /* STRING */,
    dataShapeName: "PostalCode" /* DATASHAPENAME */
};

// result: INFOTABLE
var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params2);

// PostalCode entry object
var newEntry = new Object();
newEntry.stateName = json.stateName; // STRING
newEntry.city = json.city; // STRING
newEntry.street = json.street; // STRING
newEntry.state = json.state; // INTEGER

result.AddRow(newEntry);

作ったサービスをテストする

コードエディタの下にある "Execute" タブの中から、作ったサービスのテスト実行ができます。
入力パラメタ "upperCode" と "lowerCode" に適当な値をセットし、"Execute Service" もしくは "Save and Execute" をクリックすると、サービスが実行されます。結果は右側の "Output" に出力されます。下図は、upperCode に 248、LowerCode に 0004 をセットしてテスト実行した際の様子です。神奈川県の県番号は 14なんですね...

image.png

マッシュアップを作る

サービスの準備が整いましたので、マッシュアップを作ってみましょう。今回は名前を "PostalCodeSearch" とし、下図のようなウィジェット配置にしました。

image.png

"Data" タブで、先ほど作った PostalCodeSearch" Thing の "SearchAddress" サービスを呼びます。

image.png

ウィジェットとサービスの関係は次の通り。

image.png

ボタンのクリックで PostalCodeSearch の SearchAddress サービスが呼ばれます。その際、二つの Numeric Entry ウィジェットの値が、入力パラメタとして渡されます。SearchAddress サービスは INFOTABLE を戻してくるので、その中から stateName、city、そして street フィールドの値を、それぞれ Label ウィジェットに渡していますね。

無事マッシュアップも作れたようなので、"Save" ボタンでサーバー側上で編集を確定して、"View Mashup" をクリックしてマッシュアップを実行してみましょう。

image.png

頭3桁と下4桁を入力して "検索" ボタンをクリックすると...

image.png

無事動きました。

終わりに

本記事では、ThingWorx の ContentLoader 機能を使って、外部サービスに REST で接続する方法を説明しました。

今回は外部サービスに REST で接続して GET メソッドで情報を取得しましたが、ConentLoaderFunctions には GET 用のサービス GetJSON 以外にも PostJSONPutJSON も準備されています。また JSON だけではなく、XML 用の各メソッドも用意されているので、いろいりなサービスに対して CRUD 処理を実行できますね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした