ShowTable of Contents
XPages のデータソースの内部的な動作について解説します。
シリーズ目次:
データソースの実体
XPages のデータソースは、内部的には Java のクラスを利用して実装されています。
具体的には、Domino 文書データソースは NotesXspDocument クラスの、
Domino ビューデータソースは lotus.domino.local.View クラスのインスタンスです。
Domino 文書あるいはビューをアクセスするためのクラスとしては NotesDocument や
NotesView といったクラスが別途用意されており、JavaScript で書かれたロジックを用いて
生成、読み込み、書き込みといった操作を行うことができます。
ではなぜ、同じデータに対して2つの異なるクラスが用意されているのでしょうか?
その理由は、HTTP プロトコルによる Web アプリケーションの動作にあります。
HTTP プロトコルによる通信は一般にステートレスです。Web アプリケーションは HTTP プロトコルよる
サーバーアクセスを繰り返して、画面を表示したり機能を実現したりします。
ステートレスとは、個々の HTTP リクエストごとに通信が切断され、それ以前のリクエストの状態を
保存しないことを意味します。
つまり、Domino サーバーをアクセスするために確立したセッションや、オープンした文書を
複数のリクエストをまたいで維持したままにすることができないのです。
この問題を解決するために用意されたものがデータソースであり、
リクエストをまたいでオープンしたままにすることができない NotesDocument に対して、
NotesXspDocument は view スコープの変数として生成され、途中結果を保持するための
ラッパーとして動作します。
データソースの動作
以下のような簡単なサンプルアプリケーションを利用して、データソースの動きを順を追って確認します。
Domino 文書データソースを持ち、その内容を編集するための XPage です。

編集フィールドに加えて、2つのボタンが配置されています。
「更新」ボタンは、編集用の表を部分更新します。合わせて、データソースに保存されている値を確認するために
以下の JavaScript を実行するよう設定されています。
print("NotesXspDocument では:" + document1.getItemValueString("Subject"));
print("NotesDocument では:" + document1.getDocument().getItemValueString("Subject"));
ここで、document1 は Domino 文書データソースです。Domino 文書データスースは、元になった
NotesDocument を取得するメソッド、getDocument() を提供しています。
このロジックでは、データソースオブジェクトに保存されている Subject フィールドの値と、元の
文書に保存されている値を表示します。
「保存」ボタンには「文書の保存」シンプルアクションが設定されており、編集結果をデータベースに保存します。
ページを初めてアクセスする
初めてこのページをアクセスすると、NotesXspDocument データソースオブジェクトが新規生成されます。
その後、指定されたID を持つ文書を NotesDocument クラスを利用してオープンし、保存されているフィールドの
値を読み出してデータソースオブジェクト内にキャッシュします。
最後に、その値を初期値として持つ入力フィールドが生成されブラウザに戻されます。
リクエスト処理完了時、NotesDocument オブジェクトは破棄され、データソースオブジェクトは view スコープの
変数としてサーバーキャッシュの保管されます。
その結果、ブラウザ上には以下のような編集画面が表示されます。

フィールド値を編集する
表示されたフィールドの値をブラウザ上で編集します。編集内容をサーバーに反映するため、「更新」ボタンを押します。
「更新」ボタンを押すことで新たな HTTP リクエストが発生し、入力されたフィールド値がサーバーに送信されます。
リクエストを受けたサーバー側では、前回のリクエスト終了時にサーバーキャッシュに保管されたデータソースオブジェクトを
最初に読み出します。このリクエストにおいては、元の文書のオープンおよびフィールド値の読み出しは行われません。
送信されてきたフィールド値は、リストアされたデータソースに対して保存されます。
これらの処理が行われた後、用意した JavaScript により以下のようなメッセージが Domino コンソールに表示されます。
HTTP JVM: NotesXspDocument では:文書のタイトル-編集
HTTP JVM: NotesDocument では:文書のタイトル
このメッセージからも、更新したフィールド値が反映されているのはデータソースオブジェクトに対してのみであることが
確認できます。
ブラウザ画面上の表示は、以下のようになります。

別クライアントで裏から文書を編集する
このタイミングで Notes クライアントなど別のクライアントから同じ文章を編集、保存します。
その影響を確認するために、再度「更新」ボタンを押して JavaScript ロジックを実行します。
Domino コンソールには以下のメッセージが表示されます。
HTTP JVM: NotesXspDocument では:文書のタイトル-編集
HTTP JVM: NotesDocument では:文書のタイトル-裏から編集
ブラウザ画面上の表示は変化しません。
つまり、ブラウザ上の表示を更新するためにはデータソースオブジェクトだけが参照されており、
元文書のアクセスはこの時点でも行われていないことが確認できます。
文書の保存を行う
「保存」ボタンを押して編集結果の保存を行います。その後、結果を確認するために「更新」ボタンを押します。
Domino コンソールには以下のメッセージが表示されます。
HTTP JVM: NotesXspDocument では:文書のタイトル-編集
HTTP JVM: NotesDocument では:文書のタイトル-編集
ブラウザ画面上の表示はやはり変化しません。
「文書の保存」を行った時点で、データソースオブジェクトと元文書の内容が同期したことが分かります。
注:この例では編集の競合が発生します。編集結果を上書きするため、データソースには
concurrencyMode=force が設定されています。
currentDocument グローバルオブジェクト
通常データソースのアクセスには定義時に割り当てた変数名が利用されます。
これと同時に利用可能な変数として、currentDocument と名付けられたグローバル変数が用意されています。
この変数はページ内に Domino 文書データソースが1つ以上定義されている場合に自動的に生成され、
そのいずれかのデータソースを表します。どのデータソースを表すかは currentDocument 変数が利用される
場所に応じて動的に変化し、それぞれ「もっとも近い」データソースとなります。
どのデータソースが「もっとも近い」のかを、具体例を使って説明します。
以下の例では、XPage の中に2つのパネルコントロールが配置されています。
定義されているデータソースは3つで、XPage に対して document1 と document2 がこの順で
定義され、Panel1 に対して document3 が定義されています。
currentDocument は計算結果フィールドコントロールに対してデータバインドされています。
計算結果フィールドが配置されているのは3箇所、XPage に対して直接と2つのパネルの内側です。
このような配置が行われている場合、それぞれの計算結果フィールドでアクセスされるデータソースは
以下のようになります。
computedField1: document2
computedField2: document3
computedField3: document2
つまり、「最も近い」とは以下のルールで定義されます。
- コンポーネントツリー上同じレベルにあるデータソースが最も近く、
同じレベルにデータソースがない場合には順次親にさかのぼります。
- 同じレベルに複数のデータソースがあった場合には、
より後に定義されたものがより近くなります。