まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:npm

IBM BluemixAPI Connect サービスを利用して、データベースのテーブルスキーマから CRUD の API を生成する、という手順を試してみました:
2017071001


以下にその作業内容を紹介します。なお、以下の内容は基本的にはこのドキュメントに書かれている内容を補足しながら実行したものです:
https://new-console.ng.bluemix.net/apis/apiconnect/start


何はともあれ API Connect サービスインスタンスを1つ作成します。なお 2016/07/10 時点では(クラシックエクスペリエンスではなく)新しいUI 画面でないと正しく動かなかったので、以下は新 UI でのスクリーションショットで紹介します。

まず API Connect サービスインスタンスを作成します。新 UI 画面のダッシュボードから「コンソール」を選択し、「API」を選択します:
2016071001


API に関連するサービスの画面が表示されたら「API Connect」を選択:
2016071002


API Connect の画面に移動しますが、まだインスタンスが作成されていないので、「作成」ボタンをクリックします:
2016071003


API Connect サービスの紹介画面が表示されたら、下にスクロールします:
2016071004


利用プランを選択して「作成」ボタンをクリックします。下図では無料の "Essential" プランを選択しました。共有サーバーで利用できるリソースもあまり多くありませんが、まずはこれで作ってみます:
2016071005


作成された API Connect サービスインスタンスの画面に移動します。"Sandbox" と表示されていれば成功です。また後でこの画面を使うことになりますが、まずはここまでの作業で API Connect サーバーが1つ用意できました。Bluemix のダッシュボードに戻るには左上の "IBM Bluemix" 部分をクリックします:
2016071006


さて、API が用意できたら再度この API Connect サービスを使って公開のための設定を行うことになります。既に公開してもよい API があればしばらく読み飛ばしてください。以下はこれから1つのデータベーステーブルを作り、その中身を読み書きするための API を API Connect Developer Toolkit を使って新たに生成するための作業手順を紹介します。

API Connect Developer Toolkit を導入するにはまず Node.js と npm を作業マシンに導入する必要があります。Windows 環境であればこちらからインストーラーをダウンロードして導入します。Linux などの UNIX 環境であればこちらの記事(の nodejs と npm のインストールまで)を参考に Node.js と npm を導入しておいてください:
http://dotnsf.blog.jp/archives/1036420834.html

Node.js および npm が導入できたら、npm を使って API Connect Developer Toolkit を導入します:
# npm install -g apiconnect

なお、この作業マシン上でも API Connect サーバーを起動することになり、一部の作業をウェブブラウザから実行することになります。つまりこの作業マシンには GUI のデスクトップ環境やウェブブラウザが導入されている必要があります。環境に合わせて導入しておいてください。CentOS であれば以下のコマンドで X Window のデスクトップおよび FireFox ウェブブラウザを導入できます:
# yum groupinstall "Desktop"
# yum install firefox

そして、API Connect Developer Toolkit を使って StrongLoop LoopBack アプリケーションを作成します。以下の例ではホームディレクトリ以下に src サブディレクトリを作り、更にその下に apic コマンドで loopback アプリケーションを作成しています。この通りに実行していただいても構いませんし、別途適宜ディレクトリを変更して実行することもできます:
# mkdir ~/src
# cd ~/src
# apic loopback

最初の1回目だけはライセンスに同意していただく手続きが必要です。内容を確認の上、"Yes" を選択してください:

2017071001


ライセンス同意後、ここからは StrongLoop LoopBack とほぼ同じ手順を実行することになります。まずは API アプリケーションとしての名前を指定します。ここでは "myapp" という名前にしました:
2017071002


次にアプリケーションを作成するディレクトリ名を指定します。デフォルトではアプリケーション名と同じ名前のディレクトリが指定されます。このままでも構いませんし、変更していただいても構いません:
2017071003


アプリケーションの種類を聞かれます。今回はサーバー上で動く API をテンプレートなしで作るので、"empty-server" を選択します:
2017071004


