FileMaker Cloudから今後のFileMakerベースのWeb開発を考える

日本市場のユーザーはまだ使えないものの、FileMaker ServerをAmazon EC2上のLinuxで稼働させるFileMaker Cloud 1.15がリリースされ、多数のドキュメントが公開されました。確定情報や、将来構想も含めてここ3、4年の動向を検討できる材料が揃ってきています。

FileMaker 15が最新の現在において、FileMakerデータベースをそのままブラウザから利用できるWebDirectがFileMaker社一押しのWebソリューションであることは言うまでもありません。HTMLなどのコーディング不要であり、FileMaker Pro/Advancedで開発したデータベースをWebでそのまま利用できます。もちろん、一部に要注意点はありますが、そのあたりはドキュメントが完備されている上にあちらこちらのブログやBBS、そしてFileMaker Communityを検索すれば、何かしら解決できる状態になっています。いわゆる「Web特有の開発作業」をしなくてもWeb化できる点では非常にいいソリューションですが、一方、接続ライセンスが必要になることもあって、不特定多数を対象とするWebサイトの場合、ライセンスの範囲内に留めるための工夫が必要になります。技術的に算出は可能なものの、予測が当たるか当たらないかと言う要素は排除できず、一定の確率でアクセスできない場合が出てくることになります。自社向けの業務系システムでは問題ないものの、Webの世界は色々なサイトの利用のされ方があり、そうした要求を満たすにはWebDirectにだけ頼れないという実情があります。WebDirectはFileMaker 13より正式リリースされいくつかのバージョンを経て完成度は上がってきており、近々は細かなアップデートや「より正確な動作」を目指す段階に入っていると言えるでしょう。

一方、カスタムWeb、つまりXML共有やPHP共有を利用したWebシステム構築は、古い仕組みのままでした。特にXML共有はFileMaker Ver.5.5時代のものから本質的には変わっていません。一時期のインスタントWebはデータベースの再現性の低さもあり、プログラミング言語による開発が必要なカスタムWebと用途を分かつような感じでした。もっとも、インスタントWebでできないことが多かったので、カスタムWebに頼らないといけない状況でした。しかし、FM13よりWebDirectが登場しました。カスタムWebは無くなってしまうのではないかという予測はその前後からあったものの、FM15現在、若干の機能アップをしながら本質的には同様な仕組みがずっと搭載されています。カスタムWebはライセンスに縛られないで利用できる場合が一般的なので(ボリュームライセンスは同一組織に縛られる)、不特定多数が参照するサイトにおいても、ライセンス不足で参照できないということを配慮しなくてもよく、マシンパワー的な問題を考慮するだけでWebサイトを構築できました。

ところが、FileMaker CloudはカスタムWebを非搭載となっています。今年のDevConでのセッションの1つSneak Peak: Overview of the FileMaker Cloudでは、Cloudの構成についてすでに公開されており、こちらの内容を見る限りはカスタムWebはCloudには搭載されません。しかしながら、「FileMaker Data API」というRESTベースの機能がCloudに搭載される予定のようです。今回の最初のリリースにはこのAPIは含まれていないことから、順次あるいは次のメジャーアップデートではその方向で開発をしているということになります。そして、興味深いのは、カスタムWebはいつまで使えるのかということです。ここからは完全に予測ですが、FileMaker 16でFileMaker Data APIがCloud及びWindows/Mac対応のFileMaker Serverにも搭載され、FileMaker 18か19くらいまでカスタムWebが使えるというくらいになるのではないでしょうか。両方が並立する期間が数年はあると予測します。根拠は、FileMaker社がのDeprecated Features(使用できなくなった機能)として、ある機能がなくなる場合にはいくつかのバージョンをまたいでアナウンスをしていることがあります。カスタムWebがなくなるというアナウンスはないので、次のFM16には搭載されると予測できます。

しかし、何れにしても、3年を超える範囲を考えれば、そろそろカスタムWebの終焉を視野に入れる時がとうとうやってきたのかもしれません。もちろん、FileMaker Data APIが次のターゲットではありますが、システム単位ではもっとドラスティックにFileMakerを使わないという選択肢を考えることもあり得るでしょう。

もう1つ、前述のDevConのセッションの内容では、LDAP/Active DirectoryからOAuthベースへの移行を行うとしています。これをWindows/Macで稼働するFileMaker Serverでもその方針で進めるかどうかは微妙かと思います。これらディレクトリサービスによる認証は、WindowsやMacではOSに搭載されているから組み込まれた機能であって、Linuxでも同様な実装はできたはずです。しかしながら、FileMaker Cloudは独自に用意したインスタンスでありそこを見直して、いっそのことWebやその他、様々な状況での運用が可能なOAuthにするということでしょう。これは、うまくすると、GOで一度認証すると、同じサーバーで運用する幾つかのデータベースへのアクセス時には、本来の意味のシングルサインオンが機能して、ユーザー名やパスワードの入力が不要になるかもしれません。Macの中で実現していたことが、GO/Windows/Mac/DirectWebとシームレスに認証結果を共有できるようになるのだとしたら、素晴らしいでしょう。したがって、OAuthをFileMaker社の各アプリケーションが背後で実装していて、ユーザーは気づかないうちにその恩恵を得ている…というシナリオが理想です。さて、実際にどうなるのかは運用してみないとわかりません。何れにしても、FileMaker Data API時代のWebアプリケーションは、OAuth対応を考える必要が出てくると思われます。

