なんと、カスタムWebは動かないので、INTER-Mediatorでは利用できません。Directoryのアカウントでのログイン機能もありません。ESSはサポートはしますが、ドライバが非対応ということはちょっと簡単ではなさそう。その他諸々いろんなチェックポイントがあります。Canada.」と書かれている。ことではいさようならとは行きません。AWSでどうやって日本からのアクセスを切るのかいなと思いつつ、AWSにログインして、リージョンを「バージニア北部」にします。Marcketplaceを選択してFileMakerで検索すれば、あらあらちゃんと出て来ますね。規模の小さいのを選ぶと、ちゃんと値段もわかります。この「時間課金」というのはAWSでの一般的な課金方法です。FileMaker社からライセンスを買わなくても、時間課金ができるとは言え、よく見てください。最低の構成でも1時間が1ドル強、上がっても1.229ドル/時間。要するにアマゾンの費用に比べてFileMakerのライセンス料が異様に高いのです。月間30×24=720時間として、732ドル、ということで、月間7〜8万ほどかかります。こちらを選ぶ人は少ないでしょう。FileMakerからライセンスを買って使ってください。その場合、AMIの選択肢が違います。ライセンスを自分で持っている(BYOL)人向けのAMIがあったりします。ここで、「お金を払っても試して見るか」と腹をくくったのですが、よく見ると、15日はフリーライセンスということで、Amazon側のEC2使用料のみで、15日は使えます。いうわけで、なぜ日本では「入手できない」となっているのか?AWSは全世界に共通のサービスをしているのだから、昔の代理店ビジネスのようなことは最初からできるわけがないことは明白なのにどういうことでしょうね。いうことで、操作等より詳細を知りたい方は、インストール後に出て来たヘルプのページをご覧いただくと早いでしょう。Serverのアップデータが途中で止まる件は、こちらのページにまとめました。Server以外のサービスがhttpdを起動していても、やはりアップデートは進まず、そこで単なるシェルスクリプトによる繰り返しでhttpdのプロセスがなくなるまで待ってしまい、フリーズのようになってしまうという状況です。Ver.5を入れた状態で、一度Webサービスを起動し、その後停止した状態を見ることができたので、記録しておきます。Serverのプロセスを完全に落としても、以下のような2種類のhttpdのプロセスが残っています。-fオプションで指定されている設定ファイルを見れば、だいたいどんな機能のものなのかはわかります。httpdapache_serviceproxy.confは文字通りプロキシで、通常のWebサービスやWikiなどのサービスを受け付けてプロセスに流すような設定になっています。リバースプロキシでしょうか。Serviceだと思われます。いろいろな設定を追いかけると、/Applications/Server.app/Contents/ServerRoot/usr/libexec/scsdのプロセスがデーモンとして起動しているようで、それに対するWebインタフェースをApacheを使って稼働させている模様です。Daemon」とタイトルにあります。細かなことはわかりませんが、Webアプリケーションとして動くサービスとなっています。Serverのプロセスは起動しません。httpdを利用するサービスを全てなくすには、次のようなコマンドを打ち込みました。com.apple.service.ACSServer.plistServer.appはいろいろな機能がありますが、Webサービスはもちろん、事実上はWebアプリケーションであるカレンダーやWikiなどの機能を一切使わないのなら、上記のようにしてリバースプロキシとACSServerはなくてもおそらくは問題ないと思われます。DirectoryのMasterとして使う限りでは、上記のサービスを落とした状態でも利用できています。これらのサービスは単純に「落としても構わない」とは言い切れないですし、皆さん自身が判断してください。Serverを同時に使う場合には、Server.appのWebあるいはApacheを使っている一切の機能を使わないでおくようにするしかないと思います。ちなみに、聞くところによると、FileMaker社のサポートに問い合わせると「Server.appはアンインストールしろ」と言われるらしいです。それもどうかと思います。事実上、同じ会社の製品なんですけどね。Serverをどうしてもアンインストールしたい場合があります。インストーラが「先にアンインストールしないといけません」とメッセージを表示して、それ以上進めないとなると、仕方ありません。Serverのアンインストーラがあることを知っていれば、便利かもしれません。Serverという場所にも、アンインストーラがあります。14.0.4bのアップデータがリリースされました。このところ、アップデートが頻繁にありますが、いざアップデートしようとすると、最初の部分でフリーズしてしまうことがあります。フリーズと言っても、マウスカーソルがレインボーになってしまう現象です(画面ショットではレインボー状態は撮影できないので、以下の図は普通のポインタになっています)。ちなみに、この現象は、14.0.4bのアップデータに限らず、13のアップデータでも発生することがあります。いつまで経ってもこのまま進みません。アクティビティモニタを見ると、パッチアプリケーションのCPU稼働率が100%近くになっています。いうことは、本当にフリーズか、適切でない処理待ちをしていることが考えられます。そこで、ターミナルを起動して、プロセスを見てみます。パッチアプリケーションのプロセスには「Patch」という特徴的な文字があります。以下のコマンドで、プロセスIDは27530だとわかります。(以下、コマンドラインの出力が長いので折り返して見えるようにしておきますが、見づらい点はご容赦ください。Patch次に、このプロセスが別のプロセスを起動していないかをチェックします。0」なるプロセスがあります。最後の方の数値は起動ごとに違うものがつけられ、正常終了すると消されているファイルです。0これは/bin/shつまり引数をシェルスクリプトとして実行しているということです。catコマンドで、ファイルパスにスペースがあるのでダブルクォートで囲むなどの対処をして、中身を読んでみます。パッチアプリケーションは、このプロセスが終了するのを、おそらく単なるループで待っているためにフリーズするのでしょう。psコマンドである種のプロセスが存在するかどうかを2秒ごとにチェックし、調べているプロセスがなくなれば、スクリプトを終了します。2donewhileの行を見ると、psコマンドの結果に、fmserver_helperd、fmsib、fmslogtrimmer、fmxdbc_listener、fmsasedという文字列があるかを調べています。Serverの様々なプロセスが起動した状態なのかを調べています。httpdというプロセスまで存在するかを調べています。Serverを停止させて行うようにということで、FileMaker関連のプロセスがなくなっているという条件はまあいいでしょう。Serverのプロセスを事前に全部止めておくには、以下のコマンドでできます。/Library/LaunchDaemons/com.filemaker.fms.plistしかし、httpdとなると、何らかのきっかけで動かしてしまっているかもしれません。Serverあたりがhttpを使っていました。Server.appは、それらのプロセスをオフにしても、httpdの稼働を止めません。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が起動していたらアップデートをしない」という仕様です。Server以外のhttpdの起動を許さないという仕様に問題があります。Server.app自体が色々なサービスでhttpdを使うのですが、80番ポートの取り合いになるのは確かにまずいでしょう。Serverのインストーラーは、自分自身のhttpdのポート番号を指定することで、他のサービスとの同居の可能性を探っています。Serverが起動したhttpd」ではなく、単に「名前がhttpd」のプロセスを探しているにすぎません。Server以外でhttpdを使いっていればトラブルが発生する仕様なのです。これでは仕様の上で矛盾があると言えるでしょう。Serverしか動かさないという前提でもそれはそれで構わないと思いますが、だったら、LinuxのVMで動かすようにして欲しいというのが総意ではないでしょうか。XとWindowsで、アプリケーションみたいなインストーラでセットアップするサーバーはもはや古さを感じます。現在のシステム構築環境にマッチしない仕様を早く改善しないと、先頭集団からさらに引き離されるでしょう。Nii.FileMakerのWebビューアが、WebDirectで文字化け最近ブログ更新していないので、小さなネタですが書いておきます。私がWebDirectの話をするのは予想外かもしれませんが、ちょっとハマったことがあったので書いておきます。FileMakerでのソリューション内で、複数の文書を並べるような機能が必要だったので、Webビューアを使いました。全文字を平面上に成り行きでレイアウト出来るので便利です。Webビューアには、dataスキームを利用して、フィールドの値などを合成したHTMLを与えてWebビューアに表示しました。Pro上ではもちろん問題ありません。WebDirectでWebビューア部分が文字化けしました。理由はフォントではなく、文字セット指定がなかったからです。content='IE=Edge,chrome=1'/&gt;....のように、charsetを入れればブラウザ上では文字化けは無くなりました。charsetを省略すると、us-asciiと同じになるそうですが、それはブラウザ上だからかと思われます。Proでは指定なしでも文字化けないようにしているということでしょうね。Nii.FileMakerのスクリプトで実現するインジェクションもしくはアスペクト指向アスペクト指向プログラミング(AOP)はオブジェクト指向の世界での手法の1つですが、FileMakerでのスクリプトでそれを実現する方法が見つかったので、記事で残しておきます。AOPについては後ろの方でまとめて、まず、何を実現したかを具体的に説明しましょう。マスターテーブルからの選択結果を記録するデータベースに次のようなリレーションシップを定義しています。フィールドmemoとtermはテキストで、後のフィールドは数値型です。_idの付くフィールドは連番数値を自動入力して、主キーフィールドととします。Inteface)は、テーブルオカレンスのUI_Mainのレコードを表示させるように定義しました。リレーションシップの先の2つのテーブルオカレンスを、3つのポータルに表示しています。このデカルト積を使うリレーションシップにより、Selectionsテーブルのすべてのレコードがポータルに表示されます。ポータルには3つのボタンがありますが、それぞれ概ね同じ目的です。最初のポータルでは、ポータル内でのボタンを押したレコードに対応するselection_idフィールドの値が、select1フィールドに入力されます。その動作を3通り考えることで、AOPに迫るというのが概要です。実際のソリューションでは主キー値となる連番はユーザーに見せないように作りますが、ここでは動作が一目瞭然となるように意識的に通常のソリューションでは見せない内容をレイアウトに表示して動作をチェックします。Memoフィールドの左側のClearボタンにより、Memoフィールドの文字列を消去します。ここでSelectAボタンがどうなっているのかを説明しましょう。SelectAボタンは一番簡単なというか、理解しやすい方法です。1」というスクリプトが実行されます。3」というスクリプトが動くように指定をします。ボタン名の番号と、スクリプト名の番号は対応していません。わかりにくいことをやってしまってごめんなさい。3つのスクリプトは以下のようになります。ポータル内で選択したレコードのselection_idの値を、UI_Mainテーブルオカレンスのselect*フィールドに代入をしています。それぞれ、自分自身のポータルと、対応するUI_Mailのフィールドがスクリプトの設定に見えています。スクリプトの共通化このような「同じようなスクリプト」は、共通化したいですね。昔のFileMakerなら、共通化は難しい上に、個別に記述できるから分かりやすいといった議論もあったわけですが、今時の複雑なソリューションでは、スクリプトの数が爆発する傾向にあり、1つのスクリプトにまとめる意義は高まっていると言えるでしょう。いうわけで、「SelectB」ボタンでは、SelectAボタンの手法を1つのスクリプトにまとめてみました。B」という共通のスクリプトを呼び出しています。この時、最初のポータルのSelectBボタンは、スクリプト引数として、次のような設定を行います。値を入力するフィールド名と、値を取り出すフィールド名を、改行で区切って指定をしておきます。それぞれのポータルのSelectBボタンは同一のスクリプトを呼び出すものの、スクリプト引数を異なるものにするということです。Bスクリプトは、次のようなものです。引数から値を取り出したものは、フィールド名の文字列です。その文字列のフィールド名で指定したフィールドに値を設定するには「フィールドを名前で設定」スクリプトを利用します。文字列で与えたフィールドから値を取り出すのは、GetField関数を使います。引数を変数に入れると同時に、スクリプトステップは異なるものとなり、関数の利用も行わないといけません。共通化したことによるデメリットここまでのような単純なスクリプトで済ませられるのであれば、それはそれでいいのですが、実際の開発では複雑な要求が発生します。ここまでは、選択ボタンは同じ動作をするという前提でしたが、現実にはそういうことはあまりありません。ボタンごとに固有の要求が出てくることがあります。具体例としては次のようなことです。あるポータルでのボタン選択をするときにだけ、別の選択肢は空欄にしたり、場合によっては初期値的な設定を強制的に行う必要があるある選択の場合に、ある条件が成り立つ場合にだけ、選択していいかどうかをダイアログで問い合わせるある選択肢の選択後に、テーブルの更新など、その選択肢に固有の処理を追加しないと要求が実現できないこうなってくると、「そら見たことか、スクリプトはボタンごとに設定するのが王道だ」と思わず口走ってしまうかもしれませんが、未だに1ファイルに1データベースみたいな作り方をする発想が抜けきれないとしか言いようがありません。ここの例では、共通なステップは1つだけですが、複雑な処理は共通化しておかないとデバッグやメンテナンスコストが増大するのは言うまでもなく、システム構築の常識です。FileMakerでは、プログラミング言語的な柔軟性を犠牲にする分、ツールを使った開発がやりやすいとか、学習コストが低いという長所を得ています。なんとかならないかとも考えるわけです。以前だと、「共通部分があるものの、違う部分もある」という場合にどういった手法をやっていたかといえば、まずは、スクリプトが分かれてしまうのは仕方ないとして、共通部分を「スクリプトの実行」ステップで呼び出すということです。この方法は汎用的かつ共通部分の抽出ができるという面ではメリットですが、「違う部分」が発生するごとにスクリプトが増えることになります。ありがちですが、「違う部分がない」にもかかわらずスクリプトが別々とか、「違う部分がある」のにシステムの全然違う箇所からスクリプトを共通に使うなどの、後からの不具合発見を阻害する作りに往往にしてなりがちです。IFを利用して、例えば、押したボタンごとに分岐を作り、ボタンごとに違う処理を組み込む方法です。これだと、1つのスクリプトで共通に使えますが、一方で、ボタンが増えればIFの分岐が増えてしまいます。作れば動作しますが、あるボタンの動作を追う時には無視するスクリプトが大量になってしまうなど、可読性が低くなります。自分が関係してるところだけをちゃんと書けばいいということは理屈の上では成り立つことですが、現実には変数を共通に使ったことでのバグの発生などが懸念されます。分離されていないことでの気づかない悪影響は、当然ながら気づくののコストがかかります。したがって、IFで分岐を入れるのはいいような悪いようなということになります。Injection)の手法により、関心ごとを分離して実装することができないかと考えました。ボタンごとにニーズが違うのであれば、ボタンごとに関心ごとが異なると位置づければ、これはAOPの実現でもあります。C」スクリプトを呼び出すようにしています。3つのポータル上のいずれも同様な設定になっています。以下のスクリプト指定は、1つ目のポータルのSelectCボタンのものです。スクリプト引数はSelectBボタンと同様な指定です。スクリプトは同一でも、ポータルごとに、設定するフィールドやポータルが参照するテーブルオカレンスが違うので、それらをスクリプト引数で指定をします。C」スクリプトは次のようなものです。コメントの「前処理スクリプトの呼び出し」部分が追加されています。「URLを開く」ステップと併せて示します。ここで、このボタンをクリックしたスクリプトの関心ごとを、選択した結果を保存するフィールドで区別するということを考えます。この前提が上記のスクリプトの動作に必要となります。ここで、例えば、1つ目のSelect3ボタンをクリックしたとします。C」スクリプトの最初の2つのステップで、次のように変数が設定されます。UI_First_Selections::selection_idそして、「URLを開く」オプションで、次の方なURLが生成されて、そのURLを開こうとします。FileMakerのURLスキーマは、ご存知ない場合には、どこかのサイト等で調べてください。fmp://$/AOScriptTest?script=SelectButton_UI_Main_select1&amp;param=any_parameters&amp;$srcField=UI_First_Selections::selection_id&amp;$destField=UI_Main::select1最初の$で自分自身を参照します。URLのscriptパラメータは、その直前のscriptName変数の計算式をみてください。スクリプト名は、「SelectButton_<値を設定するフィールド名>」となります。値を設定するフィールド名は、ボタンのスクリプト呼び出しのスクリプト引数で指定されています。コロンがフィールド名に含まれますが、無難にするためにアンダーラインに置き換えます。1つ目のポータルのSelectCボタンをクリックすると、自分自身の「SelectButton_UI_Main_select1」スクリプトを呼び出すということになります。ここで、「スクリプトの実行」ステップが使えない理由は、そのステップではスクリプトの選択はできても、変数等でのスクリプト名の指定ができないからです。ここではURLスキームの利用を行います。「SelectButton_UI_Main_select1」スクリプトは例えば、以下のようなものを作成しました。select2とselect3フィールドを空白にします。ここで、レイアウトを指定する必要がない点は注目点の1つです。2つ目のポータルのSelectCボタンを押した時に呼び出されるURLでは、スクリプト名は「SelectButton_UI_Main_select2」となりますが、このためのスクリプトは作っていません。2つ目のポータルのSelect3ボタンをクリックした時、「URLを開く」では存在しないスクリプトをパラメーターに指定します。エラーとして出ないように「エラー処理」ステップを入れているので、要するに、存在しないスクリプトを実行しようとしても、スルーするだけです。「SelectButton_UI_Main_select3」スクリプトは次のようなものです。SelectButton_UI_Main_select1スクリプトとSelectButton_UI_Main_select3スクリプトの最初の1行は同じで、パラメーターに指定した内容をmemoフィールドに入力することです。式が途中で切れていますが、結果を見れば明白だと思うので、式はここには記述していません。選択した時の動作を確認する実際に動かしてみます。Clearボタンを押してmemoフィールドを空白にして、3つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect3フィールドに入り、memoには何かの表示が見えています。Cスクリプトがボタンクリックにより呼び出され、その中で、SelectButton_UI_Main_select3スクリプトが呼び出されたということです。Clearボタンを押してmemoフィールドを空白にして、2つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect2フィールドに入りますが、memoは空白のままです。Cスクリプトがボタンクリックにより呼び出されただけの結果になります。Clearボタンを押してmemoフィールドを空白にして、1つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect1フィールドに入り、select2とselect3は空白となり、memoには何かの表示が見えています。Cスクリプトがボタンクリックにより呼び出され、その中で、SelectButton_UI_Main_select1スクリプトが呼び出されたということです。IFを使うことなく、クリックしたボタンに応じて処理を分岐させています。ここで、もし、新しくselect4フィールドを用意して、同様にポータルから選択できるようにしたとします。Cスクリプトを設定して、引数にフィールド名を指定します。select4フィールドに特有の処理を、「SelectButton_UI_Main_select4」を記述して追加します。ここに、選択肢を設定する前に行いたい処理を記述します。Cスクリプト自体に一切の変更を加えることなく、select4フィールド特有の処理を追加できることになります。実装のパタンとしては、GoFのパターンのStateに近いことをやっていると考えていいかと思います。実開発への展開に向けてまず、FileMaker的な考慮点を考えましょう。スキームにより、変数で与えたスクリプト名で実行できる点です。この時、本当に通信するのではなく、同一のスクリプト実行環境で実行を行っているようです。その証拠として、「URLを開く」ステップの先で、「全スクリプトの終了」ステップを実行すると、呼び出した元のスクリプトも途中で中止してしまいます。このことは、「URLを開く」ステップの先で呼び出したスクリプトで、状況を判定して、これ以上の処理はキャンセルするという動作を組み込むことができることも言えるのです。グローバル変数を「URLを開く」ステップの先で設定して、それを呼び出し元でも参照できます。同一のグローバル変数が使えるので、「URLを開く」ステップは同一のユーザーセッション上で稼働していると言えるのです。この辺りの検証スクリプトの残骸が、コメントで残っているので、参考にしてください。ここのスクリプトでは、前処理だけを実装しましたが、後処理、あるいはある特定の「中処理」を必要に応じて組み込むことも可能です。これは、呼び出すスクリプトの性質上、自由に決めることができるでしょう。FileMakerの場合、その「仕様記述」に困難さんがある点も見逃せません。コメントに書くというのは曖昧かつ、記述者により違いや間違いの混入など、問題点は多いでしょう。開発のマネージメント上、状況に応じたベターな方法を見つける必要があります。アスペクト指向スクリプトプログラミングアスペクト指向とは、オブジェクト指向でのクラスの考え方では解決しにくい問題を扱います。クラスは単一の仕組みを持つのが理想ではありますが、いろいろな機能を組み込んだ結果、幾つかのクラスに共通の処理を実装してしまったというようなことがあるかもしれません。機能の実装においては、ある基準でまとめた結果、別の基準で見た時にはまとまってないということがあります。あるのがログ記録機能です。いくつかのクラスの実装ではログの記録があるものの、そのログの処理はクラスが違っても共通のことです。あれば、ログの記録ということ自体をその他のクラスとは別の独立したことと考える方が、明確にその機能だけに集中して検討が可能です。物事のある側面(Aspect)に注目すると、その側面は必ずしもクラスとしての分解に馴染まないことが出てきます。側面として検討した昨日をうまく実装する方法が必要になります。それがアスペクト指向プログラミングです。一方で、アスペクト指向はオブジェクト指向を否定するものではなく、オブジェクト指向プログラミングの拡張の1つとして捉えるべきです。オブジェクト指向ではないプログラミングでも適用できる手法です。Injection)はプログラムのあるポイントに別のプログラムを挿入することです。オブジェクト指向の世界においては、インタフェースや抽象化クラスなどのいろいろなテクニックを使って、実装上の振る舞いや制約をきちんとしたルールに落とし込んでいると言えます。ある側面を定義したものをDIによって別のクラスに埋め込みをするということでの、アスペクト指向の実現できているということになります。アスペクト指向とDIは同一のものではありませんが、結果的には表裏一体な関係であると言えるでしょう。FileMakerでのInjection、つまり処理の注入は、若干明示的にはなってしまいますが、「URLを開く」でできることが以上のようにわかりました。タイトルにインジェクトションだけを書いたのかというと、依存性つまりDependencyのコントロールが事実上できないという点があります。1つの分かりやすい側面は、名前さえ一致すればどんなスクリプトも呼び出せてしまうという点は、依存を無視しているともいえるわけです。ここで示した例は、スクリプトにより選択肢の選択ができるという共通点があります。Cスクリプトが1つのクラスだと思っていいかと思います。一方で、選択する先によって関心事が違うという状況を想定しました。あるボタンは「別のフィールドも更新する」という側面を持ち、別のボタンは「他には何もしない」という共通点の薄い別の側面があったわけです。「URLを開く」を応用した手法により、ボタンごとに異なる側面の実装を独立したスクリプトできるようになりました。したがって、この手法は、FileMakerのスクリプト実装におけるアスペクト指向プログラミングであると言えます。ServerのWebを動かすための方法を書きましたが、そこで、.htaccessファイルなどを有効にする方法記述しました。14.0.4を新たにインストールした場合、前記の文書の記述だとエラーが出ることがわかりました。14のどのバージョンでも当てはまるようです。いうことで、設定ファイルはHTTPServer/conf/httpd.confは以下のように変更すれば良いでしょう。all」も、Directoryタグ内に書いていたのですが、これを書くと、こんなエラーが出ました。最初のエラーにより、ステータスは403が返り、もちろん、ブラウザでは何も出てきません。includes」のエラーは派生的なもの、あるいは副作用的なもののようです。includesそれから、ディレクトリへのアクセスで、index.htmlよりも先にindex.phpを開きたい場合のDirectoryIndexディレクティブの設定は、上記のDirectoryタグのすぐ下にあるdir_moduleが組み込まれた場合の設定にあります。Publishing/publishing-engine/php/yosemite/httpd.fmi.conf.phpの最後の行にあるDirectoryIndexディレクティブを修正しないといけないことが分りました。Apacheの設定ファイルは、バージョンが違うとそこそこ違ったりしますし、管理手法も比較的変動が大きく、「以前使えた設定や手法が通用しない」ということはこのところ頻繁に経験します。