すると入力された内容にそってアプリケーションが作られます・・・・が、私の場合は何故かここでエラーになってしまいました:
2017071005


エラーになった場合はアプリケーションディレクトリ(この例では myapp)に移動し、"npm install" を実行して手動でインストールします:
2017071006


ではこの API アプリケーションを具体的に作成していきます。ここからはブラウザでの作業になるので、まずはデスクトップ画面を開き、その中でターミナルウィンドウを開きます。

アプリケーションディレクトリ(この例では myapp)に移動し、"apic edit" と入力します。すると "Express server listening on http://127.0.0.1:9000" と表示され、デスクトップ内にデフォルトブラウザが開いて、この URL が開きます。まず最初に Bluemix にログインする必要があるため、「Bluemix にサインイン」を選択します:
2017071007


IBM Bluemix のアカウントとパスワードでログインします:
2017071008


ログインが成功すると「ドラフト API」の画面に移動します。「OK」をクリックします:
2017071001


IBM API Connect のトップ画面に移動します。以下の様な画面が表示されることを確認してください:
2017071002


ここからテーブルモデルのスキーマを定義して、そのモデルの CRUD 操作 API を生成するのですが、その前にその情報を格納するデータソース(データベース)を作成する必要があります。「データソース」タブに移動して、まだデータソースが1つも定義されていないことを確認してから「追加」をクリックします:
2016071001


最初にデータソースの名称を入力します。ここでは "db" とだけ指定して「新規作成」します:
2016071002


次にこのデータソースのコネクターと localStorage を指定します。前者はデフォルトでもあるインメモリDB(In-memory db)を指定し、localStorage には window.localStrage と入力して、画面右上の保存ボタンで保存します。これでデータソースの定義は決まりました:
2016071003


続けてモデルを定義します。「モデル」タブに移動して「追加」ボタンをクリックします:
2016071001


新しく作成するモデルの名称を入力します。この例では "item" という名前のモデルにしました:
2016071002


続けて新規作成した item モデルに追加設定を加えるため、一覧から選択します:
2016071003


(モデルの)複数形には "items" 、基本モデルには "PersistedModel" 、そしてデータソースには先程作成した "db" を指定します:
2016071202


続けてプロパティを追加するために右下の+印をクリックして、以下のようにプロパティを設定します。追加するプロパティは2つで、1つ目は必須の name(string)、2つ目は必須ではない price(number)とします。item(商品)のname(名前)とprice(値段)を設定するためのプロパティだと思ってください。なお、特に指定しなくても id というインデックスプロパティがこれらに加えて追加されます:
2016071000


プロパティの追加が完了したら、右上の保存ボタンでモデル定義を保存します。またこの状態で CRUD API を有効にするため、画面下の "Stopped" と書かれた左にある三角をクリックして、API アプリケーションを実行します:
2016071201