最後にINTER-Mediatorです。もちろん、カスタムWebベースでの稼働はFileMaker Serverのサポートが続く限り継続させますが、FileMaker Data APIへの対応は必定であることは言うまでもありません。現在はスペックも、テスト稼働もできないのでなんとも言えませんが、開発ができるようになった段階からなるべく早く開発を進める予定です。

FileMaker Cloud残念ながら稼働せず

昨夜というか未明にインスタンスを作りました。ヘルプによると、メールがきて、そこにセットアップするためのページを表示するリンクがあるのですが、昼過ぎてもメールは来ません。なるほど、そうやって、US/Canada以外には使わせないようにしているのか!というところです。多分、Amazonの顧客情報のリージョンによって、メールの発行をコントロールしているのでしょう。FileMaker CommunityではすでにCloudの話題が流れているので、USの利用者は使用を開始しています。ヘルプ画面を見るしかないので、FileMaker Cloud Supportのリンクを紹介しておきます。

ここからは想像です。セットアップの画面のヘルプを見ると、Amazonのアカウント番号、そして自分で決めるホスト名などを入力します。どうも、自分自身のインスタンスへのアクセスURLは「ホスト名」を含むURLとして決められるみたいです。Amazonのアカウントを知らせれば、背後でどのインスタンスが未セットアップなのかは分かります。ヘルプを見ると、「FileMaker Cloud」というシステムがAWS内で動いているようです。Cloud利用可能なユーザーに対して、そのユーザーのインスタンスとは別のセットアップシステムで入力すると、ターゲットとなるインスタンスに対して変更を行うような仕組みになっているのだと思われます。したがって、セットアップのURLをメールで知らせてもらわないと絶対にわからないし、知らせてもらったとしてもAmazonの顧客情報を付き合わせれば、未提供のリージョンであれば何もしないというどうさになるのかもしれません。

そんなわけで、残念ながら、日本のユーザーはインスタンスのセットアップまでしかできないということになります。

FileMaker Cloudまだ使えず

EC2にインスタンスを作ったら、メールが来て、最初のセットアップができるようにヘルプには書かれています。しかしながら、1時間ほど待った今、まだ来ません。ということで、もう少し追加情報や検討ポイントを書いておきます。ちなみに、英語のサイトでは、Cloudのマニュアルページがすでに用意されていました。

まず、インスタンスを作った時に自動的に作られるセキュリティグループにファイアウォールの設定がありますが、「インバウンド」を見ればわかりますけど、ちゃんとFileMakerのデータベースのポートである5003が開いています。80, 443はいいとして、SSHは開いていません。しかしながら、編集ボタンを押して、SSHを追加すれば、通常の手順でSSHに接続できます。接続方法はコンソールのインスタンスで「接続」ボタンをクリックして確認できますが、デフォルトのユーザー名は「centos」であってrootではありませんので注意しましょう。当然ながら、インスタンスを作った時にキーファイルが作られてダウンロードしていると思いますが、こちらもアクセス権をmacOSだと600にするなど、sshの作法に従って作業をします。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-09-28-1-01-16%ef%bc%882%ef%bc%89

SSHで接続してみて見ると、Apacheもnginxも上がっていません。しかも、TCPで1つもポートが開かれていない。この状態ではデータベースはもちろん、外部から接続のしようがないように思います。それにヘルプに書かれた「メール」がない状況を考えて、がっつり推測ではありますが、この状態でなんらかのアクティベーションをFileMaker側で行うのではないかと考えました。どうでしょう。従来のライセンスを使う場合だと、FileMaker Storeでアクティベーションするのだから、なんらかのアクティベーションがあるのは確実ではないかと思った次第です。とすれば、確かに日本の顧客であればアクティベーションをしないという対処も可能かもしれません。ですが、これは推測です。

さて、ライセンスです。作業中に見えた別のページを見ると、Amazonに対してAMIの利用料を年間で払うプランもあるようです。これだと、年間880ドルだから、FileMaker ServerのAVLAより高いけど、まあべらぼうに高いわけではありません。これまで通り、FileMaker社から購入したライセンスでも、Amazonに対して年間あるいは時間で課金した料金でも支払えるようになっています。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-09-28-1-13-00%ef%bc%882%ef%bc%89

ちなみに、FileMaker Server 15は当初は、Windows ServerかOS Xでの運用しかできなかったのです。Linuxで稼働するサーバーは皆が(特にSI関係者は)熱望していたと思います。FileMaker 5.5のサーバーではLinux版もあったものの、FileMaker 7でWindows/Macだけになって10数年経過して、Linux対応していたのも忘却の彼方です。

サーバーなのでLinuxで稼働させるのはそんなに難しい話ではないと思いますが、おそらくLinuxで稼働させるとなると無数のディストリビューションがあることから、サポートコストがかさむことを懸念したのだと思われます。しかしながら、Amazon EC2のAMIで提供すれば、プラットフォームはAmazonだけだし、課金のシステムも完備です。サポートは最小限になるし、きちんとライセンス料を取れる仕組みであることを考えれば、仕組み自体は非常にうまく考えられています。

FileMaker Cloudのバージョンは、「FileMaker Cloud 1.15.0」となっています。1.がついている。FileMaker Pro/GOは15.0.2を使えとなっています。FAQを読むと、書き込み権限があるのはDocumentsフォルダなど限られており、サーバーサイドのスクリプトには注意が必要でしょう。といいつ、これはMacOSでは同様でした。スケジュールスクリプトが組めないというのも注意が必要でしょう。今後、アップデートでできないこともできるようになって欲しいものではありますが、ともかく、カスタムWebが動くようにして欲しいです。新し目のXMLスキームだけでもいいですから。

