これはCData Software Advent Calendar 2023 13日目の記事。
本記事では、CData API Serverを活用して、自分のMac環境で動いているデータベース(MySQL on Docker)をREST API化するための手順を解説する。できるだけ設定内容や手順を細かく書いているので、試してみたい方は是非写経してみてください。
モチベーション
きっかけは、CData Software Japanの杉本さん(@sugimomoto)からのおすすめだった。それで CData API Server の存在をはじめて知った。
CData API Server(以下、CAS)とは、ざっくり説明すると、RDBなど、さまざまなデータソースに対してのデータ取得、更新のためのREST APIを公開できるプロダクトである。ただ、単にREST APIを公開できるだけでなく、安全にデータアクセスするためのセキュリティと認証機能だったり、データのフィルタリング、変換、集計のためのクエリ言語やデータ変換機能など、実運用に必要な機能を備えている。詳しくはプロダクトページを参照ください。
この存在を知ってまず思ったのが、データソース接続のためのドライバーやライブラリのインストールができないような環境において、とても有効だろうなと。CASにより、REST APIといった比較的に接続敷居の低いインターフェースを通じてアクセスできるようになるわけだが、例えばセンサー、ミニデバイスなどIoT環境だったり、制約の多いサンドボックス環境などでは、REST APIを通じてデータソースとの連携ができるようになるのは嬉しいはず。
特に、私の場合、日常的にAPIテストでおなじみのPostmanを使っているのだが、Postmanではその制約上(*補足)、外部のデータソースと連携をするにはそのデータソース操作のためのAPIを経由する必要があったりする。そういったモチベーションから本プロダクトを試してみたわけだ。
* [補足] Postmanでは、Postmanスクリプトを使うことでAPIリクエストの自動化、テストの実行、データの操作、環境変数の設定など、さまざまなタスクを実行が可能になる。これはJavaScript言語をベースとしてPostmanサンドボック環境で実行可能となっている。しかしサンドボック環境なので、ビルトインなライブラリは限定されており、現時点(2023年12月現在)では、データベースなど外部データソースへのアクセスにはREST APIなどHTTPインターフェースを経由する必要がある。
検証環境
環境 | 内容 |
---|---|
ローカルOS | macOS Ventura 13.6 (チップ Apple M2 Pro ) |
Java (CData API Serverの実行環境) | Openjdk 21.0.1 2023-10-17 LTS |
MySQL (今回のデータソース) | MySQL 5.7 (コンテナとしてDockerで実行) |
事前準備
CASを動かすためのJava環境と、今回のデータソースであるMySQL(コンテナ)を準備する。
Java環境の用意
宗教上の理由からOracle JDKではなく、OpenJDK(Eclipse Temurin(Adoptium))をインストールしている。
- Temurin™ for macOS aarch64 pkgをadopium サイトからダウンロード
- pkgファイルを実行。 Eclipse Temurin 21.0.1+12-LTSは
/Library/Java/JavaVirtualMachines/temurin-21.jdk
にインストールされる
チェック
$ java --version
openjdk 21.0.1 2023-10-17 LTS
OpenJDK Runtime Environment Temurin-21.0.1+12 (build 21.0.1+12-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.1+12 (build 21.0.1+12-LTS, mixed mode)
$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home
JAVA_HOMEの設定
export JAVA_HOME=`/usr/libexec/java_home`
MySQL on Dockerの設定
今回利用したMySQL on Dockerの一通りの設定は、こちらのリポジトリにアップしている。
まずは、MySQL on Dockerのための設定一式をgit clone。
git clone https://github.com/yokawasa-sandbox/mysql-docker.git
docker-composeでMySQLコンテナを起動。
cd mysql-docker
docker-compose up -d
次のような出力がされ、無事MySQLコンテナが立ち上がる。
[+] Building 0.0s (0/0)
[+] Running 3/3
✔ Network mysql-docker_default Created
✔ Volume "mysql-docker_mysql" Created
✔ Container mysql Started
次のように、立ち上げたMySQLコンテナにログイン
docker exec -it mysql /bin/bash
サンプルデータ追加のためのSQL文であるinsert.sqlがexamples/insert.sql
に配置しているので、それを次のようにINSERT。MySQLユーザーとパスワードは、docker-compose.ymlに記述してあるとおり、それぞれuser
、password
で実行する。
bash-4.2# cd /var/tmp
bash-4.2# mysql -u user -p db < examples/insert.sql
INSERTした内容を確認してみる。下記のように4つのテーブルができていればOK。
bash-4.2# mysql -u user -p db
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db |
+--------------------+
2 rows in set (0.01 sec)
mysql> use db
mysql> show tables;
+---------------+
| Tables_in_db |
+---------------+
| Articles |
| AuthorArticle |
| Authors |
| Books |
+---------------+
これで準備は完了。
CData API Server (CAS)の設定・実行
いよいよCASを設定、実行していく。
ダウンロードと展開
こちらのページよりCASのzipファイルをダウンロードする。 ローカルOSがmacOSなのでCross-Platform (Java)を選択してCDataAPIServer.zipダウンロード。
ダウンロードしたzipファイルを解凍。
unzip CDataAPIServer.zip
tree -L 1
.
├── admin
├── api
├── apiserver.jar
├── apiserver.logging.properties
├── apiserverRealm.properties
├── db
├── lib
├── logs
├── readme.md
├── service.sh
├── settings.cfg
├── tmp
└── webapp
CASには、最初からJetty(Webサーバー兼Java Servletコンテナ)がバンドルされたパッケージが含まれている。ファイルで言うとapiserver.jar。ほとんどのシナリオにおいてはこれでOKとのこと。
ちなみに、CASは、任意のJavaサーブレットコンテナ(Tomcat、JBoss、WebSphere、WebLogicなど)でホストすることもできるとのことで、したがってインストールパッケージには、これらJavaサーバーにデプロイするための.war
ファイルも含まれている。
ここでは、シンプルにJettyバンドルのjarファイルを実行する。
CAS ログインサービスの設定
CASの設定ファイルはwebapp/apiserver.xml
に配置されている。このファイルのloginServiceの箇所をみていると、次のようになっており、apiserverRealm.propertiesが、そのための設定ファイルであることがわかる
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">APIServerRealm</Set>
<Set name="config"><SystemProperty name="apiserver.home" default="."/>/apiserverRealm.properties</Set>
</New>
</Set>
apiserverRealm.properties
には下記フォーマットで各ユーザーのパスワード、ロールを記入することになっている。
user : pass, <user role>
とりあえず、ここでは次のようにadminユーザーのパスワードをadmin
、ロールをcdata_admin
で設定した。
admin:admin,cdata_admin
CASの開始
それでは次のコマンドでCASを起動。これでCASが http://localhost:8080 で受付可能となる。
java -jar apiserver.jar
管理用APIへのアクセス
http://localhost:8080/ にアクセスすると次のようなログインページが表示される。
ここで先程設定したadminユーザー(パスワードadmin)でログインする。
上記のようにライセンスが無いことを示すWARNINGが表示される。
ライセンス追加
情報
タブをクリックしてライセンス追加する。ここでは「30日の評価版をアクティベート
」から評価ライセンスを追加する。
DB設定追加
設定
タブをクリックして +接続を追加
をクリックしてREST API化したいデータベースを選択する。ここではMySQLを選択する。
次のように、MyQLのドライバークラスを選択肢、サーバーホスト、ポート、ユーザー、パスワード、データベース名といった接続設定を追加する。
リソースの追加
設定
> リソース
で リソースを追加
を選択する。上記で設定したデータ接続を選択すると、次のように追加するリソースを選択するボックスが表示される
ここでは、全てのDBのテーブルを選択してリソースとして登録する。
ユーザー追加
REST API利用のためのユーザーを追加する。設定
> ユーザー
で +追加
を選択する。ここでは、次のように user: myuser
として変更を保存
すると、認証トークン( 例: U3tpuIc0OXe0DjqDg67g ) が発行される。REST APIリクエストでこの認証トークンが必要となる。
これでMySQL連携のためのREST APIにアクセスする準備が完了。
REST APIへのアクセス
それでは、REST APIにアクセスしてみる。API
タブをクリックするとリソースアクセスのためのAPI一覧が表示される。ここではBooksテーブルリソースのためのAPIを選択。
ここではBooksのアイテム取得のためのAPIを選択してみる。すると次のように、そのAPIのドキュメントが表示される。見ての通り、サンプルリクエストのためのcURLやJavaScriptコードが表示される。また、アイテム取得内容を制御するためのリクエストパラメータの詳細も書かれている。
curlコマンドでテスト
それでは、上記のAPIドキュメントページに表示されているcURLをそのままコピペしてテストしてみる。MY_AUTH_TOKEN
のところは先程取得した認証トークンに置き換えが必要。
curl --header "x-cdata-authtoken: MY_AUTH_TOKEN" "http://localhost:8080/api.rsc/db_Books/"
実行すると下記のように無事結果が取得できた。ここではjqで出力結果のJSONを整形。
CDataAPIServer
curl --header "x-cdata-authtoken: U3tpuIc0OXe0DjqDg66g" "http://localhost:8080/api.rsc/db_Books/" | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 430 0 430 0 0 4575 0 --:--:-- --:--:-- --:--:-- 4831
{
"@odata.context": "http://localhost:8080/api.rsc/$metadata#db_Books",
"value": [
{
"ArticleTitle": "Buy a paper",
"Author": "James Elk",
"Copyright": "1932-01-01"
},
{
"ArticleTitle": "Buy a paper",
"Author": "Mary G. Lee",
"Copyright": "1932-01-01"
},
{
"ArticleTitle": "How write a paper",
"Author": "Tom M Ride",
"Copyright": "1934-01-01"
},
{
"ArticleTitle": "Sell a paper",
"Author": "Henry S. Thompson",
"Copyright": "1966-01-01"
}
]
}
Postmanでテスト
繰り返し実行、複雑な実行するならば、cURLではツラいですよね。というわけで、同じことを本命Postmanでテストしてみる。
Postmanではインポート
を選択すると下記のようなインポート用のボックスが表示される。ここのリクエストバーにcURLコマンドをそのままペーストするだけでAPIリクエスト設定がPostmanにインポートできる。
送信
ボタンを押して、無事同じ結果が得られた。
ここでは、取得系APIしか解説していないが、当然、更新系POST、PUT、DELETEなリクエストも問題なく実行できた。超絶に簡単である。
Postmanのプレリクエストスクリプトでデータベースのデータを取得する例
Postmanにおける外部データベースのデータ活用例として、APIリクエスト送信時に外部データベースのデータを活用してリクエスト送信データを変えたいケースがあるかと思う。
そういう場合、PostmanではAPIリクエスト送信前に実行されるプレリクエストスクリプトを活用するのが一般的である。プレリクエストスクリプトにて外部データベースからデータを取得し、変数を通じてリクエスト送信データをセットすることでリクエスト送信データを変えることができる。
以下、今回作成したREST APIを通じてBookアイテムを取得するスニペットです。取得したデータから必要な部分をご自分で取り出してリクエスト送信内容を変えてみてください。
const getRequest = {
url: 'http://localhost:8080/api.rsc/db_Books/',
method: 'GET',
header: {
'Content-Type': 'application/json',
'x-cdata-authtoken': '<認証トークン>'
}
}
pm.sendRequest(getRequest, function (err, response) {
console.log(response.json());
});
以下、スニペットをプレリクエストスクリプトで実行した結果をコンソール表示しているイメージ。
おわりに
CASを活用することで、データベースを超絶簡単にREST API化できることが分かった。
先述の通り、Postmanではその制約上、外部のデータソースと連携をするにはそのデータソース操作のためのAPIを経由する必要があったりするわけだが、CASを使えばそれが比較的簡単にできそうだ。
本質的には、その取得したデータをどう活用していくかが重要だったりするわけだが、とにかく外部データソース連携のための1つの選択肢としてCASは良さそう。