しばらくすると HTTP サーバーが起動し、ステータスが "Running" に変わります。同時に API アプリケーションの URL(http://127.0.0.1:4001/)が表示されます:
2016071203


この状態になると、作成した myapp の API アプリケーションが起動している状態になり、item モデルの読み書きが可能になります。試しにいくつかの API を curl で実行してみましょう(以下青字が入力コマンド、黒字が出力結果)。

まずは item の一覧を取得(GET /api/items)します。まだ何も追加していないので、結果は空配列になっています:
# curl -XGET http://localhost:4001/api/items
[]

1つの item を追加(POST /api/items)してみます。まずは必須の "name" プロパティをわざと指定せずにデータを POST してエラーになることを確認します:
# curl -H 'Content-Type: application/json' -XPOST http://localhost:4001/api/items -d '{"price":100}'
{
 "error":{
  "name":"ValidationError",
  "status":422,
  "message":"The `item` instance is not valid. Details: `name` can't be blank (value: undefined).",
  "statusCode":422,
  "details":{
   "context":"item",
   "codes":{
    "name":["presence"]
   },
   "messages":{
    "name":["can't be blank"]
   }
  },
  "stack":"ValidationError: The `item` instance is not valid. Details: `name` can't be blank (value: undefined).\n ....
    :

↑"name" がブランクではダメ、と怒られています。というわけで、改めて正しいデータを指定して追加してみましょう:
# curl -H 'Content-Type: application/json' -XPOST http://localhost:4001/api/items -d '{"name":"あいうえお","price":100}'
{"name":"あいうえお","price":100,"id":1}

↑追加処理が成功したようです。入力データに指定しなかった id 要素が追加され、その値が1になっているようです。


この状態で再度 item の一覧取得を実行すると、追加したデータが含まれた配列で返ってくることを確認します:
# curl -XGET http://localhost:4001/api/items
[{"name":"あいうえお","price":100,"id":1}]

また id を指定して要素を取り出す(GET /api/items/{id})こともできます:
# curl -XGET http://localhost:4001/api/items/1
{"name":"あいうえお","price":100,"id":1}

↑こちらは結果が1つしか存在しない API なので、結果は配列ではなく、該当する JSON オブジェクトそのものになります。

データを更新(PUT /api/items)することもできます:
# curl -H 'Content-Type: application/json' -XPUT http://localhost:4001/api/items -d '{"id":1,"name":"かきくけこ","price":200}'
{"name":"かきくけこ","price":200,"id":1}

# curl -XGET http://localhost:4001/api/items
[{"name":"かきくけこ","price":200,"id":1}]

そして削除(DELETE /api/items/{id})する API も用意されています:
# curl -XDELETE http://localhost:4001/api/items/1
{"count":1}

# curl -XGET http://localhost:4001/api/items
[]

というわけで、item モデルを定義しただけで、その item モデルを読み書き更新削除する API が自動生成できていることが確認できました。


API Connect 本体の機能をほとんど紹介できてないのですが、長くなったのでとりあえずここまで。


Slack のボットを作るためのフレームワークである BotKit の使い方(というか導入方法)を紹介します。


前提条件として、当然ですが Slack のアカウントは必要です。お持ちでない場合は Slack のページでサインアップおよびサインインを済ませておいてください。サインイン済みの環境に対してボットを作成します。

また BotKit は Node.js のアプリケーションとして動作するので、そのパッケージマネージャである npm が導入されている必要があります。(CentOS 環境用の内容ですが)以下のページを参照するなどして、npm コマンドが使える状態を作っておいてください:
CentOS に StrongLoop をインストールする


最初に Slack の Bot creation page にアクセスして、新しいボットを1つ作成します:
Bot creation page


アクセス先でボットの名前を指定(下図では @dotnsf_bot)して、"Add bot integration" ボタンをクリックすると、ボットが作成されます。ボットの名前は他の人が使っていると使えないので気をつけてください:
2016031701


ボットの作成に成功すると以下の様な画面になり、API Token が表示されます。この値を後で使います。メモ帳などにコピーしておきます:
2016031702


仮にこの API Token の値が xoxb-XXX(API Token)XXX であったとして以下を紹介します。適宜自分の環境と読み替えてください。

次に BotKit をダウンロードします。npm をセットアップしたシステムにログインし、適当なディレクトリ(以下の例では /usr/local/src/)で以下のコマンドを続けて実行し、必要なパッケージとその依存パッケージをダウンロードします:
# cd /usr/local/src
# git clone https://github.com/howdyai/botkit.git
# cd botkit
# npm install

全て導入が完了したら、上記で取得した API Token を使ってボットを動かします(以下を一行で実行します):
# token=xoxb-XXX(API Token)XXX node bot.js

すると以下の様な画面になって、ボットが起動します(途中でボットを強制終了させる場合は Ctrl+C で抜けます):
2016031703



デフォルトのボット(実体は bot.js)ではいくつかの決められた挙動をするように実装されています。いくつか試してみましょう。


まず自分の Slack ID で(ボットを作成した時の Slack ID で)Slack にアクセスし、適当なチャネル(例えば #general)に入ります:
2016031704


以下のコマンドをメッセージとして入力し、ボットをこのチャネルに招待します:
/invite @(ボットの名前)
2016031705


続けて "Hello" というメッセージをこのボット宛に送ります。頭に @(ボットの名前): を付けてメッセージを送ります:
@(ボットの名前): Hello


するとボットが反応し、Hello というメッセージを返してくれます。最初の会話が成立しました:
2016031706



続けて自分のことを聞いてみます。先程と同様にして "Who am i" というメッセージを送ってみますが、"I don't know yet!"(「まだ知らない」)という答が返ってきました。そりゃそうだ:
2016031707


というわけで自分のことを教えてあげましょう。"call me (名前)" というメッセージを送ります。「次からはそう呼ぶ」と分かってくれたっぽい感じ:
2016031708


では改めて "Who am i" と聞いてみます。今度は自分が指定した名前を返してくれました。一応覚えていてくれたっぽいです:
2016031709


最後にこのボットを Slack から終了する方法も紹介します。実行中のコマンドラインから Ctrl + C で強制終了することもできますが、"shutdown" と命令し、確認のメッセージに "Y" と回答するとボットはシャットダウンします(コマンドも終了します):
2016031801




と、デフォルトのボットの挙動はまあこんな感じです。この中身は bot.js の中で実装されていて、そのカスタマイズもこのファイルを編集することになりますが、それについては別のまた機会に。

(2016/Mar/22 追記)
続きはこちら


サーバーサイド JavaScript アプリケーションサーバーである Node.js の MVC フレームワーク Sails.js を API 管理っぽい感じで使ってみました。使ってみた感想としては「(Ruby on )Rails や Strongloop っぽい」という印象です:
2016011001


Sails.js を使う前提として、Node.js の動作環境が必要です。こちらを参照するなどして Node.js アプリケーションサーバーの実行環境を用意しておいてください:
http://dotnsf.blog.jp/archives/1036420834.html


ここに npm を使って Sails.js を導入します。が、そのためには npm のバージョンが 1.4.0 以上である必要があります。まずは npm そのものをアップデートしておきましょう:
# npm update -g npm

その後、npm を使って Sails.js をインストールします:
# npm install -g sails

これで Sail.js の導入は完了したので、sails コマンドが使える状態になっているはずです。試しに1つプロジェクト(mysailsapp)を作ってみましょう。コマンドラインから以下のように入力します(この辺りからして Rails っぽいです):
# sails new mysailsapp

試しにこの状態で一度アプリケーションサーバーを起動して、ウェブブラウザからプロジェクトを参照してみます。作成したプロジェクトのディレクトリに移ってから sails の lift コマンドで HTTP サーバーを起動します:
# cd mysailsapp
# sails lift

2016011002


この状態でウェブブラウザで 1337 番ポートを指定してアクセス(http://XX.XX.XX.XX:1337/)するとデフォルト状態でのプロジェクトページが確認できます:
2016011003


では MVC フレームワークっぽいこともやってみましょう。いったん Ctrl+C で sails lift を終了してから、改めて "item" という名前で商品を扱うような Model と Controller を生成します(sails lift で HTTP サーバーも再起動します):
# sails generate api item
# sails lift

この状態で http://XX.XX.XX.XX:1337/item/ にアクセスすると、現在の item の状態が JSON で確認できます(今はまだ作っただけで中身がないのでこのような空配列の状態になっています):
2016011004


item に1つの要素を追加してみます。ウェブブラウザで http://xx.xx.xx.xx:1337/item/create/?name1=valu1&name2=value2&name3=value3&... といった感じの URL を指定してアクセスしてみます。例えば今回は商品の名称(name)と商品コード(code)を指定してこのような URL にしました:
http://xx.xx.xx.xx:1337/item/create/?name=キュレル薬用シャンプー&code=4901301223159

するとこのような結果が表示されます。データレコードが生成され、id (1)も割り振られました。GET でレコード作れちゃうんですね、へー。。。
これを何度か繰り返して、必要なだけ商品を登録しておきます:
2016011005


改めて /item/ にアクセスすると、作成したデータレコードの配列が取得できることが確認できます:
2016011007


id を指定して、/item/(id) にアクセスすると、その指定した商品の情報を取得することもできます:
2016011008


とりあえず Model と Controller を簡単に作って API 生成ツールとして使えそうなことはわかりました。では更に View の機能も使ってみます。上記で作成した item を表示する test というビューを定義して、
/item/test/(id) にアクセスすると、指定した id の商品情報を出力できるようにしてみます。

まずはコントローラー内に test ビューを定義し、item というパラメータで指定 id の商品をビューに送るような処理を記述します。api/Controllers/ItemController.js というファイルが生成されていると思うので、このファイルを編集して以下の様な処理を追加します(青字部分を追加):
  :
  :
module.exports = { _config: {}, test: function( req, res ){ Item.findById( req.param( 'id' ) ).exec( function( err, item ){ res.view( {item: item[0]} ); }); } }

/item/test/(id) というリクエストの (id) 部分を使って Item を検索し、見つかった結果(結果は配列なので、配列の0番目)を item という名前でビューに送ってレンダリングする、という処理内容です。

更に views/item/test.ejs というファイルを以下の内容で新規に作成します:
<h1><%= item.name %></h1>
<h3>コード = <%= item.code %></h3>
<hr/>
作成日 : <%= item.createdAt %>

この状態で Sails を再起動(Ctrl+C で止めてから再び sails lift)し、ウェブブラウザで /item/test/(id) にアクセスすると、指定した ID の商品が指定したビューのフォーマットで表示できることが確認できるはずです:
2016011009


モデルとコントローラを簡単に生成しての API 作成ツールとしてだけではなく、ビューも使った MVC のフレームワークとしても Sails.js は便利に使えそうです。


 

IBM が9月に買収した StrongLoop は、Node.jsExpress フレームワークへのコントリビューションの多く、IBM の Node.js による API 開発の中核的な役割になっていくものと思われます。例えば、以下の Watson API リファレンスのサイトは StrongLoop を使って提供されています:
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/

この StrongLoop (と、前提としての Node.js)そのものは無料で提供されているので、誰でも自分の環境にインストールして使うことができます。 というわけで、CentOS に(Node.js と)StrongLoop をインストールして使ってみました。


StrongLoop は npm で提供されています。なので、まずは Node.js と npm を yum でインストールします:
# yum install epel-release
# yum install nodejs npm --enablerepo=epel

Node.js と npm がインストールできたら、npm を使って LoopBack と StrongLoop をインストールします:
# npm install -g loopback
# npm install -g strongloop

このインストールにはそれなりに時間がかかりますが、作業としてはこれだけで StrongLoop がインストールできます!


では実際に StrongLoop を使ってデータベースのモデルを作り、その CRUD の REST API を公開してみましょう。 まずは空のディレクトリ(下の例では ~/tmp)を作ってそこに移動します:
# cd
# mkdir tmp
# cd tmp

このディレクトリに loopback 環境を作成します:
# slc loopback
2015111001


アプリケーションの名前と、そのアプリケーションの作成ディレクトリを聞かれます。ここでは両方とも myapp と指定しました:
2015111002


すると必要なモジュールのインストールを含めた作業が始まり、完了すると myapp というディレクトリが作られます:
2015111003


出来上がった myapp ディレクトリに移動して、モデルの定義を行います。以下のコマンドを入力します:
# cd myapp
# slc loopback:model

ここからは API で CRUD を行うモデルとして、以下の様な item モデルを定義することにしましょう:
列名列型必須条件
namestringYES
codestringYES
pricenumber 


実際にはこの定義に加え、自動的に id という列が定義されます。では最初に myapp アプリ内に item モデルを作成し、これらの3つの列を順に定義していきます。まず model name は "item" を入力します。次に data-source は、今回はデフォルトのメモリ DB を使うので "db (memory)" を選びます。またこのモデルは永続性(persistant)を有効にしたいので、その Base class には "PersistedModel" を指定してします。またこの item は REST API で公開したいので Expose するかどうかの質問には Yes を選択。この item モデルの複数形名にカスタムな名称を使うわけではない(普通に items とする)ので、Custom plural form の質問は空のままで Enter を押します。そしてこのモデルは common モデルにするので "common" を選択します:
2015111004


次に各列を順に定義します。最初は name 列を定義します。名前には "name" を指定し、その type には "string" を、そして必須かどうかの属性は必須なので "Y" を入力します:
2015111005


続けて "code" 列を定義します。同様にして名前には "code"、type には "string"、そして必須属性を "Y" で指定します:
2015111006


最後に "price" 列を定義します。名前には "price"、type には "number" 、必須属性を "N" で指定します:
2015111007


これで全ての列を指定し終わったので、最後に名前欄を空欄にして Enter を押します。これでモデルの定義が完了です:
2015111008


ここまでの作業ができたら、カレントディレクトリで node.js を起動します:
# node .

すると、デフォルトでは 3000 番ポートで node.js が待受る形で起動します:
2015111001


この状態で表示されているアドレス(http://(strongloopをインストールしたホスト名):3000/explorer)にブラウザでアクセスしてみると、作成した myapp アプリケーション内に定義されている API の一覧が表示され、その中には item モデルについても含まれているはずです:
2015111002


item と書かれた箇所をクリックすると展開され、この item モデル向けに用意されている API の一覧が表示されます。特に何もしなくても item モデルの定義をしただけで一通りの CRUD 操作ができるような API が準備されていることがわかります:
2015111003


用意された API はこの画面から実際に動かして試してみることもできます。例えば一番上にある /items への GET を実行してみましょう。このエントリの /items を書かれた箇所をクリックして開くと、この GET リクエスト API に関する情報が表示されます:
2015111101


この画面内の "Try it out" と書かれたボタンをクリックすると実際に API を発行することができます。実際にクリックすると curl で実行されたコマンドや実際にリクエストされた API の URL などが確認できます。また Response Body には実行結果が表示されます。この例では実行結果は [] と、空の配列になっているので、実行しても何も得られなかった、ということになります(今はまだ中身がないのでこれで正しい実行結果です):
2015111102


では実際に item レコードを作ってみましょう。レコードを作成するには POST リクエストを実行することになるので、/items への POST エントリを開き、Parameters 欄の data の部分に以下のようなフォーマットの JSON データを入力して "Try it out!" ボタンをクリックします( "id" は自動割り振りされるので、指定してあってもいなくても構いません。また実際に指定するデータは適当で構いません):
{
  "name": "アディゼロ匠 B22875",
  "code": "4055339759613",
  "price": 12050,
  "id": 0
}

2015111103


問題なく処理が成功すると、以下の様な結果が得られます。Response Code が 200 になっていれば成功を意味しており、Response Body には以下の様な JSON が返されます("id" の値として 0 を指定していましたが、自動割り振りされた結果の 1 が付与されています)。このデータが正しく追加された、ということになります:
{
  "name": "アディゼロ匠 B22875",
  "code": "4055339759613",
  "price": 12050,
  "id": 1
}

2015111104


データが正しく追加されたので、改めて再度 /items の GET を実行すると、今度は Response Body の結果は [] ではなく、先程入力したデータが含まれた配列になっているはずです。モデルを定義しただけで自動生成された CRUD の API が( /items の GET と POST だけですが)正しく動いていることが確認できました:
2015111105


RDB のテーブルに相当するレコードを定義すれば、(コードを書くこともなく)即 CRUD API が用意される、という意味では便利です。


いずれはモニタリングやトレーシングなどもできる StrongLoop Arc についても勉強して、ここで紹介するつもりです。



このページのトップヘ