FileMaker Cloudが出たぞ!

突然、FileMaker Cloudがリリースされました。FileMaker Server 15のクラウド版ですが、Amazon Web Serviceで稼働するFileMaker Serverです。CentOS 7ベースです。なんと、カスタムWebは動かないので、INTER-Mediatorでは利用できません。他に、LDAP/Active Directoryのアカウントでのログイン機能もありません。ESSはサポートはしますが、ドライバが非対応ということはちょっと簡単ではなさそう。その他諸々いろんなチェックポイントがあります。

しかし、よく見ると、「FileMaker Cloud is currently only available in the United States and Canada.」と書かれている。日本のお客様はお預け〜!? ってことではいさようならとは行きません。AWSでどうやって日本からのアクセスを切るのかいなと思いつつ、AWSにログインして、リージョンを「バージニア北部」にします。そして、EC2のインスタンスを作って見るわけですが、ここで、AWS Marcketplaceを選択してFileMakerで検索すれば、あらあらちゃんと出て来ますね。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-09-28-0-29-05%ef%bc%882%ef%bc%89

一番規模の小さいのを選ぶと、ちゃんと値段もわかります。この「時間課金」というのはAWSでの一般的な課金方法です。FileMaker社からライセンスを買わなくても、時間課金ができるとは言え、よく見てください。最低の構成でも1時間が1ドル強、上がっても1.229ドル/時間。要するにアマゾンの費用に比べてFileMakerのライセンス料が異様に高いのです。月間30×24=720時間として、732ドル、ということで、月間7〜8万ほどかかります。まあ、こちらを選ぶ人は少ないでしょう。FileMakerからライセンスを買って使ってください。なお、その場合、AMIの選択肢が違います。ライセンスを自分で持っている(BYOL)人向けのAMIがあったりします。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-09-28-0-33-22%ef%bc%882%ef%bc%89

ここで、「お金を払っても試して見るか」と腹をくくったのですが、よく見ると、15日はフリーライセンスということで、Amazon側のEC2使用料のみで、15日は使えます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-09-28-0-35-36%ef%bc%882%ef%bc%89

そういうわけで、なぜ日本では「入手できない」となっているのか?AWSは全世界に共通のサービスをしているのだから、昔の代理店ビジネスのようなことは最初からできるわけがないことは明白なのにどういうことでしょうね。

ということで、操作等より詳細を知りたい方は、インストール後に出て来たヘルプのページをご覧いただくと早いでしょう。

第1弾は以上!

Server.appとFileMaker Server 14を共存させる

FileMaker Serverのアップデータが途中で止まる件は、こちらのページにまとめました。FileMaker Serverは、自身でhttpdコマンドのプロセスを起動するため、アップデータを適用するためにプロセスを止めた状態でないと処理しないのはいいとしても、FileMaker Server以外のサービスがhttpdを起動していても、やはりアップデートは進まず、そこで単なるシェルスクリプトによる繰り返しでhttpdのプロセスがなくなるまで待ってしまい、フリーズのようになってしまうという状況です。

OS X 10.11にServer.app Ver.5を入れた状態で、一度Webサービスを起動し、その後停止した状態を見ることができたので、記録しておきます。FileMaker Serverのプロセスを完全に落としても、以下のような2種類のhttpdのプロセスが残っています。-fオプションで指定されている設定ファイルを見れば、だいたいどんな機能のものなのかはわかります。

$ ps -ef|grep httpd
0 235 1 0 4:14PM ?? 0:00.47 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 358 235 0 4:14PM ?? 0:00.02 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 359 235 0 4:14PM ?? 0:00.06 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 360 235 0 4:14PM ?? 0:00.11 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 361 235 0 4:14PM ?? 0:00.06 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 362 235 0 4:14PM ?? 0:00.02 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
0 472 1 0 4:14PM ?? 0:00.35 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/apache2/services/ACSServer.conf -E /var/log/apache2/services/ACSServer_error_log
70 476 472 0 4:14PM ?? 0:00.02 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/apache2/services/ACSServer.conf -E /var/log/apache2/services/ACSServer_error_log
70 20919 235 0 5:36PM ?? 0:00.01 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
1026 28116 27955 0 5:57PM ttys001 0:00.00 grep httpd

apache_serviceproxy.confは文字通りプロキシで、通常のWebサービスやWikiなどのサービスを受け付けてプロセスに流すような設定になっています。つまり、リバースプロキシでしょうか。

ACSServer.confの方は、いろいろ見ていると、/AccountsConfigService/api/とかいったパスが出てくるので、ACSはAccounts Config Serviceだと思われます。いろいろな設定を追いかけると、/Applications/Server.app/Contents/ServerRoot/usr/libexec/scsdのプロセスがデーモンとして起動しているようで、それに対するWebインタフェースをApacheを使って稼働させている模様です。man scsdはきちんとドキュメントが表示され、「Accounts Config Service Daemon」とタイトルにあります。細かなことはわかりませんが、Webアプリケーションとして動くサービスとなっています。

何れにしても、これらのサービスが稼働していれば、FileMaker Serverのプロセスは起動しません。httpdを利用するサービスを全てなくすには、次のようなコマンドを打ち込みました。

$ cd /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/
$ sudo launchctl unload -w com.apple.serviceproxy.plist
$ sudo launchctl unload -w com.apple.service.ACSServer.plist

