Oracle® Fusion Middleware Oracle Application Development FrameworkによるFusion Webアプリケーションの開発 12c (12.2.1.1.0) E77397-02 |
|
前 |
次 |
この章の内容は次のとおりです。
JSFページが送信され、新しいページがリクエストされると、JSFページ・リクエスト・ライフサイクルが起動されます。このライフサイクルでは、ページの値の送信、現在のページのコンポーネントの検証、コンポーネントのナビゲーションと結果ページへの表示および状態の保存とリストアが処理されます。JSFライフサイクル・フェーズでは、UIコンポーネント・ツリーを使用してコンポーネントの表示を管理します。このツリーはJSFページのランタイム表現で、ページ内の各UIコンポーネント・タグがツリーのUIコンポーネント・インスタンスに対応します。
FacesServlet
オブジェクトで、JSFアプリケーションのページ・リクエスト・ライフサイクルが管理されます。FacesServlet
オブジェクトで、リクエスト処理に必要な情報を含み、ライフサイクルを実行するオブジェクトを起動するFacesContext
と呼ばれるオブジェクトが作成されます。
JSFライフサイクルのほかに、ADF FacesおよびADFページ・ライフサイクルも実行されます。ただし、ADF FacesライフサイクルではJSFライフサイクルが拡張され、クライアント側の値のライフサイクル、1つのページに複数のフォームを使用する弊害(ユーザーの編集内容の消失など)なしに独立して送信可能なセクションをページに作成できるサブフォーム・コンポーネント、追加スコープなどの追加機能を提供します。アプリケーションのライフサイクルで実行できる機能を含む、JSFライフサイクルとADF Facesライフサイクル両方の詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の「ADF FacesでのJSFライフサイクルの使用」を参照してください。
ADFページ・ライフサイクルは、データ・モデルの準備と更新、モデル・レイヤーでのデータの検証、ビジネス・レイヤーでのメソッドの実行を処理します。ADFページ・ライフサイクルでは、バインディング・コンテナを使用して、現在のページ・リクエスト時にページによる簡単なデータ参照を可能にします。
組み合せたJSFページ・ライフサイクルとADFページ・ライフサイクルは、アプリケーション・サーバーにHTTPリクエストが届いたときに始まってページがクライアントに戻されるまで続く、より大規模なイベント・シーケンスに含まれる1つのシーケンスにすぎません。このイベント・シーケンス全体をWebページ・ライフサイクルと呼びます。このライフサイクルは、MVCアーキテクチャで定義されているようにモデル、ビュー、コントローラのレイヤーを通して処理をたどっていきます。ページ・ライフサイクルは厳格に定義されたイベント・セットではなく、一般的なユースケースで使用されるイベント・セットです。図30-1に、JSFとOracle ADFを併用した場合のWebページ・リクエストのライフサイクルのシーケンス図を示します。
図30-1 JSFおよびOracle ADFを使用したWebページ・リクエストのライフサイクル
JSFおよびOracle ADFを使用したWebページ・リクエストの処理の基本的なフローは、次のようになります。
http://yourserver/yourapp/faces/some.jsp
に対するWebリクエストが、クライアントからアプリケーション・サーバーに到着します。
ADFBindingFilter
オブジェクトが、HTTPセッション内でADFバインディング・コンテキストを検索し、それがまだ存在しない場合はその初期化を初めて実行します。ADFBindingFilter
の機能には、バインディング・コンテキスト・メタデータ・ファイルの名前の検索、各データ・コントロールの検索と構築などがあります。
ADFBindingFilter
オブジェクトが、該当するリクエストに関与する各データ・コントロールに対してbeginRequest()
メソッドを起動します。このメソッドにより、データ・コントロールは各リクエストの開始時に通知を受けるため、必要な設定を実行できるようになります。
JSF Lifecycle
オブジェクト(各リクエストの標準的な処理フェーズの調整を行う)が、ライフサイクルの各フェーズでADFPhaseListener
クラスに通知し、JSFライフサイクルとADFモデル・データ・バインディング・レイヤーを調整するためのカスタムな処理が実行できるようにします。JSFページ・ライフサイクルとADFページ・ライフサイクルのフェーズの詳細は、「JSFページ・ライフサイクルとADFページ・ライフサイクルについて」を参照してください。
注意:
FacesServlet
クラス(javax.faces.webapp
内)は、JSFアプリケーションのweb.xml
ファイル内で構成され、各リクエストを処理するためのJSF Lifecycle
クラス(javax.faces.lifecycle
内)を最初に作成します。ただし、FacesServlet
クラスは、該当する処理をすべて実行するLifecycle
クラスであるため、図に示していません。
ADFPhaseListener
オブジェクトが、各リクエストを処理するためのADF PageLifecycle
オブジェクトを作成し、該当するフェーズ前後のメソッドをADF PageLifecycle
クラス内の対応メソッドに委譲します。ページのバインディング・コンテナは、ユーザーのセッション中、以前に使用されていない場合は作成されます。
アプリケーション・モジュール・データ・コントロールが、リクエスト時に初めて参照されると、アプリケーション・モジュール・プールからアプリケーション・モジュールのインスタンスを取得します。
JSF Lifecycle
オブジェクトが、レンダリング対象のページにコントロールを移動します。
該当するページ上の一連のUIコンポーネントが、該当ページのバインディング・コンテナ内の値バインディングおよびイテレータ・バインディングにアクセスし、フォーマット設定された出力をレンダリングしてブラウザに表示します。
ADFBindingFilter
オブジェクトが、該当するリクエストに関与する各データ・コントロールに対してendRequest()
メソッドを起動します。このメソッドにより、データ・コントロールは各リクエストの終了時に通知を受けるため、必要なリソースのクリーンアップを実行できるようになります。
アプリケーション・モジュール・データ・コントロールがendRequest
の通知を使用して、アプリケーション・モジュール・プールにアプリケーション・モジュールのインスタンスを解放して戻します。
得られたページが、ユーザーのブラウザに表示されます。
ADFページ・ライフサイクルには、対応するJSFフェーズの実行前後にADFページ・ライフサイクル・リスナーに通知するためのみに定義されたフェーズも含まれています(これらのフェーズは実装されていません)。これらのフェーズにより、カスタム・リスナーを作成してJSFページ・ライフサイクルとADFページ・ライフサイクルの両方のフェーズに登録できるため、必要に応じてグローバルに、またはページ・レベルでADFページ・ライフサイクルをカスタマイズできるようになります。
図30-2に、JSFページ・ライフサイクルとADFページ・ライフサイクルを組み合せた概要を示します。
図30-2 JSFページ・ライフサイクルとADFページ・ライフサイクル
たとえば、テキストが表示された入力テキスト・コンポーネントおよびボタンからなるページがあるとします。このページが初めてレンダリングされるとき、ビューのリストア・フェーズ中にコンポーネント・ツリーが構築され、コンポーネントのレンダリング中、ライフサイクルはレスポンスのレンダリング・フェーズまで進みますユーザーがボタンをクリックすると、完全なライフサイクルが起動されます。リクエスト値の適用フェーズおよび検証処理フェーズ中、コンポーネント・ツリーが再構築され、入力テキスト・コンポーネントではすべての新規値が抽出されます。エラーが発生した場合は(検証によるエラーなど)、ライフサイクルはレスポンスのレンダリング・フェーズにまで進みます。それ以外の場合は、モデルの更新フェーズ中にモデルが新規値によって更新され、アプリケーションの起動フェーズ中、ボタンに関連付けられたすべてのアプリケーション処理(ナビゲーションなど)が実行されます。
図30-3は、JSF、ADF Faces、ADFモデル・フェーズがページ・リクエストのライフサイクルの中で統合されるしくみの詳細を示しています。
図30-3 Fusion Webアプリケーションでのページ・リクエストのライフサイクル
ADFモデルを使用するJSFアプリケーションでは、ページ・ライフサイクルのフェーズは次のようになります。
ビューのリストア: リクエストされたページのURLがbindingContext
オブジェクトに渡され、URLと一致するページ定義が検索されます。リクエストされたページのコンポーネント・ツリーが、新しく作成されるかリストアされます。送信されたページ上のすべてのコンポーネント・タグ、イベント・ハンドラ、コンバータおよびバリデータは、FacesContext
インスタンスにアクセスできます。コンポーネント・ツリーが空の場合(つまり、送信されたページからのデータがない)は、ページ・ライフサイクルは直接レスポンスのレンダリング・フェーズに進みます。
リクエスト状態とサーバー側の状態の間で不一致が検出された場合、エラーがスローされ、ページ・ライフサイクルはレスポンスのレンダリング・フェーズに進みます。
JSFのビューのリストア: ビューのリストア・フェーズに対して、フェーズ前後のイベントを提供します。リスナーを作成してこのフェーズの前または後のイベントに登録すると、リスナーをビューのリストア・フェーズに登録したときのように、アプリケーションが動作します。ADFモデル・ページ・ライフサイクルのコンテキストの初期化フェーズでは、after(JSF Restore View)
イベントをリスニングして実行します。ADF Controllerは、このフェーズの前後のイベントのリスナーを使用して、サーバー側の状態をリクエストと同期させます。たとえば、ブラウザの「戻る」ボタンの検出およびブックマーク参照などは、このフェーズで処理されます。前後のリスナーの実行後、ページ・フロー・スコープが使用可能になします。
コンテキストの初期化: リクエストされたページのページ定義ファイルの実行時表現であるbindingContainer
オブジェクトが、ページ定義ファイルを使用して作成されます。ADFページ・ライフサイクルの全フェーズで情報を保持するためのLifecycleContext
クラスがインスタンス化され、関連付けられているリクエスト、バインディング・コンテナおよびライフサイクルの値で初期化されます。
モデルの準備: ADFページ・ライフサイクルは、BindingContainer.refresh(PREPARE_MODEL)
メソッドをコールすることにより、モデルの準備フェーズを開始します。モデルの準備フェーズでは、BindingContainer
ページ・パラメータが準備された後、評価されます。タスク・フローにパラメータが存在する場合、パラメータはフローに渡されます。
次に、RefreshプロパティがprepareModel
に設定された実行可能ファイルが、ページ定義ファイルの<executables>
セクション内のエントリの順序と、それらのRefreshCondition
プロパティ(存在する場合)の評価に基づいてリフレッシュされます。実行可能ファイルがイテレータ・バインディング・リフレッシュに到達すると、対応するデータ・コントロールが実行され、それによってサービス・オブジェクト内の1つ以上のコレクションが実行されます。イテレータ・バインディングがリフレッシュに失敗すると、JBO例外がスローされ、データを表示できなくなります。RefreshCondition
プロパティの詳細は、「pageNamePageDef.xml」を参照してください。
受信リクエストにPOST
データまたは問合せパラメータが含まれていない場合、ライフサイクルはレスポンスのレンダリング・フェーズに進みます。
ページがテンプレートを使用して作成されており、そのテンプレートにADFモデルを使用したバインディングが含まれている場合、テンプレートのページ定義ファイルを使用してテンプレートのバインディング・コンテナが作成されます。コンテナがバインディング・コンテキストに追加されます。
taskFlow
実行可能バインディングが存在する(ページにリージョンが含まれているなど)場合、taskFlow
バインディングによりADFコントローラのViewPortContext
オブジェクトがタスク・フローに作成された後、フローにあるページのネストされたバインディング・コンテナが実行されます。
リクエスト値の適用: ツリー内の各コンポーネントにより、リクエスト・パラメータから(そのデコード・メソッドを使用して)新しい値が抽出され、ローカルに格納されます。関連付けられているほとんどのイベントは、後の処理のためにキューされます。コンポーネントのimmediate
属性がtrue
に設定されている場合は、コンポーネントに関連付けられている検証、変換およびイベントがこのフェーズで処理され、ライフサイクルは検証処理フェーズ、モデル値の更新フェーズ、アプリケーションの起動フェーズをスキップします。さらに、関連イテレータが起動されます。ADF Facesの検証と変換の詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の「入力の検証および変換」を参照してください。
JSFのリクエスト値の適用: リクエスト値の適用フェーズに対して、フェーズ前後のイベントを提供します。リスナーを作成してこのフェーズの前または後のイベントに登録すると、リスナーをリクエスト値の適用フェーズに登録したときのように、アプリケーションが動作します。
検証処理: クライアントでコンポーネントのローカルの値が変換され、検証されます。エラーが発生した場合は、ライフサイクルがレスポンスのレンダリング・フェーズに進みます。このフェーズの最後に、コンポーネントの新しい値が設定され、検証または変換のエラー・メッセージおよびイベントがFacesContext
でキューされて、すべての値変更イベントが配信されます。例外もバインディング・コンテナにより捕捉されてキャッシュされます。
JSFの検証処理: 検証処理フェーズに対して、フェーズ前後のイベントを提供します。リスナーを作成してこのフェーズの前または後のイベントに登録すると、リスナーを検証処理フェーズに登録したときのように、アプリケーションが動作します。
モデル値の更新: コンポーネントの検証済のローカル値がモデルに移され、ローカル・コピーが破棄されます。更新可能なコンポーネント(inputText
コンポーネントなど)については、リフレッシュ条件がデフォルト(deferred
)に設定され、リフレッシュ条件(該当する場合)がtrue
に評価されている場合、対応するイテレータがリフレッシュされます。
JSFページのバッキングBeanを使用してUIコンポーネントを管理する場合、バッキングBeanプロパティにバインドされているUI属性もこのフェーズでリフレッシュされます。
JSFのモデル値の更新: モデル値の更新フェーズに対して、フェーズ前後のイベントを提供します。リスナーを作成してこのフェーズの前または後のイベントに登録すると、リスナーをモデル値の更新フェーズに登録したときのように、アプリケーションが動作します。
モデル更新の検証: モデルに設定された検証ルーチンと比較して、更新されたモデルが検証されます。例外がバインディング・コンテナにより捕捉されてキャッシュされます。
アプリケーションの起動: コマンド・コンポーネントまたはイベントのアクション・バインディングが起動されます。
JSFのアプリケーションの起動: アプリケーションの起動フェーズに対して、フェーズ前後のイベントを提供します。リスナーを作成してこのフェーズの前または後のイベントに登録すると、リスナーをアプリケーションの起動フェーズに登録したときのように、アプリケーションが動作します。
メタデータのコミット: 実行時メタデータへの変更がコミットされます。 このフェーズでは、メタデータ・サービス(MDS)を使用して、実行時にアプリケーションに対して行われるあらゆる変更が格納されます。MDSを使用した実行時の変更の保持の詳細は、「MDSによるアプリケーションのカスタマイズ」を参照してください。
内容の初期化(アプリケーションの起動ライフサイクルでナビゲーションが発生した場合のみ): 実行されるbeforeJSFRenderResponse
イベントをリスニングします。次のページのページ定義ファイルが初期化されます。
モデルの準備(アプリケーションの起動ライフサイクルでナビゲーションが発生した場合のみ): 次のページの定義に含まれるすべてのページ・パラメータが設定されます。
レンダリングの準備: バインディング・コンテナがリフレッシュされ、リクエスト値の適用フェーズまたは検証フェーズで発生したすべての変更が反映されます。読取り専用コンポーネント(outputText
コンポーネントなど)に対応するイテレータがリフレッシュされます。必要な場合は、すべての動的リージョンが切り替わります。afterJSFRenderResponse
イベントのように、登録されたすべてのリスナーにprepareRender
イベントが送信されます。
注意:
選択する有効フェーズとして、JDeveloperではprepareRender
ではなくrenderModel
が表示されます。これは、バインディング・コンテナでコールされるrefresh(RENDER_MODEL)
メソッドを表します。
レスポンスのレンダリング: Java EE Webコンテナがページ内のタグを横断するにつれて、ツリー内のコンポーネントがレンダリングされます。後続のリクエストおよびビューのリストア・フェーズ用に、状態の情報が保存されます。
ページと関連データの両方を表示するのに必要な待機時間を短くするため、特定のADF Facesコンポートネント(table
コンポーネントなど)では、最初のリクエストにデータ・ストリーミングを使用します。ページにこれらのコンポーネントが1つ以上含まれる場合、ページは通常のライフサイクルをたどります。しかし、そのリクエスト時にデータをフェッチするかわりに、特別な別のリクエストが実行されます。ページは単にレンダリングされるだけなので、データ・ストリーミングを使用するコンポーネントに対してレスポンスのレンダリング・フェーズのみが実行され、対応するデータがフェッチされ、表示されます。ユーザーのアクション(表でのスクロールなど)によって次のデータのフェッチが発生する場合は、別のリクエストが実行されます。表、ツリー、ツリー表などのコレクションベースのコンポーネントおよびデータ視覚化のコンポーネントはすべて、データ・ストリーミングを使用します。
JSFのレスポンスのレンダリング: レスポンスのレンダリング・フェーズに対して、フェーズ前後のイベントを提供します。リスナーを作成してこのフェーズの前または後のイベントに登録すると、リスナーをレスポンスのレンダリング・フェーズに登録したときのように、アプリケーションが動作します。
ADF Facesには、ページ上の特定のコンポーネント(通常は値が変更されたコンポーネント)にのみページ・リクエスト・ライフサイクル(変換と検証を含む)を実行する場合に使用できる、最適化されたライフサイクルが用意されています。
最適化されたライフサイクルを使用する方法の1つは、一方のコンポーネントのイベントが、もう一方のコンポーネント(ターゲット)のトリガーとして機能するように、依存性を手動で設定する方法です。トリガー・コンポーネントでイベントが発生すると、ターゲット・コンポーネントと、トリガーおよびターゲットの両方の子コンポーネントでライフサイクルが実行され、これらのコンポーネントのみがレンダリングされます。これは、部分ページ・レンダリング(PPR)とみなされます。
次の例は、トリガーの役割を果たすラジオ・ボタンと、ターゲットとなる出力テキストを保持するpanelGroupLayout
コンポーネントを示しています(outputText
コンポーネントは常時レンダリングされるわけではないため、panelGroupLayout
コンポーネントをターゲットとする必要があります)。
<af:form> <af:inputText label="Required Field" required="true"/> <af:selectBooleanRadio id="show" autoSubmit="true" text="Show" value="#{validate.show}"/> <af:selectBooleanRadio id="hide" autoSubmit="true" text="Hide" value="#{validate.hide}"/> <af:panelGroupLayout partialTriggers="show hide" id="panel"> <af:outputText value="You can see me!" rendered="#{validate.show}"/> </af:panelGroupLayout> </af:form>
ラジオ・ボタンのautoSubmit
属性がtrue
に設定されているため、選択されると、SelectionEvent
が起動されます。panelGroupLayout
コンポーネントが両方のラジオ・コンポーネントのターゲットとして設定されているため、このイベントが起動されると、selectOneRadio
(トリガー)、panelGroupLayout
コンポーネント(トリガーのターゲット)とその子コンポーネント(outputText
コンポーネント)のみ、ライフサイクルの処理が行われます。outputText
コンポーネントは表示ラジオ・ボタンの選択時にのみレンダリングされるよう構成されているため、ユーザーは、ラジオ・ボタンの上の必須入力フィールドにテキストを入力しなくても、ラジオ・ボタンを選択して出力テキストを表示できます。
部分トリガーとターゲットをコード内で手動で設定するかわりに、ADF Facesフレームワークには自動PPRが用意されています。自動PPRは、イベントに対応するイベント・ルート・コンポーネントが存在する場合、またはコンポーネント自体がイベント・ルートである場合に実行されます。イベント・ルート・コンポーネントにより、PPRの境界が決定されます。たとえば、attributeChangeEvent
はイベントを起動させるinputText
コンポーネントを、そのイベント・ルートであるとみなします。したがって、前述の例では、inputText
コンポーネントの値が変更されると、これがPPRの最初の境界であるため、inputText
コンポーネントとそのすべての子コンポーネント上のみでライフサイクルが実行されます。
イベント・ルートのほか、Fusion Webアプリケーションではデフォルトで、同一のイテレータ・バインディングに関連付けられたすべてのUIコンポーネントに対しても自動PPRが実行されます。関連付けられたすべてのコンポーネントは、そのいずれかで値変更イベントが発生するたびに、すべてリフレッシュされます。この機能は、イテレータのchangeEventPolicy
属性をppr
に設定することで制御します。デフォルトでは、これはグローバルに設定されています。
たとえば、「データ・コントロール」パネルを使用して多数のinputText
コンポーネントを作成するとします(フォームを作成する場合など)。これらのinputText
コンポーネントのいずれかでattributeChangeEvent
が発生すると、他のinputText
コンポーネントも同一のイテレータに関連付けられているため、これらすべてのinputText
コンポーネントがリフレッシュされます。
もう1つの例として、panelSplitter
コンポーネントを含むページがあるとします。スプリッタの左側は新規顧客を作成するためのフォーム(Customer
コレクションを使用してフォームをドロップして作成)であり、スプリッタの右側にはフォームの用法の説明文が表示されています。フォームを構成する各inputText
コンポーネントのバインディングは、すべてCustomer
イテレータに関連付けられているため、フォームが送信され、いずれかのinputText
コンポーネントの値が変更されるたびに、Customer
に関連付けられているinputText
コンポーネントのみがライフサイクル処理されます。スプリッタ右側の説明文を含め、ページの残りの部分はリフレッシュされません。
注意:
自動PPRを実行するには、イベントおよびイベント・ルート・コンポーネントが『Oracle ADF FacesによるWebユーザー・インタフェースの開発』のイベントおよび部分ページ・レンダリングに関する項の表5-1にリストされている必要があります。リストされていない場合は、同ガイドの、部分トリガーの使用に関する項を参照して、PPRを手動で設定する必要があります。
たとえば、同一のデータ・コントロール・コレクションに基づきフォームと表を作成するとします。フォームにはデータ行の詳細が表示され、表にはコレクション内のすべての行が表示されます。フォーム内で現在表示されている行は、表内でも選択された状態で表示されます。フォームの「次へ」ボタンがクリックされたときに、新たな行が選択された状態に表を更新させる必要があります。選択イベントは自動PPRによってサポートされないため、表とフォームは同一のイテレータを使用しているにもかかわらず、表はリフレッシュされません。ターゲットの表に対するPPRのトリガーとして、「次へ」および「前へ」ボタンを設定する必要があります。
注意:
構成済イテレータに関連付けられたページ定義ファイル内でコントロール・バインディングが定義されているUIコンポーネントのみが、リフレッシュされます。
マネージドBeanからイテレータに直接アクセスし、このBeanを介してイテレータの値をUIコンポーネントに公開する場合は、これらのUIコンポーネントに対して自動PPRは実行されません。この場合は、PPRを手動で構成する必要があります。詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の部分トリガーの使用に関する項を参照してください。
デフォルトでは、すべての新規アプリケーションではグローバルPPRが使用されます。設定する必要はありません。ただし、ページに対するページ定義ファイル内で、この設定をオーバーライドできます。
始める前に:
部分ページ・レンダリングに関する知識が役立つ場合があります。詳細は、「部分ページ・レンダリングおよびイテレータ・バインディングに関する必知事項」を参照してください。
PPRを使用するようにイテレータ・バインディングを設定するには:
特定のイテレータ・バインディングに対し、PPRを使用するように、または使用しないように設定するには、関連付けられたページ定義ファイルを開き、イテレータを選択して、「プロパティ」ウィンドウ内でChangeEventPolicyを設定します。
すべてのイテレータ・バインディングがPPRを使用するように設定するには:
「アプリケーション・リソース」パネルで、「ディスクリプタ」および「ADF META-INF」ノードを開き、「adf-config.xml」をダブルクリックします。
概要エディタで「モデル」ナビゲーション・タブをクリックし、「デフォルトの変更イベント・ポリシーはPPRです」を選択します。
ADF FacesフレームワークでのPPRの使用方法の詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の「部分ページ・コンテンツの再レンダリング」を参照してください。
タスク・フローは、(ページに関連付けられている)親バインディング・コンテナのリフレッシュ時に初めてリフレッシュされます。これはモデルの準備フェーズで発生します。後続のリクエストでは、レンダリングの準備フェーズにおいて、refresh
およびrefreshCondition
属性とそのパラメータ値に基づいてタスク・フローがリフレッシュされます。
注意:
子ページ・フラグメントのページ定義は、引き続き子ページ・フラグメントのバインディングのリフレッシュを処理します。
ヒント:
最初は公開されないリージョン(ポップアップ・ダイアログなど)がページ上にある場合、リージョンが表示されなくても、親ページのレンダリング時にパラメータは使用可能である必要があります。リージョンにパラメータが必要であるにもかかわらず、これらのパラメータ値を親ページのレンダリング時に使用できない場合は、動的リージョンを使用する必要があります。パラメータがNULLの場合、リージョンのパラメータの準備が完了してリージョンを表示できるようになるまで、空のタスク・フローを使用できます。空のタスク・フローに切り替えるには、動的リージョンのtaskFlowId
属性を空の文字列に設定します。
EL式をrefreshCondition
属性の値として設定した場合、ライフサイクルのレンダリングの準備フェーズ中に評価されます。式がtrue
に評価されると、タスク・フローは再度リフレッシュされます。refreshCondition
がfalse
に評価されると、refreshCondition
が指定されていない場合と動作は同じです。
注意:
EL式でbindings
変数が使用されていると、リージョン内に表示されるページ・フラグメントではなく、親ページのバインディング・コンテナが参照されます。
タスク・フロー実行可能ファイルのrefresh
プロパティの有効な値は次のとおりです。
default
: 親ページが最初に表示されるときに、リージョンは1回のみリフレッシュされます。
ifNeeded
: taskFlow
バインディングのパラメータ値に変更があった場合のみ、リージョンがリフレッシュされます。taskFlow
バインディングにパラメータがない場合、ifNeeded
はデフォルトと同じです。ifNeeded
を使用した場合、refreshCondition
属性は考慮されません。
注意:
refresh
属性をifNeeded
に設定した場合は、refreshCondition
属性のいずれの値よりも優先されます。また、動的パラメータMap
を使用してtaskFlow
バインディングにパラメータを渡す場合、ifNeeded
はサポートされません。その場合は、refreshCondition="#{EL.Expression}"
を使用します。
taskFlow
バインディングによる唯一の処理はそのパラメータのリフレッシュであり、Refresh
をalways
に設定する意味はありません。taskFlow
バインディングのパラメータが変更されないかぎり、ADFリージョンをリフレッシュする理由はありません。
子ページ・フラグメントのページ定義は、引き続き子ページ・フラグメントのバインディングのリフレッシュを処理します。
実行時には、バインディング・コンテナおよびマネージドBeanなどのADFオブジェクトはインスタンス化されています。これらのオブジェクトにはそれぞれ、そのスコープ属性により設定された存続期間が定義されています。RequestContext
APIからjava.util.Map
としてスコープにアクセスできます。たとえば、リクエスト・スコープのfoo
というオブジェクトにアクセスするには、式#{requestScope.foo}
を使用します。
オブジェクト・スコープは、プログラミング言語のグローバル変数およびローカル変数のスコープに相当します。スコープが広いほど、オブジェクトの可用性が高くなります。オブジェクトの存続期間中、これらのオブジェクトによってあるインタフェースが公開され、情報が保持され、あるいは変数およびパラメータが他のオブジェクトに渡されます。たとえば、セッション・スコープで定義されたマネージドBeanは、ページ・リクエストが複数存在する場合に使用できます。ただし、リクエスト・スコープで定義されたマネージドBeanは、1つのページ・リクエストが継続する間のみ使用できます。
Fusion Webアプリケーションには次の6種類のスコープがあります。
アプリケーション・スコープ: オブジェクトは、アプリケーションが継続する間使用できます。
セッション・スコープ: オブジェクトは、セッションが継続する間使用できます。
注意:
セッション・スコープにはウィンドウの一意性はなく、セッション内のすべてのウィンドウは、同じセッション・スコープ・インスタンスを共有します。複数のウィンドウが同じオブジェクトにアクセスできることが不適切な場合(たとえば、ウィンドウ間でマネージドBeanが競合しないようにする場合)は、ページ・フロー・スコープやビュー・スコープなどのウィンドウ固有のスコープを使用する必要があります。
ページ・フロー・スコープ: このオブジェクトは、タスク・フローの継続期間中、利用できます。その名のとおり、ページ・フロー・スコープは、タスク・フロー(バインドまたはバインドなし)のインスタンスに固有です。したがって、(タスク・フローによって作成された)2つ以上のリージョンを含むページがある場合、ページ・フロー・スコープの別のインスタンスが各リージョンに対して存在します。また、ユーザーが別のブラウザ・タブでリージョンを含むページを開く場合、ページ・フロー・スコープの別のインスタンスが各ブラウザ・タブに対してインスタンス化されます。
注意:
これは標準JSFスコープではないため、Beanを参照するためのスコープをEL式に明示的に含める必要があります。たとえば、pageFlowScope
スコープからMyBean
マネージドBeanを参照するには、#{pageFlowScope.MyBean}
という式になります。
リクエスト・スコープ: オブジェクトは、HTTPリクエストが作成された時点からレスポンスがクライアントに戻されるまで使用できます。
バッキングBeanスコープ: ページ・フラグメントおよび宣言コンポーネントのみのマネージドBeanに使用されます。このオブジェクトは、HTTPリクエストが発生してからレスポンスがクライアントに返送されるまでの間、利用できます。1つのページに複数のページ・フラグメントまたは宣言コンポーネントが含まれる場合があり、競合を避けるには別々のスコープ・インスタンスに値を保持する必要があるため、フラグメントおよび宣言コンポーネントにはこのスコープが必要です。したがって、すべてのページ・フラグメントまたは宣言コンポーネントのマネージドBeanで、バッキングBeanスコープを使用する必要があります。
注意:
これは標準JSFスコープではないため、Beanを参照するためのスコープをEL式に明示的に含める必要があります。たとえば、バッキングBeanスコープからMyBean
マネージドBeanを参照する場合の式は、#{backingBeanScope.MyBean}
になります。
ビュー・スコープ: このオブジェクトは、現在のビュー・アクティビティのビューIDが変更されるまで利用できます。このスコープは、所定のページの値を保持するために使用できます。ただし、1つのページから次のページに必要な値を格納するために使用できるリクエスト・スコープとは異なり、ビュー・スコープに格納されたものはビューIDの変更とともに失われます。
注意:
JSFおよびADF Facesはいずれも、ビュー・スコープを実装しています。ADF Facesのビュー・スコープのみが、ページのリダイレクトおよびリフレッシュの後も維持されます。Fusion Webアプリケーションでは、式でviewScope
を使用すると、ADF Facesビュー・スコープに解決されます。
このビュー・スコープは標準JSFスコープではないため、Beanを参照するためのスコープをEL式に明示的に含める必要があります。たとえば、ビュー・スコープからMyBean
マネージドBeanを参照する場合の式は、#{viewScope.MyBean}
になります。
注意:
スコープを定義する必要があるオブジェクト(マネージドBeanなど)を作成する場合、スコープをnone
に設定できます。これは、このオブジェクトが特定のスコープ内には存在しないが参照されるたびにインスタンス化されることを意味します。
デフォルトでは、バインディング・コンテナおよびそれに含まれるバインディング・オブジェクトは、セッション・スコープで定義されます。ただし、値バインディングおよびイテレータ・バインディングによって参照される値はリクエスト間で定義されず、スケーラビリティ上の理由により、セッション・スコープに残りません。このため、バインディング・オブジェクトが参照する値は、そのバインディング・コンテナがADFライフサイクルによって準備されているリクエストの間のみ有効です。セッション・スコープには、バインディング・コンテナおよびバインディング・オブジェクト自体のみ残されます。
図30-4に、各タイプのスコープが有効な期間を示します。
図30-4 スコープとページ・フローの関係
マネージドBeanをどのスコープに登録するかを決定するときは常に、できるかぎり狭いスコープを使用するようにします。セッション・スコープは、セッション全体に関連する情報(ユーザー情報やコンテキスト情報など)にのみ使用します。タスク・フロー間で値を渡すためにセッション・スコープを使用しないでください。ページ・フラグメントまたは宣言コンポーネントのマネージドBeanを作成するときは、バッキングBeanスコープを使用する必要があります。
マネージドBeanは、adfc-config.xml
または特定のタスク・フローの構成ファイルに登録できます。FusionアプリケーションでのマネージドBeanの使用の詳細は、「Fusion WebアプリケーションでのマネージドBeanの使用」を参照してください。
注意:
Fusion Webアプリケーションでは、faces-config.xml
でマネージドBeanを登録しないでください。
タスク・フロー内の変数にどのスコープを使用するかを決定するときは、アプリケーション・スコープまたはセッション・スコープ以外のスコープ・オプションを使用する必要があります。これら2つのスコープは、タスク・フローの存続期間を超えてオブジェクトをメモリーに保存するため、タスク・フローのカプセル化および再利用で障害が発生します。さらに、アプリケーション・スコープおよびセッション・スコープでは、オブジェクトがメモリーに必要以上に長い時間保持されるため、不要なオーバーヘッドが発生します。
タスク・フロー内のアクティビティ間でデータ値を渡す必要がある場合は、ページ・フロー・スコープを使用する必要があります。現在のビュー・アクティビティ内でのみ必要とされ、ビュー・アクティビティ間にまたがっていない変数の場合、ビュー・スコープを使用する必要があります。現在のリクエストより長い期間スコープが存続する必要がない場合には、リクエスト・スコープを使用する必要があります。これは、UIコンポーネント情報の格納に使用する唯一のスコープです。最後に、タスク・フローが同じページの2つのリージョン・コンポーネントまたは宣言コンポーネントに表示される可能性があり、リージョン・インスタンスを分離する場合、タスク・フロー内のマネージドBeanには、バッキングBeanスコープを使用する必要があります。
ADFライフサイクルには明確に定義されたフェーズが含まれており、このフェーズによって対応するJSFフェーズの実行前後にADFライフサイクル・リスナーに通知が行われます。このライフサイクルは、必要なコードを起動するカスタム・フェーズ・リスナーを作成した後、これらのフェーズのいずれかで実行されるようにライフサイクルに登録することによってカスタマイズできます。
注意:
1つのアプリケーションでは、複数のフェーズ・リスナー・インスタンスを保持できません。デフォルトでは、最初のADFPhaseListener
インスタンスがMETA-INF/faces-config.xml
構成ファイルに登録されます。たとえば、ADFPhaseListener
のカスタマイズされたサブクラスを登録すると、2つ目のインスタンスが作成されます。この場合、直近に登録されたインスタンスのみが使用されます。
警告メッセージ「ADFc: ADFページ・ライフサイクル実装を''新しいリスナーのクラス名''と置換しています。」により、インスタンスがより新しいものに置き換えられたことが通知されます。
カスタム・フェーズ・リスナーを作成するには、PagePhaseListener
インタフェースを実装するリスナー・クラスを作成する必要があります。次に、コードの実行が必要なフェーズの前または後にコードを実行するメソッドを追加します。
次の例は、カスタム・フェーズ・リスナーを作成するために変更できるテンプレートを示しています。JDeveloperでクラスを作成する方法の詳細は、「カスタム・クラスの生成方法」を参照してください。
public class MyPagePhaseListener implements PagePhaseListener { public void afterPhase(PagePhaseEvent event) { System.out.println("In afterPhase " + event.getPhaseId()); } public void beforePhase(PagePhaseEvent event) { System.out.println("In beforePhase " + event.getPhaseId()); } }
カスタム・リスナー・クラスを作成したら、クラスを起動する必要があるフェーズに登録する必要があります。アプリケーション全体で使用できるようにグローバルに登録するか、1つのページに対してのみ登録することができます。
ADFライフサイクルをグローバルにカスタマイズするには、adf-settings.xml
構成ファイルを編集してカスタム・フェーズ・リスナーを登録します。adf-settings.xml
ファイルは、ADFコントローラなど複数のADFコンポーネントにより共有され、構成情報を格納します。
adf-settings.xmlにリスナーを登録するには:
adf-settings.xml
では複数のフェーズ・リスナーを指定できるほか、これらの相対的なコール順序も任意で指定できます。このファイルに新しいリスナーを登録する際には、次の2つのパラメータを使用して、リスナー・リストでの配置を指定します。
beforeIdSet
: そのリスナーが、beforeIdSet
で指定されているリスナーよりも先にコールされます。
afterIdSet
: そのリスナーが、afterIdSet
で指定されているリスナーよりも後にコールされます。
次の例は、アプリケーション用に複数のリスナーが登録された構成ファイルの例を示しています。
<lifecycle> <phase-listener> <listener-id>MyPhaseListener</listener-id> <class>view.myPhaseListener</class> <after-id-set> <listener-id>ListenerA</listener-id> <listener-id>ListenerC</listener-id> </after-id-set> <before-id-set> <listener-id>ListenerB</listener-id> <listener-id>ListenerM</listener-id> <listener-id>ListenerY</listener-id> </before-id-set> </phase-listener> </lifecycle>
例では、MyPhaseListener
は登録されたリスナーであり、リスナーAおよびCの後かつ、リスナーB、MおよびYより先に実行されます。リスナーBの後にMyPhaseListener
を実行するには、リスナーBの<listener-id>
要素を<after-id-set>
要素の下に移動します。
単一ページのライフサイクルをカスタマイズするには、ページ定義ファイルでControllerClass
属性を設定します。このリスナーが有効なのは、ページ定義によって記述された特定ページのライフサイクルに対してのみです。ページ定義ファイルとFusion Webアプリケーションにおけるその役割の詳細は、「ページ定義ファイルの処理」を参照してください。
標準JSFページまたはページ・フラグメントのどちらに対するものかに応じて、異なるコントローラ・クラスを指定します。
単一ページまたはページ・フラグメント用にADFライフサイクルをカスタマイズするには:
「アプリケーション」ウィンドウで、ページまたはページ・フラグメントを右クリックし、「ページ定義に移動」を選択します。
「構造」ウィンドウで、ページ定義ノードを選択します。
「プロパティ」ウィンドウで、「ControllerClass」フィールドにカーソルを置いたときに表示されるアイコンをクリックして、「編集」を選択します。
「階層」タブをクリックし、ページまたはページ・フラグメントの目的のコントローラ・クラスに移動します。各種ページに使用するコントローラ・クラスを次に示します。
標準JSFページの場合 - oracle.adf.controller.v2.lifecycle.PageController
を指定
afterPhase/beforePhaseイベントを受信する必要がある場合は、oracle.adf.controller.v2.lifecycle.PagePhaseListener
を指定します。
ページ・フラグメント - 次を指定します。 oracle.adf.model.RegionController
ヒント:
完全修飾クラス名としてページ定義のControllerClass
属性の値を指定するか、ControllerClassフィールドに、クラスに直接解決されるEL式を入力できます。
ControllerClass
属性の値にEL式を使用すると、#{
YourExpression}
が有効なクラスではないことを示す警告が「構造」ウィンドウに表示される場合があります。この警告は無視しても問題ありません。