composer.jsonファイル内でのスクリプトのパスをUNIX/Windows互換にする

 PHPでのモジュール管理ツールであるcomposerでは、通常「composer update」と入力することでインストール作業が始まるが、インストール後に実行するスクリプトを記載することもできる。INTER-Mediator Ver.6では、composerの仕組みによりnode.jsをインストールして、「composer update」に引き続いて「npm install」を自動的に動かすようにしている。composer.jsonファイルの主要部分はこんな感じだ。package.jsonはすでに用意されている。composerはvendorというディレクトリを作り、そこにモジュールをコピーし、加えてネームスペースを元にしたファイル検索の仕組みが組み込まれる。単にコマンドを入れてみれば、nodeやnpmコマンドがvendor/binにコピーされているので、相対パスの記述が適切だと考えた。

{
"name": "inter-mediator/inter-mediator",
"version": "6-dev",
"time": "2019-03-07",
:
"require": {
"php": "^7",
:
"mouf/nodejs-installer": "*",
:
"scripts": {
:
"post-update-cmd": [
"./vendor/bin/npm --save-dev install"
],
:

 これで、macOS、Linuxでは正しくnpmコマンドが稼働するのではあるが、Windowsではエラーが出てnpmが動かない。PowerShellでは次のようにでる。最後の行は赤い背景になる。コマンドプロンプトでもほぼ同様だ。

> ./vendor/bin/npm --save-dev install
'.' is not recognized as an internal or external command,
operable program or batch file.
Script ./vendor/bin/npm --save-dev install handling the post-update-cmd event returned with error code 1

 やっぱり/だろうかと思ってディレクトリセパレータを¥にしてみた。もちろん、JSONなので¥¥とタイプするが、やはり同じだ。./を無くしても同じである。

 あれこれ調べて分かった。composerのドキュメントのNoteの所に書いてある。要するに、./vendor/bin(あるいは.¥vendor¥bin)へは、composerによってパスが通っているらしい。composerによってインストールされるコマンドの場合は、以下のように相対パスを書かなくても、npmコマンドの実行はできるということである。この記述だと、UNIXでもWindowsでも同一の記述でnpmコマンド実行ができる。

 :
"post-update-cmd": [
"npm --save-dev install"
],
:

Ubuntu Server 18上でのMySQL

別の記事でUbuntu Server 18で、INTER-Mediatorが動くまでのところを説明しました。

この中で、一部忘れていたことがあるので記載しておきます。MySQLのエンコードです。既出の記事の手順だと、MySQLのエンコードの指定をどこかでしないといけなくなります。mysql.cnfでもいいのですが、mysql.cnfにエンコード情報を入れるのではなく、PDOの接続文字列に

"charset=utf8mb4;"

の記述を追加するのが一番手軽だと思われます。スキーマにも、もちろん、

use utf8mb4;

を記述して、中身はUTF-8で記述すればいいですね。

Ubuntu Server 18でINTER-Mediatorを動かすまで

この原稿の内容は時間が経過して内容として不足しています。こちらの記事を参考にしてください。


Ubuntu Server 18.04.1 LTS上でINTER-Mediatorを動かす話です。とは言え、半分以上はLAMPサーバーセットアップの方法となるかと思います。なお、様々なコマンドがちょっとずつですが変わっているので、その辺りも含めてまとめておきます。

サーバーはVirtual Boxで稼働させました。このサーバーは単に実験するだけでなく、INTER-Mediatorのデモ用にも使いますので、外部からのアクセスが必要です。そこで、ネットワークは、NATとブリッジネットワークをこの順序に設定しておきました。そして、インストール途中で、ブリッジネットワーク側は、ローカルネットワーク側に存在できるような固定IPに設定します。この設定は後からでもできるのですが、最初からやっておくのが失敗がありません。NATが必要かどうかの問題もありますが、ブリッジネットワークを切っても外部に接続できるようにするために、こうしました。

さて、セットアップ後、apt-getなのですが、その前に、以下のように、レポジトリの設定ファイル/etc/apt/sources.listの3行いずれも末尾に「universe」という単語を入れておきます。こうしないと、PHPのいくつかのモジュールをインストールできませんでした。

$ cat /etc/apt/sources.list
deb http://archive.ubuntu.com/ubuntu bionic main universe
deb http://archive.ubuntu.com/ubuntu bionic-security main universe
deb http://archive.ubuntu.com/ubuntu bionic-updates main universe

(2019-01-03追記)ubuntu-18.04.1.0-live-server-amd64.isoというファイルでインストールしたところ、上記のuniverseを追加する作業は不要でした。最初から、レポジトリが読み込まれる状態になっています。

こうして、apt-getします。私はaptitudeでやる習慣ができてしまったので、aptitudeでやったのですが、試行錯誤しないのなら、apt-getでやることになるので、コマンドはapt-getで書きます。Apache、PHP7.2、MySQL、PostgreSQL、SQLiteまでを入れました。INTER-Mediatorを稼働するのに必要なPHP追加モジュールは、概ねこのようなあたりですが、追加が必要そうならこの文書を更新します。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y apache2 php7.2 libapache2-mod-php7.2
sudo apt-get install -y php7.2-mbstring php7.2-bcmath php7.2-curl php7.2-xml
sudo apt-get install -y mysql-server-5.7 mysql-client-core-5.7 php7.2-pdo-mysql
sudo apt-get install -y postgresql php7.2-pdo-pgsql
sudo apt-get install -y sqlite3 php7.2-pdo-sqlite

ちなみに、PDOのライブラリは、「-PDO」の付いていないもののエイリアスらしく、そういうメッセージが出て、例えばMySQLなら「php7.2-mysql」がインストールされます。

なお、Apacheの再起動が必要になることがあるかと思われますが、こちらのコマンドを使います。serviceコマンドも従来通り使えますが、systemdベースになっていますので、今現在の状況に合わせたコマンドを使いましょう。

sudo systemctl restart apache2

INTER-Mediator Ver.6を試すなら、composerは必須です。ホームフォルダをカレントにして以下のようなコマンドを入れることでインストールされます。レポジトリのものもあるようなのですが、この方法だと最新版が入手できるので、こちらを紹介します。他のサイトもほとんどこちらの方法を紹介しています。これで、コマンドプロンプトに「composer」と入れればヘルプが表示できます。なお、実際のcomposerの動作では、PHPのzipモジュールとunzipコマンドのインストールも必要なので、そのコマンドも記載しておきます。それから、gitも必要ですね。

cd
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer

sudo apt-get install -y php7.2-zip unzip
sudo apt-get install -y git

ここまでで、LAMPサーバーセットアップができているということになります。WebサーバーのルートにINTER-Mediatorをインストールするとしたら、例えば、以下のコマンドで行えます。

cd /var/www/html
git clone https://github.com/INTER-Mediator/INTER-Mediator.git

ファイルのダウンロード後に、INTER-Mediatorフォルダをカレントにして、composerコマンドを稼働します。composerを稼働させないと、PHPのプログラムへのパスが通りません。composerを使ったいろんな作業はあるのですが、ここではダウンロードしたものをそのまま動かす方法をまずは説明しました。

cd INTER-Mediator
composer update

MySQLへのrootユーザーでのログインは次のように行います。なんとなくPostgreSQLのようになってきました。rootパスワードを設定してどうこうするという状況ではなくなったようで、この状況に適応しましょう。管理者ユーザーで、mysqlコマンドを打つのでjはなく、sudo mysqlということです。パスワードは、sudoの時のパスワードで、つまりはログインしている管理者のパスワードを入力します。MySQLのrootのパスワードはつまりは指定しません。

sudo mysql -uroot

INTER-Mediatorのサンプルファイルを読み込むとしたら、こんな感じになります。もちろん、必要に応じて、管理者のパスワードを入力します。サンプルは、INTER-Mediator/dist-docsにあります。

sudo mysql -uroot < sample_schema_mysql.txt

一方、PostgreSQLは、以前からpostgresユーザーでの接続を行うことで、データベース接続していましたが、その点は変わりません。sudoでpostgresユーザーになるので、現在のログインしている管理者ユーザーのパスワードを知っておく必要があり、postgresユーザーのパスワードは利用しません。コマンド接続と、INTER-Mediatorのサンプルの読み込み例を記載します。サンプルは、INTER-Mediator/dist-docsにあります。

sudo -u postgres -i

sudo -u postgres psql -c 'create database test_db;'
sudo -u postgres psql -f sample_schema_pgsql.txt test_db

SQLiteは特に違いはありません。サンプルは、INTER-Mediator/dist-docsにあります。

sudo mkdir -p /var/db/im
sudo sqlite3 /var/db/im/sample.sq3 < sample_schema_sqlite.txt
sudo chown www-data /var/db/im
sudo chown www-data /var/db/im/sample.sq3

[IM] FileMaker Server 17とINTER-Mediator

FileMaker 17が発売されました。そして、FileMaker Server 17がリリースされました。ちょっとずつ変わりながら毎年アップデートするFileMakerですが、サーバーは結構変わっています。大きなところでは、管理コンソールがグッと今風なデザインになり、かっこよくなりましたが、その代わり、管理コンソールで設定変更できない項目が出てきました。その辺りがINTER-Mediatorの利用に大きく関連するので、INTER-Mediatorの利用に重点を置いて、変わった部分を説明しましょう。

PHPはインストール直後は未導入

FMS16までは、セットアップ時に選択すればPHPを設定できましたが、FMS17は初期状態ではPHPは使えない状態になっています。もし、PHPを別のサーバーで動かすなら、もうFMSのWebサイトにはPHPは不要ということになりますが、FMSのWeb機能を自分のマシンで動かして検証するなどの作業をしたい方も多いでしょう。その場合、以下のようにコマンドを入れます。$に続く部分が自分で入力するコマンドで、太字にしてあります。fmsadminコマンドで、管理コンソール上では見えなくなったいくつかの機能の設定を行うようになったのです。ユーザー名とパスワードを聞かれれば、FMSの管理者のユーザー名とパスワードを入力します。

$ fmsadmin set cwpconfig enablephp=true
username (msyk):admin
password:
EnablePHP = true
Restart the FileMaker Server background processes to apply the change.

macOSの場合は、「ターミナル」を使います。ログインしているユーザーが管理者の場合には、sudoをしなくても、fmsadminは利用できます。Windows 10の場合、最近まで、スタートメニューの右クリックででてくるメニューで管理者権限でコマンドプロンプトを起動できましたが、いつの間にかこの項目はでなくなっています。スタートメニューの右クリックで「Windows PowerShell(管理者)」を選択して、PowerShellを使いましょう。「コマンドが違うのでは?」と思われるかもしれませんが、上記のfmsadminも、以下のnetコマンドもPowerShellで使えるので安心してください。

このコマンドを入力すると、最後に再起動をするように出てきます。ここで、Webサーバーだけの再起動(HTTPServerフォルダにあるstop、startというファイルをsudo touchで更新)でやってもPHPは稼働しません。それから、CWP(Custom Web Publishing)の再起動も同様です。以下のコマンドで機能の再起動を行います(松尾さん、ありがとうございます)。もちろん、FileMaker Serverの管理者のユーザー名とパスワードを入力する必要があります。

fmsadmin restart httpserver -y

以下のように、FMS全体の停止と起動を行う必要があります。macOSの場合は次のように2つのコマンドを入れます。

sudo launchctl stop com.filemaker.fms
sudo launchctl start com.filemaker.fms

Windowsの場合は、以下の2つのコマンドを入力します。なお、Windows 10の場合は、他に考慮点が色々あるので、この記事の最後の方にそれを記載をします。

net stop "FileMaker Server"
net start "FileMaker Server"

これで、phpinfo()関数を動かすと、次のように、Ver.5.6.24が稼働していることがわかります。なお、info.phpファイルの中身は、phpinfo()関数だけでなく、タイムゾーン指定を入れないと警告が出て情報は表示されません。例えば、info.phpファイルは次のように作ります。

<?php date_default_timezone_set("Japan"); phpinfo(); ?>

PHP自身は古いビルドのままですし、Ver.7.2が主要リリースな今時にVer.5.6なので、アップデートする気はないというところが感じられます。

つまり、FMS17をインストールすると、PHPの実行環境はインストールされているものの、利用できる状態になっていなかったということです。ちなみに、macOSの場合は、Apache2の主要設定ファイルである/Library/FileMaker Server/HTTPServer/conf/httpd.confの最後に、

Include '/Library/FileMaker Server/Web Publishing/publishing-engine/php/sierra/httpd.fmi.conf.php'

という行が加わり、モジュールが読み込まれます。Windowsでも、FileMaker ServerフォルダはC:¥Program Files¥FileMakerにありますが、そこからのパスはほぼ同じような場所にPHPの実行環境が用意されていますが、IISにサイトを追加してWebサーバーとして稼働するようにしています。phpinfo()関数でphp.iniファイルを確認して、必要であれば設定を変更しましょう。

db-class=”FileMaker_FX”を指定する場合

FX.phpを使ってFileMaker Serverへ接続する場合を説明しましょう。INTER-Mediator 5.7/6現在、現実にはFX.phpの一部分だけを使っていますが、何れにしても、以前からあったXML共有を利用してデータベースアクセスしています。

XML共有を利用するには、まず、Web公開エンジンをオンにします。管理コンソールで、コネクタのページを開き、左側のリストで「Web公開」を選択し、右側の「Web公開エンジン」にあるボタン(右のほうにある左右に動くスイッチ)が全体的に青くなるようにしてオンにします。しかし、これだけではありません。

XML共有をオンにするには、さらに、以下のような$以降のコマンドを入力します。もちろん、FMSの管理者アカウントで認証が必要です。このコマンドに関しては、再起動は不要です。

$ fmsadmin set cwpconfig enablexml=true
username (msyk):admin
password:
EnableXML = true

このように、「Web公開エンジン」のオン、そしてXML共有をオンにすることの両方が必要になります。

db-class=”FileMaker_DataAPI”を指定する場合

FMS16でプレビュー扱いだったFileMaker Data APIも、FMS17では正式機能となり、ライセンス価格も「ダウンロードデータ量」に関連することに決まりました。ユーザー数で考えれば幅が広くなるWebサイトの事情を考慮したという点では評価できると考えます。1年間のライセンスの場合、24GX人数までが購入価格に含まれた分量ですが、ともかく、データ転送量を見積もらないと、かかるコストが分からないという状況になりました。

FileMaker Data APIの正式版は、ある意味で「バージョン1」と呼ぶのが適切でしょう。API呼び出しのURLがプレビュー版と大きく違っており、URLに「v1」という文字があることからも、API自体にバージョン管理を今後は行うということを示唆しているものと思われます。

FileMaker Data APIに応答するようにするには、管理コンソールで、コネクタのページを開き、左側のリストで「Web Data API」を選択し、右側の「Web Data API」にあるボタン(右のほうにある左右に動くスイッチ)が全体的に青くなるようにしてオンにします。これだけでよく、コマンドの入力は不要です。

なお、INTER-Mediatorは、FMDataAPIというライブラリを利用して、FileMaker Data APIを利用しています。FMDataAPIはVer.8で、プレビュー版からバージョン1へと対応APIを変更しました。FMS17リリース直後からVer.8は公開していますが、INTER-Mediatorで利用できるようになるためには、INTER-MediatorにあるFMDataAPIをアップデートしないといけません。アップデートするのは簡単ですが、FMS16のFileMaker Data APIは使えなくなります。もっとも、プレビュー版のAPIで真剣に構築していることはないだろうという見込みもあるので、単にどどーんとアップデートしてもいいのですが、その辺り、現在は検討中というところです。アップデート情報はFacebook等で公開します。

Windows 10でFileMaker Server 17

FileMaker Serverは、以前からWindows Serverが対応OSとなっており、Windows 10は対応OSではありません。また、FMS14に関するFileMaker社の文書では、「互換性はありません」となっています。ところが、Windows 10 Pro に FileMaker Server をインストールする によると、FileMaker Server 14/15のインストールができるようにする方法が書かれています。開発者としては手元のWindowsでFMSが動いて入れば便利だと思うところでもあるので、FileMaker Server 17がWindows 10で稼働するかどうかを試してみました。前述の記事のようにインストーラが動かないということはなく、インストーラは問題なく動き、インストールは可能です。ただし、インストーラが動くとは言え、様々なエラーメッセージをうまく捌かないといけない模様であり、「簡単ではないかもしれない」と言ったところです。そこで、PHPを動かすところまでを実現するためにどうすればいいかを確認しました。なお、FileMaker社は稼働するという保証をしていないので、Windows 10でのFMS利用はご自分のリスクで進めてください。

実際に確認したのは、Windows 10 Proに、バージョン1803のアップデートを当てたPCです。IISが稼働していない状態でインストールをすると、途中で次のようなメッセージが出てきて、インストールは途中で終わってしまいます。

そこで、IISをあらかじめ起動しておきます。スタートメニューを表示した時に左端に見えるギアのアイコンの「設定」を選択して、設定ウインドウを表示します。そして、「アプリ」を選択します。そして、右端にある「プログラムと機能」を選択し、懐かしいコントールパネルの「プログラムのアンインストールまたは変更」を表示し、左側にある「Windowsの機能の有効化または無効化」を選択して「Windowsの機能」ウインドウを表示します。ここで「インターネットインフォメーションサービス」のチェックを入れます。黒い四角になるのは下位の項目が全部チェックされているわけではないということを意味しています。ここで、World Wide Webサービス>アプリケーション開発機能と階層を下り、「CGI」のチェックを入れておきます。このチェックを入れておくのがポイントです。他はそのままでいいのですが、必要に応じて他の機能を入れてもいいでしょう。OKをクリックします。もし、再起動を求められたら再起動をしてください。

この準備をした上で、FileMaker Server 17のセットアップを行えば、概ね問題なく稼働するもようです。インストール途中で以下のようなダイアログボックスが出てくれば、「Webサイトを無効にする」をクリックしてください。これはIISのデフォルトのサイトをオフにして、FileMakerでセットアップされるサイトだけを利用するためです。

こうしてセットアップが終われば、最初に説明したようにコマンドを入れればPHPが利用できるようになります。ただし、INTER-Mediatorを稼働させるという観点では、初期状態のPHPのモジュール読み込みは十分ではないので、php.ini等の設定を変更する必要があります。これについては、近日中にまとめたいと思います。

IISの設定を見るには、スタートメニューを右クリックして「コンピュータの管理」を選択します。「サービスとアプリケーション」の下位項目に、IISがあります。Default Web Siteは停止状態になり、FileMaker Serverのセットアップにより、FMWebSiteという設定が増えていることがわかります。

ここで、PHPを稼働させる設定は、「ハンドラマッピング」の中にあります。その項目の詳細設定ダイアログボックスは次のようになっています。パスは、C:¥Program Files¥FileMaker¥FileMaker Server¥Web Publishing¥publishing-engine¥php¥php-cgi.exeが指定されています。

ちなみに、WindowsでのPHPの稼働方法をチェックすることも含めて、fmsadmin set cwpconfig enablephp=trueを使わないで、IIS上でPHPを稼働できるかを試してみたのですが、その時には、以下の2つのパスのフォルダに、IIS_IUSRSグループに読み取りと実行の権限を与える必要がありました。要するにWeb公開するフォルダと、PHPの実行モジュールへのアクセス権を設定する必要があるということでしょう。

C:¥Program Files¥FileMaker¥FileMaker Server¥HTTPServer¥conf
C:¥Program Files¥FileMaker¥FileMaker Server¥Web Publishing¥publishing-engine¥php

他に、アプリケーションプールの詳細設定で、32ビットアプリケーションの有効化をtrueにしてやっと動いたということもあるのですが、FileMaker Serverに自動設定させた結果では、アプリケーションプールの設定はfalse(既定値)のままでした。

以上のように、Windows 10でもFileMaker Server 17は使えたのですが、なんども書きますが、対応OSではない点を理解した上で対処をしてください。

INTER-Mediatorのレコード数制限の実装

INTER-Mediatorのことをブログで書くのが久しぶりな気がしているが、以前のように、設計書代わりにブログを書いておく。INTER-Mediatorのコードにタッチしていない方はなんのことか分からないと思うので、最初にその点を指摘しておく。

INTER-Mediatorでは、ページネーションコントロールを自動的に生成して、例えば30レコードずつ表示するような仕組みを設定だけで実現している。しかしながら、その後に、ポップアップメニューからレコード数制限をできるようにしたり、Master/Detail形式のUIを実現したりと、1度に表示するレコード数に絡む機能を追加してきた。3年ほど前に、かなり混乱した感じになったのでリファクタリングをしたが、バグレポートをもらい、相変わらず怪しい部分があることに気づいた。ここで、根本的に直したいと思うのだが、今までの方法で欠けていたのは「ルールの明確化」だった。そこで、ルールを作って実装というか、リファクタリングをしたいと考える。

まず、現状(5.7+α)で、どんな要素が関連しているのかをまとめて見たい。レコード数に影響するUI要素は次のものである。

  1. ページネーション
  2. ポップアップメニュー(data-im=”_@limitnumber:コンテキスト名” の属性があるSELECT)
  3. Master/DetailのDetail側(navi-control=”detail”、詳細側なので常に1レコードにしたい)

コンテキスト定義のキーで、関連するものは次のとおりである。

  1. records
  2. maxrecords
  3. paging
  4. relation
  5. navi-control

さらに、関連するプロパティを挙げると次のとおりである。プロパティと言いつつ、オブジェクトは1つなので、事実上のグローバル変数である。なお、以下のプロパティの3, 4, 5は、getter/setter実装している。ローカルストレージ等を利用してページ移動してもパラメータの記憶をしたいためだ。

  1. INTERMediator.pagedAllCount
  2. INTERMediator.totalRecordCount
  3. INTERMediator.startFrom
  4. INTERMediator.pagedSize
  5. INTERMediator.pagination

これれらの仕組みをどのように解釈するかという問題である。

まず、INTERMediatorオブジェクトのプロパティについては、paging=trueのコンテキストに対してページネーションを動作させるためのものであるので、ここでは「ページングを特定のコンテキストに対して実施する」という決定がなされた後のものである。したがって、UIとコンテキスト定義の内容について、どのように解釈をすべきなのかを、まずは決めなければならない。ここを曖昧にしていたのが、バグが常に治らない原因と考える。しかし、基準も何もない。よって、「UIが自然かどうか」という観点で推測しながら決め事をしなければならない。

前提条件1:
ページネーション処理は単一のコンテキストのみ

この点は、異論はあるかもしれないが、複数のコンテキストにページングを配置すると、画面に複数のページネーションコントロールが登場して、混乱をしかねないUIとなる。適切なUI設計では複数のページネーションは不要と考える。これを前提とする。また、1コンテキストに複数のページネーションコントロールを用意するということも同様にやらないことを前提とする。

前提条件2:
Master/Detail形式のUIでは、ページネーションはMaster側にだけ適用される

MasterにもDetailにもページネーションが欲しいという声が聞こえてきそうであるが、それぞれを同時に表示することも仕組みとしては持っているため、ページネーションはMasterだけに適用させたい。Detail側にレコード移動の機能を組み込めないようにしたいのである。なお、どうしてもそうしたいと思う場合には、Master/Detailの機能を使わないで、Detailと同一内容のページファイルを用意して、普通にページネーションを利用できる。適切な対応策があるので、この前提条件はデグレードには当たらないと考える。

優先順位1:
そのコンテキストで取り出されるレコード総数はmaxrecordsを上回ることは絶対にない

この仕様の優先順位が高いとしたら、サーバー側での検証とレコード数の修正は必要であるし、通信直前に処理するなど、UIから遠いところで処理をしないといけない。

優先順位2:
navi-control=detailのコンテキスト場合、レコード数は常に1以下とする

ある時点でこの設定を入れた。優先順位を高めにして、他の設定より優先される方が、矛盾するコンテキスト設定してもうまく動く模様であるが、一方、間違いに気づきにくいということにもなる。

優先順位3:
ポップアップメニューがあればそれに従う

ポップアップメニューは、ローカルコンテキストに記録するのであるが、ローカルコンテキストのバインド処理は、ページ合成処理の最後の方にやっている。少なくとも、limitnumber:*の値の処理を、ページ合成前にもしなければならないし、本当に初めてページを開くときはローカルコンテキストがセッションに残されていないので、ノードを探る処理も結果的に入れておく必要がある。ここの改造は、コードの追加を伴う。

優先順位4:
recordsキーの値に従う

これは順当なルール。なお、relationがあるとレコード数の制限はなくすということを一瞬考えたが、関係レコードの上位3件だけ表示したいということもあると思う。結果的にrelationキーは考慮しなくてもいいのではないかと思う。

これらのルールで得られた「レコード数」を元にしてレコードを取得する。ページネーションを利用するコンテキストなら、ページネーションとの連動が必要になる。このページネーションとの連動部分が、コードとしてはうまく分離されていないのが現状である。上記のルールで決まれば、それに応じてページネーションを設定するという風に、レコード数とページネーションの処理順序を決めて、依存関係をシンプルにするようにリファクタリングを進める必要があると考えられる。すなわち、

方針:
レコード数決定プロセスとページネーション処理を分離し、レコード数の決定を先に行って結果を必要ならページネーション処理に渡す

ということになる。この方針で行ってみようと思う。

JavaScriptの通信がPendingとなった理由は通信の問題ではなかった

JavaScriptとPHPで構築しているINTER-Mediatorで、分かりにくいバグに遭遇してしまったので、記録の意味も含めてここに書いておく。そもそも発端は、Ver.5.6-RC2を入れて動かしていたアプリケーションで、そろそろVer.5.7もリリース近いので、入れ替えるかと思って入れ替えたのが直接の原因なのだが、その瞬間にバグが顕在化したのならまだしも、ある程度時間が経過してから顕在化したので、根本的な原因を突き止めるのに非常に労力が消費されてしまった。

不具合が発生したのは、勤務先の業務システムで、スタッフ向けのページはかなり重たい動作のものある。全てのページで問題が出ないで、一部の「重たいと思われる」ページでのみで不具合が顕在化した。ここで、まず判断を狂わせることになる。システムは、サクラVPSで運用している。ここ数ヶ月、徐々にレスポンスが悪くなっている感じもあったので、プロバイダやネットワークをまずは疑ってしまった。不具合による結果は、ページを表示しようにもページ自体がフリーズしてしまうのである。ログインパネルはちゃんと出るが、正しいユーザ名とパスワードを入れると、フリーズする。これに気づいたのは2018年2月の上旬だ。

当然ながら、まずやることはデバッガでの確認だ。すると、以下のように、Statusが(Pending)となている。サーバーのログを追ったところ、Apache2はステータス200でデータを全部出し切っている。クライアント側で通信に入ったものの、一切のデータ受信ができない結果になっている。色々観察した結果、ページごとにPendingになるタイミングやこのページでの行番号は違うのもの、同一ページでは常に同じタイミングで発生した。ちなみに、Chromeだとこれが発生すると高い確率でそのタブを閉じることができず、他のタブは利用できる状態であるにも関わらず、Chromeの強制終了が必要になる。

今まで動いていたという気持ちがあると、当然ながら、アプリケーション側に問題はないとまずは考えてしまう。これも、後から考えれば間違いなのだが、エンジニアの皆さんはとりあえず人のせいにしてしまう気持ちはよく分かると思う。折しも、色々探すと、サクラのサポート情報で、「さくらのVPSで回線速度が遅くアクセスに時間がかかります。」というのがあった。ページのフリーズと、遅くなるのは違うのではあるが、こういう時には楽観的に物事を見てしまう。なんだ、原因分かっているんだと思いつつ、「さくらのVPSにおいて、不特定のVPS収容ホストとクライアント環境(プロバイダ等)の組み合わせにより、 さくらのVPSからのダウンロード方向の通信に遅延が発生する場合があります。」という記述をみて、ネットワークの問題があるということに意識がかなり振られてしまった。

当然ながら、ここにある対処をしたのだが、結果は同じだった。むしろ、どのページも遅くなったので、仮にうまくいっても恒常的な対処にはならない。しかしながら、「ネットワークに問題がある」というところで判断がスタックしてしまった。もし、ネットワークに問題があるとしたら、プロバイダを変えるか、職場のネットワーク内にサーバーを立てるしかない。GMOクラウドのVPSは無料で試せるので、ともかく移動して動かして見た。結果は同じだ。同じページで、同じようにフリーズする。GMOではネットワークの問題は解決しないとしたら、一度、自宅のサーバーにセットアップして、自宅内でアクセスするとどうなるかをチェックして見た。なんと、同じようにフリーズする。また、別の軽いページを改良している時にも、フリーズが発生した。つまり、「ネットワーク」「重いページ」はどうも原因ではないという結論になった。

しかし、なんでPendingになるのか?色々検索すると、Ajaxがデッドロックしたみたいな書き込みがあった。しかし、それへの回答でも、JavaScriptはユーザープログラムは絶対に並列的に動作しないで、処理を1つずつしかしないのだから、他の言語等で発生する問題が同じように発生する可能性は低いと書かれている。もっともだ。しかも、INTER-Mediatorのこのバージョンは、Ajaxを非同期では利用せず、同期通信しているため、フレームワーク内で複数の通信が発生することはない。なお、次のバージョンでは完全に非同期通信を行うようになる。

前述のChromeのデバッガを見ると、CSSの通信がPendingになっている唯一、並列的に通信が発生するとしたら、CSSのサーバーからの取得と、INTER-Mediatorのデータベースアクセスの通信が並列にはなりうる。ちなみに、CSS自体もサーバーで生成しているので、URLは.phpになっている。そこで、フレームワークをいじってCSSアクセスのlinkタグを突っ込まないようにして見た。それでも同じところでフリーズする。やはりこれも原因ではない。

ここで、根本的な原因が全くわからない状態になった。ネットワークでも通信でもないということで、フレームワークに問題があることはほぼ明白になった。そして、2017年9月のVer.5.6.1に戻して見たところ、問題なく動いた。これで、INTER-Mediator側に問題があることが確実となった。INTER-MediatorはGitHubのレポジトリにコードが残っている。そこで、どのコミットでバグが発生したかを突き止めることにした。大雑把に2分割をしながら、2018年1月のあるコミットであるところまで突き止めた。コードを見ても、明らかに通信ではない。通信に問題があるが、原因は通信でないということはさらに明白になった。

しかし、見当がつかない状態と、ここまで絞りきれても原因の特定まではできない。このコミットでファイルは4つ変更されているが、1つはメタデータで処理には関係ないので、そのうちの3つのどれかである。そこで、ファイルを1つずつ、前のコミットに戻すことで、INTER-Mediator-Calc.jsに問題があることが分かった。diffの結果はあれこれあるが、setUndefinedToAllValuesにメソッドしか変更していないので、問題はここにある。何れにしても、計算式の処理部分に問題があることが分かったのである。

ここで腹を括って、地道にステップ動作をさせて見たところ、ついに問題の根本が分かった。325〜335行のdoループが、ある条件の場合だけ、無限ループしている。つまり、ここのループ処理にバグがあったのだが、ポップアップメニューのタグ要素に計算式の結果を適用する場合だけ、無限ループし、その他のタグ要素の場合には無限ループにならず、間違えたコードだが正しい結果が得られているという状況になっていたのである。直したところ、えらく時間がかかるようになったので、処理を効率化して高速化する必要もあったものの、ともかく修正ができて、Pendingは出なくなった。原因追及から修正完了まで、1日かかってしまった。

結論は明らかだ。ページがフリーズしたら無限ループを疑えということになる。だが、なんで、こんな処理が入っているのかという点もあって、モデルをさらに改良してここで問題になったコードは取り除く予定ではあるものの、「動いている」つもりになっていたので、後回しになってしまっているのである。テストでクリアできないかということもあると思うが、ページ展開していないとテストのしようがない部分であり、単体テストではカバーできていなかった。現在、Seleniumベースでの統合テストを組み込んでいるところであり、そこで、計算式のテストページに、ポップアップメニューに計算式を仕込んだものも作っておいた。やはり、見つけにくいバグは、テストから漏れている箇所に存在するということだ。

なんとも当たり前なことの確認に、ひどく時間がかかってしまったのではあるが、自戒の意味も含めてブログに記録する。

FileMaker Server 16のREST APIをmacOS上で試用する場合

FileMaker Server 16をまずは手元のMacにインストールして使ってみようという方も多いだろう。ここで、FileMaker Data API(REST API)を使用する場合にPHPのcurlライブラリを使うと、「SSL: CA certificate set, but certificate verification is disabled」というエラーメッセージが返ってくる。httpsでの通信が推奨され、証明書が検証できないと通信をしないということが当然となって来ているが、とはいえ、試用なので自己署名証明書で運用できないかとPHPの様々なパラメータを触ってみたところで、上記のエラーないしは別のエラーが出る。ということで、色々調べてみると、macOSに入っているopensslのバグで、サーバー検証をしないという設定ができないということらしい。homebrewから入れ直す方法など、色々紹介されているが、何をとっても大事になってしまう。

というところで、早速、FileMakerホスティングで有名なエミックの松尾さんが、ルータとなるスクリプトを公開された(一部、修正したい箇所があったので、筆者がフォークしたものもある)。FileMaker ServerのREST APIは、httpで接続してもhttpsにリダイレクトされるが、その背後のNode.jsが開いている3000ポートを目指して接続することで、httpでも処理が進められる。ただ、ヘッダをうまく使って同じホストからの接続しかできないような仕掛けがあるため、「直接3000番ポートに接続する」よりも、ルータスクリプトを使う方が楽である。

ルータは、WebアプリケーションとFileMaker Serverの中間に位置しており、WebアプリケーションがFileMaker ServerへのRESTコールを行う代わりに、ルーターに対して呼び出しを行う。ルーターはhttpsを使わずにFileMaker Serverを呼び出し結果を得て、それをWebアプリケーションに返す。動作としては「プロキシ」であるが、名前がrouterなので、ルーターと呼ぶことにする。

ルーターを利用できるようにするには、ダウンロードしたファイルrouter.phpを、以下のようなコマンドで起動する。ファイルがある場所をカレントディレクトリにして、コマンドを入力する。

php -S 127.0.0.1:8090 router.php

ここで、127.0.0.1は自分自身に接続するIPアドレスであり、コロンに続いてサーバーが利用するポート番号を指定する。他のプロセスが使っていない番号を使う必要がある。なお、使用を止めたい場合は、Terminalの画面でcontrol+Cキーを押す。

筆者が作ったAPIを利用するためのクラスFMDataAPIでルーターを利用したい場合、利用方法のサンプルを示したFMDataAPI_Sample.phpであれば、最初の方にあるインスタンス化している部分を記載のように修正する。パラメータを2つ追加して、8090ポートを使うことと、httpプロトコルを使うように設定すれば良い。他は変更が必要ない。もちろん、8090はルーターを起動する時に指定したポート番号を使う。IPアドレスも、基本的に起動時に設定したものを指定する。

修正前:
$fmdb = new FMDataAPI("TestDB", "web", "password", "127.0.0.1");

修正後:
$fmdb = new FMDataAPI("TestDB", "web", "password", "127.0.0.1", 8090, "http");

一方、FMDataAPITrialにあるスクリプトは、まず、lib.phpファイルにある以下の関数の返り値に、ルータ側のポート番号を指定する。

function targetHost()
{
    return "127.0.0.1:8090";
}

そして、Test2.php以降、プログラムの中のhttpsの記述をhttpに切り替える。callAPI関数の最初の引数が全てhttpsになっているので、httpに書き換える。

$host = targetHost();
$result = callAPI(
    "http://{$host}/fmi/rest/api/auth/TestDB",
    null,
    json_encode(array(
        "user" => "web",
        "password" => "password",
        "layout" => "person_layout",
    )),
    "POST");
resultOutput($result);

なお、phpコマンドで、router.phpを起動する時、127.0.0.1ではなく、localhostで指定した場合、上記の修正箇所のIPアドレスは、全てlocalhostで記述する。127.0.0.1では稼働しないので注意する必要がある。phpコマンドで起動する時に127.0.0.1を指定すると、Webアプリケーション側の設定は、127.0.0.1でもlocalhostでもどちらでも良いようだ。FileMaker Serverはかなり以前からIPv6ベースで動いているのだが、localhostとした場合、どこかで127.0.0.1ではないIPv6のアドレスとして識別しているのではないかと想像できるのだが、詳細は分からない。

ちなみに、FMDataAPIを使ったシステムを運用する時、原則としては正しい証明書でhttpsで運用することが原則だ。もちろん、盗聴されないためというのが大きな理由であるが、ホストを偽ってデータを収集されたり嘘の情報を流されることも防ぐ必要がある。httpsでの運用は、Let’s Encryptで無償で利用できるなど、年々手軽になってきているので、面倒がらずに対応すべきだというのが1つの結論である。

では、PHPを稼働させるWebサーバーとFileMaker Serverが同一のホストであれば、盗聴の心配はないのではないかと言うことになる。Firewallでポートを塞げば、それでいいのではないかと言う話もなくはない。ただ、FileMaker Data APIだけにWebサーバーを使うと言うことはあまりないと思われるので、Firewallの設定はちょっと面倒ではないだろうか。絶対に外部からFileMaker Data APIは利用しないで、サーバー内部に限るのであれば、httpでの運用でも問題はないかもしれないが、必ずサーバーの内部からの利用しかしないと言うことを管理者が人手で保証しないといけなくなる。通常、httpsで運用する手順を踏む方が楽なのではないだろうか。

自己署名証明書の問題も同様だ。サーバー内部に限るのなら、詐称のしようもないと考えることができる。これも、「絶対にサーバーの内部からの利用しかしないと言うことを管理者が人手で保証する」と言うモデルであり、むしろ、そういった人的な縛りよりもhttpsでの運用をする方が問題が発生しにく状況であると言えなくないだろうか?

そう言うことで、httpや自己署名証明書での運用は自己責任が大きいので、FileMaker Data APIでアプリケーションを開発したら、本番はhttpsでの運用を目指すようにすべきである。

なお、筆者の作ったFMDataAPIクラスは、デフォルトは証明書の検証をしない状態で稼働するので、そちらは開発中での利用を想定している。実際に正しい証明書が用意できれば、以下のメソッドを呼び出す。そうすれば、証明書の検証を行うようになる。自己署名でないこと、期限、アクセスしているサーバ名と同一なのかが検証される。

$fm->setCertValidating(true);

すなわち、FMDataAPIクラスは、証明書の検証もメソッドでコントロールできるようになっている。

FileMaker Data APIを使えるようにする

FileMaker Server 16に搭載されたFileMaker Data APIについて、実際に利用できるようになるまでの手順を紹介しよう。FileMakerでのWeb開発やFileMaker Data APIの意義については、「FileMaker 16より搭載のFileMaker Data APIとは」を参照していただきたい。

FileMaker ServerのインストールとAdmin Console

FileMaker Data APIの有無に関わらず、FileMaker Serverをインストーラを使って通常通りインストールを行う。展開アシスタントの「Web公開」のところで「FileMaker Data API」のチェックを入れる必要がある。このチェックに相当する機能は、アシスタント利用後でも設定できるが、使用することが分かっているのなら、インストール時にセットするのが手軽だろう。

FileMaker Serverのセットアップ後、「ステータス」のページでは、「FileMaker Data API」の状態を表示する領域が見えており、機能が動作しているかどうや接続数が参照できるようになっている。ここでは詳細な設定はない。

細かい設定は左側で「Web公開」を選択し、上部のタブで「FileMaker Data API」を選択することで表示できる。こちらでは、機能の有効/無効とログについての設定が可能である。

左側で「ログビューア」を選択してログを見るとき、「ログ」ボタンをクリックしてログの選択する箇所で「FileMaker Data API」についてのチェックボックスが表示される。こちらをオンにするとログを参照でき、アクセスするごとに1項目ずつ追加され、日時やURLのパス、クライアントIP、エラーの様子などが記録されていることが確認できる。

FileMaker Data APIに応答するデータベース

データベース自体にも、FileMaker Data APIの利用の可否を指定する部分がある。XML共有やFileMaker Serverへの接続等でも指定した「拡張アクセス権」の設定が必要である。FileMaker 16では、「fmrest」というキーワードのFileMaker Data APIを利用する拡張アクセス権が存在している。データベースを開いて、「ファイル」メニューの「管理」から「セキュリティ」を選択して表示されるダイアログボックスで「拡張アクセス権」のタブをクリックして確認できる。

データベースに設定されたアカウント、あるいは外部のアカウントは、「アクセス権セット」のいずれかの項目に結びつけられる。そのアクセス権セットの設定で、fmrestにチェックが入っている必要がある。このアクセス権セットを選択しているアカウントが、FileMaker Data APIを利用できる。

FileMaker Data APIのマニュアル

FileMaker Serverをインストールしたホストの16001番ポートを開くと、「FileMaker Server 16 開始ページ」が開く。そのページの「Web公開リソース」にある「FileMaker Data API マニュアル」をクリックすると、マニュアルが参照できる。このマニュアルはまだ日本語版は存在していない。日本語のマニュアルは同じ開始ページの「FileMaker 16 Data API ガイド」を辿れば参照できる。

例えば、FileMaker Data API マニュアルにあるREST APIの記述を見てみよう。

REST APIは、簡単に言えば、Webブラウザのアドレスバーに入れるようなURLをサーバーに遅れば結果が返ってくる仕組みだ。ならばSafariやChromeでちょっと試そうかと思うかもしれないが、原則、返って難しい。ちなみに、こうしたREST APIを試す開発ツールとして「PAW」などがすでにあり、APIの利用が成熟していることの現れであるとも言える。

このGet RecordはrecordIdを与えてデータベースの1レコードを得るものである。/fmi/rest…という部分はURLのパスとして与えるものである。その中の「:solution」はデータベース名に置き換えるが、:は含めない。ちなみに、このコロンはNode.jsでのプログラミング経験者にとっては見覚えがある表記だろう。例えば、TestDB.fmp12のpostalcodeレイアウトにあるrecordIdが25のレコードを得るには、FileMaker Serverと同じホスト上でAPIにアクセスするとしたら、

https://localhost/fmi/rest/api/record/TestDB/layout/25

というURLにアクセスする。ここで、パスの上に緑のボックスで「GET」と書いてあり、通常のWebブラウザでのアドレス手入力と同じくGETメソッドでアクセスすれば良いということになる。他にPOSTだけでなく、PUTやDELETEメソッドも使うAPIもある。POSTやPUTではURL以外にリクエストのボディ部にどんなJSONデータを指定するのかが記載されている。

Headerの項目を見て欲しいが、ここの記述は、リクエストのヘッダに、

FM-Data-token: XXXXXXXXXXXXXXX

といった形式のデータを追加しないといけない。従って、WebブラウザでURLを入れれば済むと言う話ではなくなるわけだ。このヘッダの値は、事前に呼び出したLogin APIの結果を入れる。こうした点は詳細には書かれてはいないが、APIドキュメント全体を読むとそうした事実もわかる。

ページの下の方には、どんなデータが返されるのかが記載されているが、「Success-Response:」をクリックすると、ある程度具体的なデータ例が記述されている。「Success 200」はHTTPのステータスコードが200、つまり通信が成功した時のJSONの応答に含まれているデータのキーと値についての説明となっている。なお、ちらっとOptional query parameterに書かれてあることは、解釈は決して簡単ではないが、レイアウトに含まれるポータル内にあるデータを制限する方法が記述されている。具体的には「Example query with portal」のところに書かれている「?porta=」の部分をURLに繋いで指定するのだが、これも1回読んで理解するのはほとんど無理かもしれない。

FileMaker Data APIを実際に使ってみる

ちなみに上記URLはhttpsとしたが、httpとしたらどうなるだろうか? サーバーはhttpsのURLへリダイレクトする応答を返す。つまり、httpでは処理をしないのである。リダイレクトにどう対処するかよりも、httpsと最初から指定すれば良い。

httpsで運用することになると、サーバ証明書の問題が発生する。通常は、既定値で自己署名の証明書がインストールされているが、最近は通信時に自己署名ではエラーになる場合もあり、適切なパラメータを指定しないといけなくなることもある。もちろん、本番の運用は、自己署名ではなく、正しい証明書を利用することが前提である。

/fmi/restの処理をFileMaker ServerのApacheの設定で追ったところ、Node.jsのサーバーにたどり着いた。つまり、デフォルトの3000番ポートが全てのネットワークポートに対して開かれていることから、別途、Node.jsのプログラムを動かす場合には注意が必要になる。FileMaker 16 Data API ガイドによると、8989ポートも開かれているようだが、こちらはlocalhostに対してのみ開かれている。ちなみに、Node.js内でどのようにしてFileMakerデータベースへアクセスしているかと言えば、Javaのプログラムをリモートコールするようなクラスを利用している。つまり、Node.jsの先は公開されていないJavaのAPIを利用している模様だ。この辺りも解析すると何かわかるかもしれないが、ざっと見た範囲では、FileMaker Data APIの範囲を超える仕組みを組み込むことは期待できない感じであった。

これらのAPIを解説してもいいのだが、アプリケーションの利用を考えた時、毎度URLを組み立ててリクエストとレスポンスするのはちょっと効率が悪い。すでに別の記事で紹介したように、PHPで使えるクラス「FMDataAPI」を開発しておりPHPでFileMaker Data APIを使用したいなら、このクラスを使うことが早道である。なお、他の言語でも同様により容易に利用できるライブラリの登場が待望される。引続く記事では、FMDataAPIを使いながら、得られるデータの活用方法などを解説しよう。

FileMaker Server 16より搭載のFileMaker Data APIとは?

FileMaker Data APIは、データベースへの読み書きの処理を、Web APIあるいはREST形式のAPIで利用できるものである。FileMakerデータベースを他のシステムと統合したり、Webアプリケーションのバックエンドとして使う場合には様々なフレームワークや言語と組み合わせ利用しやすい形態がREST APIと言える。FileMakerのREST APIについては、すでにアナウンスされていたとは言うものの、FileMaker Data APIがFileMaker Server 16で初めて製品としてリリースされ、利用できるようになった。本来はFileMaker Cloudに搭載されるものと思われていたが、Ver.16が先になったので、次のCloudのリリースには確実に搭載されるのだろう。REST APIはすでにサードパーティ製品はあるものの、FileMaker本体に搭載されたことは今後の製品を予測する上でも大きな出来事と考える。

FileMakerデータベースのWeb利用

FileMaker Pro/GOをクライアントとして利用するソリューションのバックエンドとして、FileMaker Serverを利用し、データの共有をスムーズにできるようにすると言うのがFileMakerのもっともメジャーな利用形態だ。一方、Webの発展が著しいのは言うまでもないが、FileMaker Serverに蓄積したデータをWebつまりWebブラウザーをクライアントとして利用できるようにするニーズもある。

FileMakerは20年近く前からWeb利用に取り組んでいる。初期のHTML拡張によるCDMLによるデータベース連動ページ作成はVer.4で搭載され、当初はかなり期待されたものの、簡単なソリューションで更新処理が複雑でない程度のものでないとかえって開発が難しく、Ver.7の時点で廃止された。Ver.7からしばらくはXSLTをベースにしたWebページ開発ができたが、こちらもVer.11までの搭載となり廃止された。標準技術をベースにしているとは言うものの、他のWeb開発とあまりに手法が違いすぎた。一方、Ver.5より搭載された初期のXML共有は現在ではCustom Web Publishing(CWP)として若干の機能更新はあるものの、現在のFileMaker Serverまで継続している。その後、PHPのクラスライブラリとして提供されたFileMaker PHP APIやそのバックエンドとしてのXML共有の拡張を経て、これらの機能は現在も利用できる。これに加えて、FileMaker Data APIが登場したのである。データの蓄積や取り出しだけを担うサーバー機能としては以上のような経緯があるものの、FileMaker Server 16では、CWPとFileMaker Data APIと言う過去からの全ての仕組みが搭載されていることになる。CloudではCWPは搭載されず、FileMaker Data APIのみとなっている。

FileMaker Pro/Advancedで作ったレイアウトをそのままWebブラウザーで表示するといった仕組みのWeb対応もなされてきた。Instant Web Publishing(IWP)は若干の改良はされてきたもののVer.12で終了となり、Ver.13以降はWebDirectとして、完成度を高めてきており、Ver.15では動きもスムーズになり、システム開発の1つの手法として実運用可能な状況になっている。ただし、Ver.13でGOからの接続がコネクション数に応じたライセンス体系を取るようになると同時に、WebDirectもライセンスが必要となった。従来のIWPは任意の接続は可能であったが、パフォーマンスの問題で数十程度のクライアントの同時接続までとなっていた。

Webアプリケーションに繋がる手法としては、Ver.15では接続数に応じたライセンスが必要となるWebDirectと、サーバーのパフォーマンス次第で接続ライセンスの不要なCWPの両方が組み込まれている。FileMakerのレイアウトがそのままWebブラウザで見えて利用できるのがメリットかデメリットかは簡単には結論は出せない。ソリューションの設計と運用によるものである。HTMLでWebクライアントを構築したい向きにはCWPが必要になるが、一方でライセンス費用を気にしなくてもいいといったコストに偏った見方をされている場合もある。

ライセンス体系は今後どうなるのか?

FileMakerはVer.13以降、接続クライアントに応じたライセンスということを重視した製品系列へとシフトしてきており、FLTというライセンス体系の追加や、IWPの廃止やGOの接続ライセンス必須化を含めて、CWPのような自由な接続という仕組みを排除してきている。加えて、年間ライセンスへとユーザーをシフトさせようとしている。

そうなると、1つの重要な命題は「CWPがいつまで使えるのか」ということに集約できる。現行のライセンスモデルにマッチしない手法だけに、いつ、機能としてなくなっても不思議ではないのである。しかしながら、それに替わる仕組みがなくなることで、システム構築の自由度がそがれることは明白である。CWPに替わるものが、Ver.16で搭載されたFileMaker Data APIとなるが、「トライアル」ということで、今後の展開を見てライセンス形態を決めようとしている意図が見えてくる。正式にリリースされたことで、まだアナウンスはないもののCWPの継続が中止される可能性はゼロではなく、結果的にどのバージョンまで使えるかという問題に帰着する。そして、FileMaker Data APIに関して、どういったライセンス体系への統合を、どのバージョンで行うかということに注目することになる。Ver.16現在、FileMaker Data APIは自由にアクセスできる状態であるが、FileMakerの製品ライセンス体系を考えれば、「いつかはお金を取る」という姿勢は容易に感じとれるのである。

モダンなデータベース利用が可能なFileMaker Data API

ちなみに、なぜ、CWPがFileMaker Data API置き換わると予想されるのかについてだが、総じてFileMaker Data APIの方がモダンであると言えるからである。サーバーにリクエストを送って結果を得るのは昔からあるXML共有でも現在のFileMaker Data APIでも同じであるが、XML共有はURLに対してXMLで結果が返るのに対して、FileMaker Data APIではHTTPのメソッドを伴うきちんと定義されたAPI動作に対してJSONで結果を返す。データの内容的には、ポータルか、別のTOのフィールドなのかを判別するという点では、XML共有は確実にできなかったこともあった。その後の改良でできるようにもなったが、パフォーマンスが悪くなった。

HTTPのメソッドとURLの組み合わせで動作を記述し、JSONで得られるFileMaker Data APIの方が、様々な用途に展開しやすいことも事実だ。機能的には、レイアウト情報まで取得できるCWPの方が勝るものの、FileMaker Data APIは必要最小限の機能になっており、むしろデータ処理に特化されてシンプルに使えることも、学習しやすい点もあり、実運用に即した進化であると言える。

筆者が現在、開発を進めているWebアプリケションフレームワークのINTER-Mediatorも、もちろん、FileMaker Data APIへの対応を行う予定である。CWPがなくなることを見越しての対応である。そこで基礎部分の足固めとして、PHPで使えるクラス「FMDataAPI」を開発し、こちらは単独でMITライセンスのオープンソースソフトウェアとしてGitHubで公開した。こちらの開発で得られた知見を元に、しばらくはFileMaker Data APIについての情報を本ブログで提供することにする。

[開発プロセス#13] アプリケーション全体を改めて記述する(2)

前回の続きである。前回はユーザーインタフェース要素、つまり、HTMLで記述できる要素は、仮想的に変数とバインドされているという仕組みの考えた上で、ユーザーインタフェース要素と、処理の記述の分離ができていることを説明した。その時の図を利用して、続きを説明しよう。

ここで処理は、分類1から5までに分けて記述をした。このうち、分類3と4がサーバーで他はクライアント側の処理として実装するのが効率良いと考えたとする。「分類2」は、最初に検索フォームを表示する仕組みを記述しているので、特にギミックがないのであればスタティックなHTMLを表示するだけになる。この図では、HTMLの表示には、その要素のHTML記述をテンプレートとして、それを元に画面を構成して表示するという記述で統一することにする。

「分類1」は、フォームに入力された検索条件を元に検索を行い、その結果を画面に表示するまでの、残りの分類を全て通ることになる。分類1については、以前に考えた基準に従って、「やるべき処理」をボックスにして記述をしたが、ここでまず、違和感が出てくる。やはり、ここでは、ボックス間の矢印は「次の処理」を示すことになり、ボックスによって矢印による処理の段取りが変わってくる。であれば、同じ矢印で示すのはどうかと考える。このボックスと矢印の記述の意味を検討して改良することは次のステップで進めることにする。

「入力内容検証」となっているが、設計であるのなら、どのような検証を行うのかを記述すべきであることは明白である。ここでは、OCL等を利用した記述を行うのが順当と考える。

入力に問題がなければ、その値を持ってサーバーからデータを取りに行く。ここで、分類1から分類4にかけては、要するにサーバに対してHTTPのリクエストをPOSTメソッドで行うというごく一般的なCGIの仕組みを利用することになる。「サーバーへPOSTメソッド」から「POST受け入れ」までの処理は、時代によって記述方法が違っていた。古くから行われているのは、FORMタグ要素のSUBMITボタンを利用することで、POSTメソッドをサーバーに投げるということだ。そして、PHPを利用していれば、「POST受け入れ」は自動的に処理されて、分類4は言語要素というか、Apache等のWebサーバーとの連携の中で処理がなされて、POSTメソッドに含まれるパラメータが変数に設定されて、プログラムのファイルの1行目からが実行されるということになっていた。分類5については、PHPを使うのであれば、echoコマンド等で出力した結果をバッファに蓄え、クライアントに送り返す。ここはリクエスト-レスポンスの関係を分離4の部分が担う。その意味では、分類4の部分は、よほどのことがない限り、自分で作ることはないと言えるだろう。分類3がサーバーサイドでの処理の部分である。

なお、FORMタグを使って検索条件を送り込み、その結果を表示するとしたら、分類5の「検索結果表画面生成」はサーバー側の処理となる。それをブラウザはそのまま表示すればいいからだ。しかしここで、分類1〜分類4までの流れをAJAXで実装したとする。そうすれば、おそらく、サーバーから受ける分類5のインプットの部分は、JSONなどの純粋なデータのみになると考えられる。そのデータを、クライアント側が保持する一覧表のテンプレートと合成して、実際にページとして表示される。これは、モダンなJavaScriptプレームワークに共通した仕組みであると言える。

これまでに検討した記述方法で全体像を記述してみたが、前述の通り、ボックスと矢印の部分の違和感を払拭することが必要であると考える。また、バインドしている事実が明白であれば、たとえば、フォームないの「名前」と「名前:検索条件」と記述した変数とのステレオタイプがbindingの関係は明白なので、この関係は1つのオブジェクトで記述しても良いだろう。また、ボックスと矢印がどの変数をアクセスするのかをより詳細に記述することにより、ユーザーインタフェースと処理プロセスの間の同時存在必要性も見えてきて、モジュール分離の指針にもなると考えられる。これらの点を引き続いて考えて行くことにする。