Server.appはいろいろな機能がありますが、Webサービスはもちろん、事実上はWebアプリケーションであるカレンダーやWikiなどの機能を一切使わないのなら、上記のようにしてリバースプロキシとACSServerはなくてもおそらくは問題ないと思われます。Server.appを、AFP/SMBのファイルサーバーとして、そしてTime Machineのサービスとして、さらにOpen DirectoryのMasterとして使う限りでは、上記のサービスを落とした状態でも利用できています。

ただ、これらのサービスは単純に「落としても構わない」とは言い切れないですし、皆さん自身が判断してください。ともかく、Server.appとFileMaker Serverを同時に使う場合には、Server.appのWebあるいはApacheを使っている一切の機能を使わないでおくようにするしかないと思います。ちなみに、聞くところによると、FileMaker社のサポートに問い合わせると「Server.appはアンインストールしろ」と言われるらしいです。それもどうかと思います。事実上、同じ会社の製品なんですけどね。

FileMaker Serverのアンインストール

FileMaker Serverをどうしてもアンインストールしたい場合があります。インストーラが「先にアンインストールしないといけません」とメッセージを表示して、それ以上進めないとなると、仕方ありません。インストーラのExtraフォルダに前のバージョンのアンインストーラがありますが、こんな場所にも、現在インストールされているFileMaker Serverのアンインストーラがあることを知っていれば、便利かもしれません。

shot3216

ディスクのルートから、ライブラリ>Application Support>FileMaker>FileMaker Serverという場所にも、アンインストーラがあります。ご参考までに。

FileMaker Serverのアップデータがフリーズする理由

FileMaker Server 14.0.4bのアップデータがリリースされました。このところ、アップデートが頻繁にありますが、いざアップデートしようとすると、最初の部分でフリーズしてしまうことがあります。フリーズと言っても、マウスカーソルがレインボーになってしまう現象です(画面ショットではレインボー状態は撮影できないので、以下の図は普通のポインタになっています)。

shot3215

ちなみに、この現象は、14.0.4bのアップデータに限らず、13のアップデータでも発生することがあります。もちろん、いつまで経ってもこのまま進みません。さて、なんででしょうか? アクティビティモニタを見ると、パッチアプリケーションのCPU稼働率が100%近くになっています。ということは、本当にフリーズか、適切でない処理待ちをしていることが考えられます。

そこで、ターミナルを起動して、プロセスを見てみます。パッチアプリケーションのプロセスには「Patch」という特徴的な文字があります。以下のコマンドで、プロセスIDは27530だとわかります。(以下、コマンドラインの出力が長いので折り返して見えるようにしておきますが、見づらい点はご容赦ください。)

$ ps jax|grep Patch
root 27530 1 27523 0 0 S ?? 0:15.60 /Volumes/FileMaker Server 14.0.4b Patch 1/FileMaker Server 14.0.4b Patch.app/Contents/MacOS/FileMaker Server 14.0.4b Patch

次に、このプロセスが別のプロセスを起動していないかをチェックします。すると、以下のように、「/bin/sh /Users/msyk/Library/Application Support/1358455 0」なるプロセスがあります。最後の方の数値は起動ごとに違うものがつけられ、正常終了すると消されているファイルです。

$ ps jax|grep 27530
root 27530 1 27523 0 0 S ?? 0:15.60 /Volumes/FileMaker Server 14.0.4b Patch 1/FileMaker Server 14.0.4b Patch.app/Contents/MacOS/FileMaker Server 14.0.4b Patch
root 27545 27530 27523 0 0 S ?? 0:00.05 /bin/sh /Users/msyk/Library/Application Support/1358455 0

これは/bin/shつまり引数をシェルスクリプトとして実行しているということです。catコマンドで、ファイルパスにスペースがあるのでダブルクォートで囲むなどの対処をして、中身を読んでみます。パッチアプリケーションは、このプロセスが終了するのを、おそらく単なるループで待っているためにフリーズするのでしょう。psコマンドである種のプロセスが存在するかどうかを2秒ごとにチェックし、調べているプロセスがなくなれば、スクリプトを終了します。

$ cat “/Users/msyk/Library/Application Support/1358455”
#!/bin/sh

cd /Library/Application\ Support/FileMaker/FileMaker\ Server
./launcher -stop

while [ “`ps auwwx | grep -e fmserver_helperd -e fmsib -e fmslogtrimmer -e fmxdbc_listener -e fmsased -e httpd | grep -v grep`” ] ; do
sleep 2
done

whileの行を見ると、psコマンドの結果に、fmserver_helperd、fmsib、fmslogtrimmer、fmxdbc_listener、fmsasedという文字列があるかを調べています。つまり、FileMaker Serverの様々なプロセスが起動した状態なのかを調べています。さらに、httpdというプロセスまで存在するかを調べています。アップデートは、FileMaker Serverを停止させて行うようにということで、FileMaker関連のプロセスがなくなっているという条件はまあいいでしょう。ちなみに、FileMaker Serverのプロセスを事前に全部止めておくには、以下のコマンドでできます。

sudo launchctl unload /Library/LaunchDaemons/com.filemaker.fms.plist

