IBM API Connect を使用して既存MySQL DBをAPI化してみた

#API Connect と StrongLoopとの違い
API Connectの概要、できることに関しては、[IBM API Connect 使ってみた〜APIを作る〜](http://qiita.com/capsmalt/items/c21ed4b75fa468952671)にまとまっているのでそちらを参照。
[StrongLoop.com](https://strongloop.com)によると、StrongLoopが進化したとのこと。
>StrongLoop is evolving into IBM API Connect.

LoopBackやStrongloopはどうなるのかは、[API Connect FAQs](https://strongloop.com/api-connect-faqs/)に記載あり。
LoopBackはオープンソースのまま、IBMおよびコミュニティが貢献、維持。
>LoopBack is still OpenSource, and IBM and the community will continue to contribute and maintain it. 

StrongLoop Arcは、API Connectに置き換わるが、機能は統合され利用できる予定。
>Arc is being replaced by API Connect, but will continue to be available as its features are integrated.

APIを作るという観点で、StrongLoopとの違い。代表的な操作をまとめると、以下。

|                  | StrongLoop                | API Connect               |
|:-----------------|:--------------------------|:--------------------------|
| インストール　　　 | `npm install -g strongloop` | `npm install -g apiconnect` |
| プロジェクトの作成 | `slc loopback`              | `apic loopback`             |
| モデル作成　　　   | `slc loopback:model`        | `apic create --type model`  |
| GUIツール起動　　  | `slc arc`                   | `apic edit`                 |

API Connectのコマンド操作について詳しくは、[KnowledgeCenter](https://www.ibm.com/support/knowledgecenter/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/rapim_cli_command_summary.html)を参照のこと。

#環境
- Windows7 Professional SP1
- MySQL Ver 14.14 Distrib 5.7.11
- Node v4.2.2
- npm v3.8.2
- apiconnect v1.0.2
 
#MySQLの定義
MySQLはローカルに導入し、簡単なものを準備。

```lang:mysql
mysql> create database sample;
mysql> use sample;
mysql> create table employee(empid int primary key, name varchar(20), telno varchar(20), deptid int not null);
mysql> insert into employee(empid, name, telno, deptid) values(1, 'George Washington', '03-0000-0000',1);
mysql> insert into employee(empid, name, telno, deptid) values(2,'John Adams', '03-0000-0001',2);
mysql> insert into employee(empid, name, telno, deptid) values(3,'Thomas Jefferson', '03-0000-0002',3);
mysql> insert into employee(empid, name, telno, deptid) values(4,'James Madison', '03-0000-0003',1);
mysql> insert into employee(empid, name, telno, deptid) values(5,'James Monroe', '03-0000-0004',2);
mysql> insert into employee(empid, name, telno, deptid) values(6,'John Quincy Adams', '03-0000-0005',3);
```

#API Connectで既存MySQL DBをAPI化

基本的な流れは、[IBM API Connect 使ってみた〜APIを作る〜](http://qiita.com/capsmalt/items/c21ed4b75fa468952671)と同様。

- apiconnectのインストール
- LoopBackでプロジェクトの作成
- API Designerを使用してデータソース作成
- API Designerを使用してAPI公開用モデルの作成
- 作成したAPI公開用モデルとMySQLのテーブルをどうやってマッピングする？ 
- 実行

##apiconnectのインストール
`$ npm install -g apiconnect`
インストールしたバージョンの確認。
`$ apic -v`
今回のバージョンは以下の通り。
![apic_version.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/5b32e9ab-8fe0-0710-0c2d-8977dd9c66d5.jpeg)

##LoopBackでプロジェクトの作成
apicコマンドでLoopBackプロジェクトを作成。プロジェクト名は"mysqlcon"としている。
`$ apic loopback mysqlcon`
WindowsだとYeomanおじさんがずれている。
![create01.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/9e315cce-2111-028d-f6a3-5afc4e5e1668.jpeg)

プロジェクトが作成後、cdコマンドで作成ディレクトリに移動。
`$ cd mysqlcon`

##API Designerを使用してデータソースを作成
コマンドでもデータソースを作成することはできるが、Designerを使用して作成。
プロジェクト内にいることを確認し、API Designerを起動。
`$ apic edit`
![create03.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/c7f9bdb2-b77c-88e3-7e49-3cfb151b5297.jpeg)
初回アクセス時に、Bluemixへのログインを求められる。
![create04.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/dc83306f-6a52-3fa3-ffb1-8e85ad265fdc.jpeg)

Bluemixのユーザー登録は、[IBM Bluemixフリートライアルアカウント作成手順](http://qiita.com/KenichiSekine/items/6ad49b25167b3f4cdb63)などを参考。
ログインすると作成したAPIのページが表示される。
![create05.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/1ddb2b62-3604-96fb-1d8f-d915bcef171a.jpeg)

メニューの「データ・ソース」を選択し、「追加」をクリック。
![create06.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/b143043a-ce96-fbd6-d939-3eb899330d0c.jpeg)

必要な情報を入力し、保存する。

- 名前 : mysqlDS
- コネクター : MySQL
- host : localhost
- ポート : 3306
- ユーザー : 該当ユーザー
- パスワード : 該当パスワード
- database : 該当DB
![create07.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/7b97803c-e06c-0254-ff0e-9f54a427bf5b.jpeg)
この操作で、以下ファイルが更新される。
- mysqlcon\server\datasources.json

StrongLoopのArcでは、データ・ソースを定義するとDBからAPI公開用モデルを抽出できる機能があったが、2016年4月時点のAPI Connectではまだ実現できない模様。StrongLoop Arcの機能は、マニュアルを参考([Discovering models from a database](https://docs.strongloop.com/display/APIS/Discovering+models+from+a+database))。
>![discovery1.png](https://qiita-image-store.s3.amazonaws.com/0/121209/139f4a3d-cdaa-1cb2-69e4-a82b14d96367.png)

**注：現在、DBからAPI用のモデルを抽出する機能は、MySQL, Postgre, Oracle, SQL Serverの4つのLoopBack connectorで提供。今後拡張されてくるはず。**マニュアル参考([Discovering models from relational databases](https://docs.strongloop.com/display/public/LB/Discovering+models+from+relational+databases))


コマンド・プロンプトに戻り、画面に表示があるように、mysql用のConnectorモジュールを、インストールする。
`$ npm install --save loopback-connector-mysql`
![create08.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/f5615bdf-77a5-16c5-fe92-1435b6fdfa24.jpeg)


##API Designerを使用してAPI公開用モデルの作成
続いて、APIとして公開するモデルを作成。メニューから「モデル」を選択し「追加」をクリック。
![create09.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/2410a2ca-aeec-9154-66fe-a8c6770b38d8.jpeg)

必要な情報を入力し、保存する。

- 名前 : employee
- 複数形 : なし
- 基本モデル : PersistedModel
- データ・ソース : mysqlDS(先ほど作ったデータ・ソース)
- 公開 : チェック
![create10.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/9ecbe541-7e36-1a9c-57a8-016c130c92b9.jpeg)

続いて、作成したMySQLを参考にプロパティーを以下のように作成し、保存。
![create11.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/d6e32f50-8d94-cbb2-4150-926937a13464.jpeg)

実際のDBのカラム名と、公開するAPIのプロパティー名が異なることは十分ありえるので、empno, deptnoはDBのカラム名とは一致しないものを利用。
この操作で、以下ファイルが作成、更新される。

- mysqlcon\common\models\employee.json
- mysqlcon\common\models\employee.js
- mysqlcon\server\model-config.json

また、`$ apic edit`を実行したコマンド・プロンプトを確認すると、swagger定義が作成されていることもわかる。
![create12.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/d328ddf9-c6d8-bbbd-6081-c44dd850c7f4.jpeg)


##作成したAPI公開用モデルとMySQLのテーブルをどうやってマッピングする？
LoopBackのマニュアル [Database discovery API](https://docs.strongloop.com/display/public/LB/Database+discovery+API) 読むと、作成したモデルのjsonファイル内に、"mysql"オブジェクトを定義するらしいことを確認。
>The result below is an example for MySQL that contains MySQL-specific properties in addition to the regular LDL model options and properties. The 'mysql' objects contain the MySQL-specific mappings. For other databases, the key 'mysql' would be replaced by the database type, for example 'oracle', and the data type mappings would be different.

APIやサンプルを参考に、コンソールに出力する以下スクリプトを作成。

```mysqlcon\server\bin\script.js
var loopback = require('loopback');
var util = require('util');
//datasourceの作成
var dsjson = require('../datasources.json');
var ds = loopback.createDataSource('mysql', dsjson.mysqlDS);
    //DBのテーブルを検索
    ds.discoverModelDefinitions({schema: 'sample'},function(err, models) {
    	var count = models.length;
        //テーブル毎にスキーマを出力
    	models.forEach(function(def) {
	    	ds.discoverSchema(def.name, null, function (err, schema) {
	    		  console.log(util.inspect(schema, true, 3));
	    		  count--;
	    		  if (count === 0) {
					ds.disconnect();
				}
			});
		});
    });
```

`$ node server\bin\script.js`
実行結果は以下(一部のみ)。
![create13.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/e29498bf-98e5-c866-75f7-0302554103d2.jpeg)
これの"mysql"オブジェクト部分を、mysqlcon\common\models\employee.jsonの各パラメーター名の該当箇所にコピペ。**注：JSONの表記方法の関係で、キーと文字列の値は、ダブルクォートで括る必要があった。**

```employee.json
{
  "name": "employee",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "empno": {
      "type": "number",
      "id": true,
      "required": true,
      "mysql":
         { "columnName": "empid",
           "dataType": "int",
           "dataLength": null,
           "dataPrecision": 10,
           "dataScale": 0,
           "nullable": "N" }
    },
    "deptno": {
      "type": "number",
      "required": true,
      "mysql":
         { "columnName": "deptid",
           "dataType": "int",
           "dataLength": null,
           "dataPrecision": 10,
           "dataScale": 0,
           "nullable": "N" }
    },
    "name": {
      "type": "string",
      "required": false,
      "mysql":
         { "columnName": "name",
           "dataType": "varchar",
           "dataLength": 20,
           "dataPrecision": null,
           "dataScale": null,
           "nullable": "Y" }
    },
    "telno": {
      "type": "string",
      "required": false,
      "mysql":
         { "columnName": "telno",
           "dataType": "varchar",
           "dataLength": 20,
           "dataPrecision": null,
           "dataScale": null,
           "nullable": "Y" }
    }
  },
  "validations": [],
  "relations": {},
  "acls": [],
  "methods": {}
}
```

これで、APIとして公開するモデルと、MySQLのテーブルのマッピングは完了。

##実行
API Designerのメニューから「実行」を選択し「開始」をクリック。
![create14.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/4852f8c0-3347-3cef-2ebb-287bcfd17f62.jpeg)

サーバー開始を確認後、「探索」をクリック。作成したemployee APIのCRUD操作が可能。左メニューの「GET /employees」を選択。
![create15.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/9934535e-b22c-1f70-1bf5-54c91d58fde9.jpeg)

右側の画面をスクロールさせ、「操作の呼び出し」をクリック。以下のように、MySQLに挿入したデータが取得できていることを確認。
![create16.JPG](https://qiita-image-store.s3.amazonaws.com/0/121209/8341bf45-b5d8-3bf2-0569-b57dfe18782a.jpeg)

#まとめ

- **現時点(2016年4月)のAPI Connectでは、モデルと既存DBのマッピングは一工夫が必要**

StrongLoop Arcでは出来ていたので、近いうちに出来るはず。LoopBack connectorも増えているので今後に期待。

***
ちなみに、以下のようにモデルを設定するとマッピングをしなくとも接続ができることも確認。
- モデルの名前とDBのテーブル名を大文字小文字で一致
- モデルのパラメーター名とDBのカラム名を大文字小文字で一致
- モデル側にプライマリー・キーを表す、IDの設定