しかし、httpdとなると、何らかのきっかけで動かしてしまっているかもしれません。あ!そういえば、Server.appで色々試したぞと思ってチェックすると、Server.appのソフトウエアアップデート、キャッシュ、Xcode Serverあたりがhttpを使っていました。しかし、Server.appは、それらのプロセスをオフにしても、httpdの稼働を止めません。仕方ないので、sudo launchctl unload <plistファイル>で順次落として、やっとFileMaker Serverのアップデータが動くようになりました。ちなみに、こうしたデーモンは、launchctlで起動しているので、killしてもすぐに再起動されます。そこで、/System/Library/LaunchDaemonsや、/Library/LaunchDaemonsに該当するファイルを探すわけですが、Server.appについては、/Applications/Server.app/Contents/ServerRoot以下の、/System/Library/LaunchDaemonsや、/Library/LaunchDaemonsにあるplistファイルを利用してデーモンを起動しています。これらのファイルから該当するhttpdを起動しているものを探して落とさないといけません。チェックすべきplistファイルのある場所は文中に記載しましたが、見づらいでしょうから以下に列挙します。

/System/Library/LaunchDaemons
/Library/LaunchDaemons
/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons
/Applications/Server.app/Contents/ServerRoot/Library/LaunchDaemons

しかし、一番の問題は、「httpdが起動していたらアップデートをしない」という仕様です。つまり、結果的にFileMaker Server以外のhttpdの起動を許さないという仕様に問題があります。Server.app自体が色々なサービスでhttpdを使うのですが、80番ポートの取り合いになるのは確かにまずいでしょう。しかしながら、FileMaker Serverのインストーラーは、自分自身のhttpdのポート番号を指定することで、他のサービスとの同居の可能性を探っています。しかし、このスクリプトを見る限りは、「FileMaker Serverが起動したhttpd」ではなく、単に「名前がhttpd」のプロセスを探しているにすぎません。つまり、FileMaker Server以外でhttpdを使いっていればトラブルが発生する仕様なのです。これでは仕様の上で矛盾があると言えるでしょう。

もちろん、特定のサーバーではFileMaker Serverしか動かさないという前提でもそれはそれで構わないと思いますが、だったら、LinuxのVMで動かすようにして欲しいというのが総意ではないでしょうか。OS XとWindowsで、アプリケーションみたいなインストーラでセットアップするサーバーはもはや古さを感じます。現在のシステム構築環境にマッチしない仕様を早く改善しないと、先頭集団からさらに引き離されるでしょう。

FileMakerのWebビューアが、WebDirectで文字化け

最近ブログ更新していないので、小さなネタですが書いておきます。私がWebDirectの話をするのは予想外かもしれませんが、ちょっとハマったことがあったので書いておきます。FileMakerでのソリューション内で、複数の文書を並べるような機能が必要だったので、Webビューアを使いました。全文字を平面上に成り行きでレイアウト出来るので便利です。Webビューアには、dataスキームを利用して、フィールドの値などを合成したHTMLを与えてWebビューアに表示しました。FileMaker Pro上ではもちろん問題ありません。しかし、WebDirectでWebビューア部分が文字化けしました。理由はフォントではなく、文字セット指定がなかったからです。そこで、

data:text/html;charset=utf8,<!DOCTYPE html><html><head>
<meta http-equiv='X-UA-Compatible' content='IE=Edge,chrome=1'/>....

のように、charsetを入れればブラウザ上では文字化けは無くなりました。charsetを省略すると、us-asciiと同じになるそうですが、それはブラウザ上だからかと思われます。FileMaker Proでは指定なしでも文字化けないようにしているということでしょうね。

FileMakerのスクリプトで実現するインジェクションもしくはアスペクト指向

アスペクト指向プログラミング(AOP)はオブジェクト指向の世界での手法の1つですが、FileMakerでのスクリプトでそれを実現する方法が見つかったので、記事で残しておきます。AOPについては後ろの方でまとめて、まず、何を実現したかを具体的に説明しましょう。

マスターテーブルからの選択結果を記録する

データベースに次のようなリレーションシップを定義しています。フィールドmemoとtermはテキストで、後のフィールドは数値型です。_idの付くフィールドは連番数値を自動入力して、主キーフィールドととします。

shot3094

あるレイアウト(User Inteface)は、テーブルオカレンスのUI_Mainのレコードを表示させるように定義しました。そして、リレーションシップの先の2つのテーブルオカレンスを、3つのポータルに表示しています。このデカルト積を使うリレーションシップにより、Selectionsテーブルのすべてのレコードがポータルに表示されます。FileMaker 13からサポートされたポップオーバーボタンで選択入力をするときに、このようなリレーションシップを利用するのが1つの典型的なパターンではないでしょうか? ポータルには3つのボタンがありますが、それぞれ概ね同じ目的です。例えば、最初のポータルでは、ポータル内でのボタンを押したレコードに対応するselection_idフィールドの値が、select1フィールドに入力されます。その動作を3通り考えることで、AOPに迫るというのが概要です。当然、実際のソリューションでは主キー値となる連番はユーザーに見せないように作りますが、ここでは動作が一目瞭然となるように意識的に通常のソリューションでは見せない内容をレイアウトに表示して動作をチェックします。Memoフィールドの左側のClearボタンにより、Memoフィールドの文字列を消去します。

shot3123

ここでSelectAボタンがどうなっているのかを説明しましょう。SelectAボタンは一番簡単なというか、理解しやすい方法です。以下のように、ボタンをクリックすると、「Select Button 1」というスクリプトが実行されます。2つ目のポータルのボタンは「Select Button 2」、3つ目のポータルでは「Select Button 3」というスクリプトが動くように指定をします。ボタン名の番号と、スクリプト名の番号は対応していません。ちょっとわかりにくいことをやってしまってごめんなさい。

shot3124

3つのスクリプトは以下のようになります。つまり、ポータル内で選択したレコードのselection_idの値を、UI_Mainテーブルオカレンスのselect*フィールドに代入をしています。それぞれ、自分自身のポータルと、対応するUI_Mailのフィールドがスクリプトの設定に見えています。

shot3129

shot3130

shot3131

スクリプトの共通化

このような「同じようなスクリプト」は、共通化したいですね。昔のFileMakerなら、共通化は難しい上に、個別に記述できるから分かりやすいといった議論もあったわけですが、今時の複雑なソリューションでは、スクリプトの数が爆発する傾向にあり、1つのスクリプトにまとめる意義は高まっていると言えるでしょう。そういうわけで、「SelectB」ボタンでは、SelectAボタンの手法を1つのスクリプトにまとめてみました。3つのポータルにある各SelectBボタンは、「Select Button B」という共通のスクリプトを呼び出しています。

shot3125

この時、最初のポータルのSelectBボタンは、スクリプト引数として、次のような設定を行います。つまり、値を入力するフィールド名と、値を取り出すフィールド名を、改行で区切って指定をしておきます。それぞれのポータルのSelectBボタンは同一のスクリプトを呼び出すものの、スクリプト引数を異なるものにするということです。

shot3127

Select Button Bスクリプトは、次のようなものです。引数から値を取り出したものは、フィールド名の文字列です。その文字列のフィールド名で指定したフィールドに値を設定するには「フィールドを名前で設定」スクリプトを利用します。そして、文字列で与えたフィールドから値を取り出すのは、GetField関数を使います。引数を変数に入れると同時に、スクリプトステップは異なるものとなり、関数の利用も行わないといけません。

shot3132

共通化したことによるデメリット

ここまでのような単純なスクリプトで済ませられるのであれば、それはそれでいいのですが、実際の開発では複雑な要求が発生します。ここまでは、選択ボタンは同じ動作をするという前提でしたが、現実にはそういうことはあまりありません。ボタンごとに固有の要求が出てくることがあります。具体例としては次のようなことです。

  • あるポータルでのボタン選択をするときにだけ、別の選択肢は空欄にしたり、場合によっては初期値的な設定を強制的に行う必要がある
  • ある選択の場合に、ある条件が成り立つ場合にだけ、選択していいかどうかをダイアログで問い合わせる
  • ある選択肢の選択後に、テーブルの更新など、その選択肢に固有の処理を追加しないと要求が実現できない

こうなってくると、「そら見たことか、スクリプトはボタンごとに設定するのが王道だ」と思わず口走ってしまうかもしれませんが、未だに1ファイルに1データベースみたいな作り方をする発想が抜けきれないとしか言いようがありません。ここの例では、共通なステップは1つだけですが、複雑な処理は共通化しておかないとデバッグやメンテナンスコストが増大するのは言うまでもなく、システム構築の常識です。

もちろん、FileMakerでは、プログラミング言語的な柔軟性を犠牲にする分、ツールを使った開発がやりやすいとか、学習コストが低いという長所を得ています。しかし、なんとかならないかとも考えるわけです。

以前だと、「共通部分があるものの、違う部分もある」という場合にどういった手法をやっていたかといえば、まずは、スクリプトが分かれてしまうのは仕方ないとして、共通部分を「スクリプトの実行」ステップで呼び出すということです。もちろん、この方法は汎用的かつ共通部分の抽出ができるという面ではメリットですが、「違う部分」が発生するごとにスクリプトが増えることになります。また、ありがちですが、「違う部分がない」にもかかわらずスクリプトが別々とか、「違う部分がある」のにシステムの全然違う箇所からスクリプトを共通に使うなどの、後からの不具合発見を阻害する作りに往往にしてなりがちです。

1つの苦肉の索は、共通のスクリプト内に、IF〜ELSE IF〜END IFを利用して、例えば、押したボタンごとに分岐を作り、ボタンごとに違う処理を組み込む方法です。これだと、1つのスクリプトで共通に使えますが、一方で、ボタンが増えればIFの分岐が増えてしまいます。もちろん、ちゃんと作れば動作しますが、あるボタンの動作を追う時には無視するスクリプトが大量になってしまうなど、可読性が低くなります。また、自分が関係してるところだけをちゃんと書けばいいということは理屈の上では成り立つことですが、現実には変数を共通に使ったことでのバグの発生などが懸念されます。分離されていないことでの気づかない悪影響は、当然ながら気づくののコストがかかります。したがって、IFで分岐を入れるのはいいような悪いようなということになります。

共通スクリプトと個別スクリプトの分離

そこで、オブジェクト指向の世界でのDI(Dependency Injection)の手法により、関心ごとを分離して実装することができないかと考えました。例えば、ボタンごとにニーズが違うのであれば、ボタンごとに関心ごとが異なると位置づければ、これはAOPの実現でもあります。

まず、レイアウト上にある「SelectC」ボタンは、いずれも、「Select Button C」スクリプトを呼び出すようにしています。3つのポータル上のいずれも同様な設定になっています。

shot3126

以下のスクリプト指定は、1つ目のポータルのSelectCボタンのものです。スクリプト引数はSelectBボタンと同様な指定です。スクリプトは同一でも、ポータルごとに、設定するフィールドやポータルが参照するテーブルオカレンスが違うので、それらをスクリプト引数で指定をします。

shot3128

そして、「Select Button C」スクリプトは次のようなものです。コメントの「前処理スクリプトの呼び出し」部分が追加されています。「URLを開く」ステップと併せて示します。

shot3133

shot3108

ここで、このボタンをクリックしたスクリプトの関心ごとを、選択した結果を保存するフィールドで区別するということを考えます。この前提が上記のスクリプトの動作に必要となります。

ここで、例えば、1つ目のSelect3ボタンをクリックしたとします。すると、「Select Button C」スクリプトの最初の2つのステップで、次のように変数が設定されます。

  • $destField ← UI_Main::select1
  • $srcField ← UI_First_Selections::selection_id

そして、「URLを開く」オプションで、次の方なURLが生成されて、そのURLを開こうとします。FileMakerのURLスキーマは、ご存知ない場合には、どこかのサイト等で調べてください。

fmp://$/AOScriptTest?script=SelectButton_UI_Main_select1&param=any_parameters&$srcField=UI_First_Selections::selection_id&$destField=UI_Main::select1

最初の$で自分自身を参照します。URLのscriptパラメータは、その直前のscriptName変数の計算式をみてください。スクリプト名は、「SelectButton_<値を設定するフィールド名>」となります。値を設定するフィールド名は、ボタンのスクリプト呼び出しのスクリプト引数で指定されています。なお、コロンがフィールド名に含まれますが、無難にするためにアンダーラインに置き換えます。つまり、1つ目のポータルのSelectCボタンをクリックすると、自分自身の「SelectButton_UI_Main_select1」スクリプトを呼び出すということになります。ここで、「スクリプトの実行」ステップが使えない理由は、そのステップではスクリプトの選択はできても、変数等でのスクリプト名の指定ができないからです。なので、ここではURLスキームの利用を行います。「SelectButton_UI_Main_select1」スクリプトは例えば、以下のようなものを作成しました。select2とselect3フィールドを空白にします。ここで、レイアウトを指定する必要がない点は注目点の1つです。

shot3114

2つ目のポータルのSelectCボタンを押した時に呼び出されるURLでは、スクリプト名は「SelectButton_UI_Main_select2」となりますが、このためのスクリプトは作っていません。つまり、2つ目のポータルのSelect3ボタンをクリックした時、「URLを開く」では存在しないスクリプトをパラメーターに指定します。しかしながら、エラーとして出ないように「エラー処理」ステップを入れているので、要するに、存在しないスクリプトを実行しようとしても、スルーするだけです。

「SelectButton_UI_Main_select3」スクリプトは次のようなものです。SelectButton_UI_Main_select1スクリプトとSelectButton_UI_Main_select3スクリプトの最初の1行は同じで、パラメーターに指定した内容をmemoフィールドに入力することです。式が途中で切れていますが、結果を見れば明白だと思うので、式はここには記述していません。

shot3134

選択した時の動作を確認する

実際に動かしてみます。まず、Clearボタンを押してmemoフィールドを空白にして、3つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect3フィールドに入り、memoには何かの表示が見えています。つまり、Select Button Cスクリプトがボタンクリックにより呼び出され、その中で、SelectButton_UI_Main_select3スクリプトが呼び出されたということです。

shot3136

Clearボタンを押してmemoフィールドを空白にして、2つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect2フィールドに入りますが、memoは空白のままです。つまり、Select Button Cスクリプトがボタンクリックにより呼び出されただけの結果になります。

shot3137

Clearボタンを押してmemoフィールドを空白にして、1つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect1フィールドに入り、select2とselect3は空白となり、memoには何かの表示が見えています。つまり、Select Button Cスクリプトがボタンクリックにより呼び出され、その中で、SelectButton_UI_Main_select1スクリプトが呼び出されたということです。

shot3138

Select Button Cスクリプトでは、IF〜Else IFを使うことなく、クリックしたボタンに応じて処理を分岐させています。ここで、もし、新しくselect4フィールドを用意して、同様にポータルから選択できるようにしたとします。もちろん、ボタン等にSelect Button Cスクリプトを設定して、引数にフィールド名を指定します。そして、select4フィールドに特有の処理を、「SelectButton_UI_Main_select4」を記述して追加します。ここに、選択肢を設定する前に行いたい処理を記述します。こうして、フィールドが増えてスクリプトの利用元が増えたとしても、Select Button Cスクリプト自体に一切の変更を加えることなく、select4フィールド特有の処理を追加できることになります。実装のパタンとしては、GoFのパターンのStateに近いことをやっていると考えていいかと思います。

実開発への展開に向けて

まず、FileMaker的な考慮点を考えましょう。ポイントとなるのは、fmp://$/… スキームにより、変数で与えたスクリプト名で実行できる点です。この時、本当に通信するのではなく、同一のスクリプト実行環境で実行を行っているようです。その証拠として、「URLを開く」ステップの先で、「全スクリプトの終了」ステップを実行すると、呼び出した元のスクリプトも途中で中止してしまいます。また、このことは、「URLを開く」ステップの先で呼び出したスクリプトで、状況を判定して、これ以上の処理はキャンセルするという動作を組み込むことができることも言えるのです。また、グローバル変数を「URLを開く」ステップの先で設定して、それを呼び出し元でも参照できます。つまり、同一のグローバル変数が使えるので、「URLを開く」ステップは同一のユーザーセッション上で稼働していると言えるのです。この辺りの検証スクリプトの残骸が、コメントで残っているので、参考にしてください。

ここのスクリプトでは、前処理だけを実装しましたが、後処理、あるいはある特定の「中処理」を必要に応じて組み込むことも可能です。これは、呼び出すスクリプトの性質上、自由に決めることができるでしょう。一方、FileMakerの場合、その「仕様記述」に困難さんがある点も見逃せません。コメントに書くというのは曖昧かつ、記述者により違いや間違いの混入など、問題点は多いでしょう。開発のマネージメント上、状況に応じたベターな方法を見つける必要があります。

アスペクト指向スクリプトプログラミング

アスペクト指向とは、オブジェクト指向でのクラスの考え方では解決しにくい問題を扱います。クラスは単一の仕組みを持つのが理想ではありますが、いろいろな機能を組み込んだ結果、幾つかのクラスに共通の処理を実装してしまったというようなことがあるかもしれません。機能の実装においては、ある基準でまとめた結果、別の基準で見た時にはまとまってないということがあります。よくあるのがログ記録機能です。いくつかのクラスの実装ではログの記録があるものの、そのログの処理はクラスが違っても共通のことです。そうであれば、ログの記録ということ自体をその他のクラスとは別の独立したことと考える方が、明確にその機能だけに集中して検討が可能です。つまり、物事のある側面(Aspect)に注目すると、その側面は必ずしもクラスとしての分解に馴染まないことが出てきます。しかしながら、側面として検討した昨日をうまく実装する方法が必要になります。それがアスペクト指向プログラミングです。

一方で、アスペクト指向はオブジェクト指向を否定するものではなく、オブジェクト指向プログラミングの拡張の1つとして捉えるべきです。ただし、オブジェクト指向ではないプログラミングでも適用できる手法です。その代表的な実装方法がDIであり、DI(Dependency Injection)はプログラムのあるポイントに別のプログラムを挿入することです。ただし、オブジェクト指向の世界においては、インタフェースや抽象化クラスなどのいろいろなテクニックを使って、実装上の振る舞いや制約をきちんとしたルールに落とし込んでいると言えます。ある側面を定義したものをDIによって別のクラスに埋め込みをするということでの、アスペクト指向の実現できているということになります。アスペクト指向とDIは同一のものではありませんが、結果的には表裏一体な関係であると言えるでしょう。FileMakerでのInjection、つまり処理の注入は、若干明示的にはなってしまいますが、「URLを開く」でできることが以上のようにわかりました。しかしながら、あえてタイトルにインジェクトションだけを書いたのかというと、依存性つまりDependencyのコントロールが事実上できないという点があります。1つの分かりやすい側面は、名前さえ一致すればどんなスクリプトも呼び出せてしまうという点は、依存を無視しているともいえるわけです。

ここで示した例は、スクリプトにより選択肢の選択ができるという共通点があります。その意味では、Select Button Cスクリプトが1つのクラスだと思っていいかと思います。一方で、選択する先によって関心事が違うという状況を想定しました。つまり、あるボタンは「別のフィールドも更新する」という側面を持ち、別のボタンは「他には何もしない」という共通点の薄い別の側面があったわけです。しかしながら、「URLを開く」を応用した手法により、ボタンごとに異なる側面の実装を独立したスクリプトできるようになりました。したがって、この手法は、FileMakerのスクリプト実装におけるアスペクト指向プログラミングであると言えます。

FileMaker Server 14をOS Xで稼働するときのWebのカスタマイズ

以前に、FileMaker Server 13とOS X ServerのWebという文書で、FileMaker ServerのWebを動かすための方法を書きましたが、そこで、.htaccessファイルなどを有効にする方法記述しました。しかしながら、FileMaker Server 14.0.4を新たにインストールした場合、前記の文書の記述だとエラーが出ることがわかりました。この点は、FileMaker Server 14のどのバージョンでも当てはまるようです。

ということで、設定ファイルはHTTPServer/conf/httpd.confは以下のように変更すれば良いでしょう。

<Directory "${HTTP_ROOT}/htdocs">
    AllowOverride All
    Options All -Indexes -ExecCGI -Includes
    Require all granted
</Directory>

FileMaker Server 13のとき、「Order allow,deny」「Allow from all」も、Directoryタグ内に書いていたのですが、これを書くと、こんなエラーが出ました。最初のエラーにより、ステータスは403が返り、もちろん、ブラウザでは何も出てきません。後半の「an unknown filter was not added: includes」のエラーは派生的なもの、あるいは副作用的なもののようです。

[Sun Nov 29 01:00:40.179248 2015] [authz_core:error] [pid 1534] [client 219.121.7.182:38310] AH01630: client denied by server configuration: /Library/FileMaker Server/HTTPServer/htdocs/index.php
[Sun Nov 29 01:00:40.179642 2015] [core:error] [pid 1534] [client 219.121.7.182:38310] AH00082: an unknown filter was not added: includes

それから、ディレクトリへのアクセスで、index.htmlよりも先にindex.phpを開きたい場合のDirectoryIndexディレクティブの設定は、上記のDirectoryタグのすぐ下にあるdir_moduleが組み込まれた場合の設定にあります。しかしながら、ここを変えても意図通りに動かないなと思ったら、/Library/FileMaker Server/Web Publishing/publishing-engine/php/yosemite/httpd.fmi.conf.phpの最後の行にあるDirectoryIndexディレクティブを修正しないといけないことが分りました。

Apacheの設定ファイルは、バージョンが違うとそこそこ違ったりしますし、管理手法も比較的変動が大きく、「以前使えた設定や手法が通用しない」ということはこのところ頻繁に経験します。注意しましょう。