Oracle® Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド 11gリリース2 (11.1.2.1.0) B66719-01 |
|
前 |
次 |
この章では、ADF Facesクライアント側アーキテクチャの概要を説明します。
この章では、次の項目について説明します。
ADF Facesは、JavaServer Facesアーキテクチャを拡張し、標準のサーバー中心モデルの上にクライアント側フレームワークを追加しています。ADF Facesコンポーネントの大部分は、リクエストのためにサーバー側で生成されるHTMLにレンダリングされます。また、ADF Facesでは、クライアント側コンポーネントとイベント・モデルを使用してクライアントに到達できるようにコンポーネントを実装できます。
ADF Facesフレームワークには、JavaScriptを使用するために通常必要な機能の多くがすでに含まれています。多くの場合、JavaScriptを使用しなくても、リッチなコンポーネント機能を宣言的に実現できます。ただし、クライアント側イベントに対するカスタム処理など、独自のJavaScriptを追加する必要がある場合があります。このような場合は、クライアント側フレームワークを使用できます。
最も多く対話対象となるJavaScriptクラスはAdfUIComponent
とそのサブクラスです。このクラスのインスタンスは、サーバー側コンポーネントのクライアント側表現です。クライアント側コンポーネントは、イベント処理がサポートされる簡単なプロパティ・コンテナとみなすことができます。クライアント側コンポーネントは、主に、アプリケーション開発者とフレームワーク自体の両方に対するAPI規定を公開することでページに動作を追加するためにあります。特に、クライアントでのボタンの状態の切替えを可能にするのは、この規定です。
各クライアント・コンポーネントには、プロパティ(キーと値のペア)のセットと、サポートされている各イベント・タイプ用のリスナーのリストがあります。すべてのADF Faces JavaScriptクラスは、他のJavaScriptライブラリと名前が競合しないようAdf
で始まります。たとえば、RichCommandButton
はAdfRichCommandButton
を持ち、RichDocument
はAdfRichDocument
を持つなどです。
クライアント側JavaScriptレイヤーでは、クライアント・コンポーネントは主にフレームワークおよび開発者にAPI規定を提供するために存在します。クライアント・コンポーネントは、状態を格納し、APIを提供するためにのみ存在するため、DOM(Document Object Model)と直接対話しません。DOMとのすべての対話は、ピアと呼ばれる媒介を使用して行われます。ピアは、Javaレンダラによって生成されたDOMと対話し、その状態の更新およびユーザー操作への応答を処理します。
ピアでは、この他に次のような多くの処理が行われます。
この分離により、コンポーネントおよびアプリケーション開発者がコンポーネントのDOM実装の変更から隔離され、コンポーネント(たとえば、Flashコンポーネント)がHTML DOMで実装されているかどうかをアプリケーションが知る必要もまったくなくなります。
大部分のコンポーネントベースのフレームワーク同様、JSFのコンポーネント・モデルに固有の特性は、コンポーネントはネストして階層(通常コンポーネント・ツリーと呼ばれる)を形成できるということです。これは、親コンポーネントで子が追跡され、コンポーネント・ツリーをたどって特定のコンポーネントの子孫をすべて見つけることができるということです。コンポーネント・ツリー全体はサーバーにあり、ADF Facesクライアント側コンポーネント・ツリーにはあまり移入されません。
パフォーマンスを最適化するために、クライアント・コンポーネントは、clientListener
ハンドラが登録されているため、またはページ開発者がクライアント側のコンポーネントと対話する必要があり、クライアント・コンポーネントを使用可能として構成したため必要になった場合にのみ存在します。例外的なケースを除き、クライアント・フレームワークを理解する必要はありません。アーキテクチャ機能の大部分は、コードを作成せずに宣言的に使用できます。
たとえば、フレームワークでは、各サーバー側コンポーネントに対応するクライアント・コンポーネントをすべて作成するわけではないため、クライアント版のコンポーネント・インスタンスが必要な場合もあります。4.4項「クライアント側コンポーネントのインスタンス化」に、これを宣言的に行う方法が説明されています。JDeveloperのプロパティ・インスペクタを使用して、4.8項「レンダリングおよび可視性の理解」で説明されている、コンポーネントをレンダリングするかどうか、あるいは非表示にするかどうかを決めるプロパティを設定します。
注意: 既存のサーバー側コンポーネントに対応しないJavaScriptコンポーネントが存在することも可能です。たとえば、一部のADF Facesコンポーネントでは、ポップアップ・コンテンツが必要なクライアント側動作を持ちます。これらのコンポーネントでは、サーバー側JavaRichPopup コンポーネントが存在しなくても、AdfRichPopup JavaScriptコンポーネントを作成できます。 |
その他の機能では、ADF Faces JavaScript APIの使用が必要な場合があります。たとえば、4.5項「ページでのクライアント・コンポーネントの検索」では、APIを使用して特定のクライアント側コンポーネントを探す方法を説明し、4.6項「クライアントでのコンポーネント・プロパティへのアクセス」では、特定のプロパティにアクセスする方法を説明しています。
JavaScriptを多用したフレームワークに共通する問題は、大規模なJavaScriptコード・ベースをクライアントに送信する最良の方法を決定することです。すべてのコードが単一のJavaScriptライブラリにある場合はダウンロード時間が長くなりますが、JavaScriptを多くのライブラリに分割しすぎると、ラウンドトリップが大量になります。この問題を軽減するために、ADF FacesではJavaScriptコードがパーティションに集約されます。JavaScriptライブラリ・パーティションには、コンポーネントのコードまたは通常一緒に使用される機能、あるいはその両方が含まれています。詳細は、4.9項「JavaScriptライブラリのパーティション化」を参照してください。
従来のJSFアプリケーションでは、クライアントでイベントを処理する場合、DOMレベルのイベントをリスニングする必要があります。ただし、これらの実装は移植可能な形式で配信されません。ADF Facesのクライアント側イベント・モデルはJSFイベント・モデルと似ていますが、クライアントで実装されます。クライアント側イベント・モデルはDOMの要約で、コンポーネントレベルのイベント・モデルとライフサイクルが提供され、サーバーから独立して実行されます。このため、ボタンのclick
イベントをリスニングする必要がありません。かわりに、キーまたはマウスのイベントで発生するAdfActionEvent
イベントをリスニングできます。
クライアントによって送信されるイベントはすべてAdfBaseEvent
クラスのサブクラスです。各クライアント・イベントには、イベントをトリガーしたコンポーネントであるソースがあります。イベントには、イベントをリスニングするリスナーを判断するタイプ(action
またはdialog
など)もあります。クライアント・リスナーは、af:clientListener
タグを使用してコンポーネントに宣言的に登録します。
af:clientListener
タグを使用して、クライアント・イベントに対して対応するJavascriptをコールします。たとえば、クリックされたら"Hello World"アラートを表示する必要のあるボタンがあるとします。最初に、アラートを表示することでイベントに応答するJavaScript関数を作成する必要があります。次に、その関数を呼び出すクライアント・リスナーをコンポーネントに追加します。
前提作業
クライアント・イベント処理に関する知識が役立つ場合があります。詳細は、4.2項「クライアント・イベントのリスニング」を参照してください。
クライアント・イベントをリスニングする手順:
JavaScript関数を実装します。たとえば、アラートを表示するには、例4-1に示すJavaScript関数を作成できます。
コンポーネント・パレットの「操作」パネルから、「クライアント・リスナー」を、イベントを起動するコンポーネントに子としてドラッグ・アンド・ドロップします。
手順1で作成した関数と、リスナーが応答する必要のあるアクションのタイプを入力します。例4-2に、sayHello
関数のリスナーに対して作成するコードを示します。
ヒント: ボタンにクライアント・リスナーが登録されているため、フレームワークで、クライアント版のコンポーネントが自動的に作成されます。 |
クライアント版のコンポーネントがあるため、ボタンがクリックされると、Adf
Action
クライアント・イベントが起動されます。AdfAction
イベントをリスニングするようclientListener
タグが構成されているため、sayHello
関数が実行されます。クライアント側イベントの詳細は、6.3項「ADF Facesクライアント・イベントに対するJavaScriptの使用」を参照してください。
インラインJavaScriptをページに直接追加するか、JavaScriptライブラリをページにインポートできます。ライブラリをインポートする場合は、ページ・コンテンツ・サイズが削減され、ライブラリをページ間で共有でき、ブラウザによってキャッシュできます。可能な場合には必ずJavaScriptライブラリをインポートする必要があります。インラインJavaScriptは、ページ固有の小さなスクリプトが必要な場合にのみ使用します。
パフォーマンスのヒント: JavaScriptを必要とするページにのみJavaScriptを含めると、JavaScriptがテンプレートに含まれている場合とは異なり、それを必要としないページではロードする必要がないため、パフォーマンスが向上します。ただし、ほとんどのページで同じJavaScriptコードを使用する場合は、ライブラリをインポートするためのスクリプトまたはタグをテンプレートに含めることを検討してください。ただし、JavaScriptコード・ライブラリが非常に大きくなった場合、ライブラリを内容に応じて分割し、(テンプレートではなく)ページで必要な部分のみを含めることに注意してください。この方法で、ブラウザ・キャッシュが使用され、ページのHTMLコンテンツが小さくなるため、パフォーマンスが向上します。 |
JavaScriptをページに作成し、clientListener
タグを使用して呼び出します。
前提作業
ページへのJavaScriptの追加に関する知識が役立つ場合があります。詳細は、4.3項「JavaScriptのページへの追加」を参照してください。
インラインのJavaScriptを使用する手順:
例4-3に太字で示すコードを追加して、MyFaces Trinidadタグ・ライブラリをページのルート要素に追加します。
コンポーネント・パレットで、「レイアウト」パネルの「コア構造」グループから、「リソース」をページにドラッグ・アンド・ドロップします。
注意: ページまたはテンプレートにf:verbatim タグを使用してJavaScriptを指定しないでください。 |
「リソースの挿入」ダイアログで、ドロップダウン・メニューから「JavaScript」を選択し、「OK」をクリックします。
ページの<af:resource>タグ内にJavaScriptを作成します。
構造ウィンドウで、JavaScriptを呼び出すコンポーネントを右クリックし、「componentの中に挿入」→「ADF Faces」→「クライアント・リスナー」の順に選択します。
「クライアント・リスナーの挿入」ダイアログで「メソッド」フィールドにJavaScript関数の名前を入力します。タイプ・フィールドで、関数を起動するイベント・タイプを選択します。
af:resource
タグを使用して、ページからJavaScriptライブラリにアクセスします。このタグは、document
タグのmetaContainer
ファセットの内部に含める必要があります。
前提作業
ページへのJavaScriptの追加に関する知識が役立つ場合があります。詳細は、4.3項「JavaScriptのページへの追加」を参照してください。
ページからJavaScriptライブラリにアクセスする手順:
document
タグの下に、例4-5に太字で示すコードを追加し、JavaScriptライブラリが含まれるディレクトリへの相対パスに/mySourceDirectory
を置き換えます。
構造ウィンドウで、JavaScriptを呼び出すコンポーネントを右クリックし、「componentの中に挿入」→「ADF Faces」→「クライアント・リスナー」の順に選択します。
「クライアント・リスナーの挿入」ダイアログで「メソッド」フィールドに関数の完全修飾名を入力します。たとえば、sayHello
関数がMyScripts
ライブラリにある場合、MyScripts.sayHello
と入力します。タイプ・フィールドで、関数を起動するイベント・タイプを選択します。
JavaScriptでクライアント・コンポーネントにアクセスする必要がある場合、リスナーのコンテキストで行われ、イベントのソース・コンポーネントにアクセスする必要がある場合がしばしばあります。getSource()
メソッドを使用してクライアント・コンポーネントを取得します。例4-6に、名前を表示するためにソース・クライアント・コンポーネントにアクセスするsayHello
関数を示します。
例4-6 クライアント・イベント・ソースへのアクセス
function sayHello(actionEvent) { var component=actionEvent.getSource(); //Get the ID for the component var id=component.getId(); alert("Hello from "+id); }
クライアント・イベント・ソースへのアクセスの詳細は、6.3項「ADF Facesクライアント・イベントに対するJavaScriptの使用」を参照してください。クライアント側プロパティへのアクセスの詳細は、4.6項「「クライアントでのコンポーネント・プロパティへのアクセス」を参照してください。実行時にクライアント・イベントを処理する方法の詳細は、6.3.7項「実行時の処理: クライアント側イベントの機能の仕方」を参照してください。
デフォルトでは、フレームワークでは、どのコンポーネントが、対応するクライアント側コンポーネント・インスタンスを持つかについて保証されません。クライアント上のコンポーネントと対話するには、通常はclientListener
ハンドラを登録します。登録されているclientListener
ハンドラがコンポーネントにある場合、コンポーネントはクライアント側表現を自動的に持ちます。clientComponent
属性をtrue
に設定して、コンポーネントがクライアントで使用できるよう明示的に構成することもできます。
clientComponent
属性を使用してクライアント側インスタンスを持つようにコンポーネントを手動で構成できます。
パフォーマンスのヒント: クライアントのコンポーネントとプログラムで対話する場合にのみclientComponent をtrue に設定します。 |
注意: フレームワークが独自に使用するためにクライアント・コンポーネントを作成する場合、そのクライアント・コンポーネントにはその時点でフレームワークが必要とする情報のみ含まれます。たとえば、一部の属性は使用可能でない場合があります。 |
前提作業
クライアント側インスタンスに関する知識が役立つ場合があります。詳細は、4.4項「クライアント側コンポーネントのインスタンス化」を参照してください。
クライアント側インスタンスのコンポーネントを構成する手順:
構造ウィンドウで、クライアント側インスタンスを必要とするコンポーネントを選択します。
プロパティ・インスペクタで、ClientSideをtrue
に設定します。
clientComponent
属性をtrue
に設定すると、コンポーネントのAdfUIComponent
クラスのインスタンスがフレームワークで作成されます。このクラスでは、クライアント側で操作できるAPIが提供され、基本的なプロパティ・アクセッサ・メソッド(getProperty()
、setProperty()
など)、イベント・リスナーの登録およびイベント配信関連のAPIも提供されます。フレームワークには、プロパティ固有のアクセッサ・メソッド(getText()
、setText()
など)を公開するレンダラ固有のサブクラス(AdfRichOutputText
など)も用意されています。これらのアクセッサ・メソッドは、AdfUIComponent
クラスのgetProperty()
およびsetProperty()
メソッドをラップするのみのラッパーで、コーディングが簡便になるよう用意されています。
たとえば、sayHello
関数から値(表示するテキスト)を取得するoutputText
コンポーネントがページにあるとします。この関数は、値を設定するためにoutputText
コンポーネントにアクセスできる必要があります。これが機能するには、クライアント側バージョンのoutputText
コンポーネントがある必要があります。例4-7に、JSFページ・コードを示します。outputText
コンポーネントにid
値があり、clientComponent
属性がtrue
に設定されていることに注意してください。また、値はJavaScriptで設定されるため、例には値がないことにも注意してください。
例4-7 コンポーネントの追加
<af:commandButton text="Say Hello"> <af:clientListener method="sayHello" type="action"/> </af:commandButton> <af:outputText id="greeting" value="" clientComponent="true">
outputText
にクライアント側表現があるため、JavaScriptでこれを見つけて使用できます。
イベントのソースではないクライアント・コンポーネントを検索する必要がある場合、AdfUIComponent.findComponent(expr)
メソッドを使用できます。このメソッドはJSFのUIComponent.findComponent()
メソッドと似ており、指定した検索式に合致するIDを使用してUIComponent
オブジェクトを検索して返します。AdfUIComponent.findComponent(expr)
メソッドは、サーバーではなくクライアントでのみ機能します。
例4-8に、コンポーネントのIDを使用してoutputText
コンポーネントを検索するsayHello
関数を示します。
例4-8 findComponent()を使用したクライアント・コンポーネントの検索
function sayHello(actionEvent) { var buttonComponent=actionEvent.getSource(); //Find the client component for the "greeting" af:outputText var greetingComponent=buttonComponent.findComponent("greeting"); //Set the value for the outputText component greetingComponent.setValue("Hello World") }
ADF Facesには、AdfPage.PAGE.findComponentByAbsoluteId(absolute expr)
メソッドもあります。このメソッドは、IDの文字列をハードコーディングする場合に使用します。クライアントIDがコンポーネントから取得される場合は、AdfUIComponent.findComponent(expr)
を使用します。
注意: 似たような名前のAdfPage.PAGE.findComponent(clientId) というメソッドもありますが、この関数は、リリース間で変わる可能性のある実装固有の識別子を使用し、ページ作成者は使用しません。 |
見つける必要があるコンポーネントがネーミング・コンテナ(pageTemplate
、subform
、table
およびtree
など)であるコンポーネントにある場合は、AdfPage.PAGE.findComponentByAbsoluteId(absolute expr)
メソッドを使用するかわりに、AdfUIComponent.findComponent(expr)
メソッドを使用します。絶対式も相対式も使用できます。
ヒント: コンポーネントがネーミング・コンテナかどうかは、コンポーネント・タグのドキュメントを確認して判断できます。タグのドキュメントには、コンポーネントがネーミング・コンテナかどうかが示されています。 |
絶対式では、NamingContainer.SEPARATOR_CHAR
文字を先頭とし、完全修飾されたJSFクライアントID(コンポーネントを含むNamingContainer
コンポーネントのすべてのIDが先頭に付けられる)を使用します。次に例を示します。
":" + (namingContainersToJumpUp * ":") + some ending portion of the clientIdOfComponentToFind
たとえば、myTemplate
テンプレートを使用するページのID r1
のリージョンに含まれるID pc1
のパネル・コレクション・コンポーネント内にあるID t1
の表を検索するには、次の文字列を使用できます。
:myTemplate:r1:pc1:t1
または、両方のコンポーネント(検索を実行するコンポーネントと検索されるコンポーネント)が同じNamingContainer
コンポーネントを階層のどこかで共有する場合は、相対パスを使用して、検索を実行するコンポーネントとの相対で検索を実行できます。相対パスには、たとえば次のように、先頭に複数のNamingContainer.SEPARATOR_CHAR
文字があります。
":" + clientIdOfComponentToFind
前述の例で、検索元のコンポーネントが表と同じリージョンにある場合、次を使用できます。
::somePanelCollection:someTable
ヒント: ネーミング・コンテナをフォルダと考え、clientId をファイル・パスと考えます。フォルダとファイルに関して、2つの連続ピリオドとスラッシュ(../) を使用して、階層内の上にホルダに移動します。これは、複数のコロン(: )文字がfindComponent() 式で果たす役割と同じです。先頭の単一のコロン(: )は、ファイル・パスが、ファイル構造のルートからの絶対パスであることを意味します。式の先頭に複数のコロン(: )文字がある場合、最初のコロンは無視され、他のコロンは考慮されます。コロン(: )文字当たり1セットのピリオドとスラッシュ(../ )が考慮されます。
|
絶対パスを使用するか相対パスを使用するかを決める際、次の点に注意します。
検索対象のコンポーネントが常に同じネーミング・コンテナ内あることがわかっている場合は、絶対パスを使用します。
検索元のコンポーネントと検索対象のコンポーネントの相対的位置が常に同じであることがわかっている場合は、相対パスを使用します。
クライアントにはgetChildren()
関数もgetFacet()
関数もありません。かわりに、すべての子コンポーネントとファセット(つまり、すべての子孫)にアクセスするAdfUIComponent.visitChildren()
関数が用意されています。ADF Facesはスパース・コンポーネント・ツリー(クライアント・コンポーネントが必要に応じて作成されるツリー)であるため、getParent()
メソッドがクライアントで返すコンポーネントは、サーバー上の実際の親ではない場合があります(先祖である可能性はあります)。同様に、クライアント上に直接の子として出現するコンポーネントは、任意の子孫である可能性があります。詳細は、ADF Faces JavaScriptのドキュメントを参照してください。
コンポーネントの各組込みプロパティには、簡易アクセッサ・メソッドがコンポーネント・クラスに用意されています。たとえば、クライアント・コンポーネントでgetValue()
メソッドをコールし、サーバーで使用されたのと同じ値を受け取ることができます。
注意: ADF Faces内のブール・プロパティを含むすべてのクライアント・プロパティでgetXyz 関数ネーミング規則を使用します。ブール・プロパティのisXyz ネーミング規則は使用されません。 |
定数もクラス・オブジェクトのプロパティ名に使用できます。たとえば、styleClass
を使用するかわりにAdfRichDialog.STYLE_CLASS
定数を使用できます。
注意: 一部のJavaScript実行環境では、文字列をコーディングすると呼出しのたびにオブジェクトを割り当てる必要があるため、JavaScriptでは、文字列をコーディングするよりも定数を参照する方が効率的です。 |
コンポーネントのプロパティが変更されると、最終的な結果として、コンポーネントのDOMが新しい状態を反映するように更新されます。場合によっては、サーバーへのラウンドトリップは発生しません。このプロセスにおけるコンポーネントのロールはかなり限られています。新しいプロパティ値を格納してから、変更をピアに通知するだけです。ピアには、新しいコンポーネント状態を反映するようにDOMを更新するロジックが含まれます。
注意: すべてのプロパティの変更が、クライアント側のピアを使用して処理されるわけではありません。一部のプロパティ変更はサーバーに伝播され、PPRを使用してコンポーネントがレンダリングされます。 |
クライアントに設定されるほとんどのプロパティ値は、サーバーとの自動同期が行われる原因になります(ただし、一部の複合Javaオブジェクトはクライアントにまったく送信されません)。ただし、これとは異なる動作をするセキュア・プロパティと分離プロパティの2種類のプロパティがあります。
セキュア・プロパティは、クライアントにまったく設定できないプロパティです。たとえば、悪意のあるクライアントでJavaScriptを使用してcommandLink
コンポーネントのimmediate
フラグがtrue
に設定されるとします。この変更がサーバーに伝播された結果、サーバー側の検証が省略され、セキュリティ・ホールとなる可能性があります(immediate
プロパティの使用の詳細は、5.2項「immediate属性の使用」を参照してください)。つまり、immediate
プロパティはセキュア・プロパティです。
JavaScriptからセキュア・プロパティの設定を試みると失敗します。詳細は、4.6.3項「無効化されたプロパティを非保護にする方法」を参照してください。表4-1に、クライアント・コンポーネントのセキュア・プロパティを示します。
表4-1 セキュア・クライアント・プロパティ
コンポーネント | セキュア・プロパティ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ADF Facesでは、disabled
プロパティを非保護にできるように構成できます。この機能は、JavaScriptを使用してボタンを有効および無効にする必要がある場合に役立ちます。
分離プロパティは、クライアントで設定できるがサーバーに伝播することはできないプロパティです。これらのプロパティには、サーバーのライフサイクルに依存しないクライアント上のライフサイクルがあります。たとえば、クライアント・フォーム入力コンポーネント(AdfRichInputText
など)には、JavaのEditableValueHolder
コンポーネントのようにsubmittedValue
プロパティがあります。ただし、このプロパティの設定はサーバーに直接影響しません。この場合、標準のフォーム送信手法によって、送信された値のサーバーでの更新を処理します。
プロパティは、分離とセキュアの両方にすることができます。実際には、このようなプロパティはクライアント上で分離プロパティのように動作します。これらはクライアントで設定できますが、サーバーには送信されません。ただし、サーバーではセキュア・プロパティとして動作するため、クライアントがこれらを設定しようとすると拒否されます。
ADF Facesフレームワークには、基礎となるADFUIComponent.setProperty
関数をコールして適切なプロパティ名を渡す便利なsetXYZ
関数が用意されています(詳細は、ADF Faces JavaScript JavaDocを参照してください)。例4-9に、setProperty
関数を使用して、値が変更されたときにinputText
コンポーネントのbackgroundcolor
プロパティを赤に設定する方法を示します。
例4-9
<af:form> <af:resource type="javascript"> function color(event) { var inputComponent = event.getSource(); inputComponent.setproperty("inlineStyle", "background-color:Red"); } </af:resource> <af:outputText id="it" label="label"> <af:clientListener method="color" type="valueChange"/> </af:inputText> </af:form>
これらの関数を使用してプロパティの値を変更できます。分離プロパティまたはセキュア・プロパティでないかぎり、値はサーバー上でも変更されます。
プロパティの値をサーバーに常に配信して同期することは望ましくない場合があります。たとえば、フォームにinputText
コンポーネントがあり、ユーザーがコンポーネントの1つで値を変更したらすぐに、変更済インジケータを表示するとします。この操作を行うには、JavaScriptを使用して、valueChangeEvent
イベントが配信されたらクライアント・コンポーネントのchanged
属性をtrue
に設定します。また、ユーザーがページを送信した場合は、その時点で値が保存されるため、変更済インジケータを表示しません。
次の例に示すように、JavaScriptを使用して、valueChangeEvent
が配信されたらchanged属性をtrueに設定します。
例4-10 JavaScriptを使用したchangedプロパティの設定
<af:form> <af:resource type="javascript"> function changed(event) { var inputComponent = event.getSource(); inputComponent.setChanged(true); } </af:resource> <af:inputText id="it" label="label"> <af:clientListener method="changed" type="valueChange"/> </af:inputText> <af:commandButton text="Submit"/> </af:form>
コンポーネントのすべてのプロパティは一般にサーバーと同期されるため、この例を使用すると、changed
属性の値(true
)はサーバーにも送信されます。このため、変更済インジケータは引き続き表示されます。
値がサーバーに保存されたときにインジケータを表示しないようにするには、次のいずれかの代替方法を使用できます。
イベント・リスナーを使用して、ロジックをクライアントからサーバーに移動します。この代替方法は、valueChangeEvent
イベントなど、サーバーに配信されるイベントがある場合に使用します。例4-11に、JSPコード例を示します。
例4-11 サーバー上のプロパティ値を設定するJSPコード
<af:form> <af:inputText label="label" autoSubmit="true" changed="#{test.changed}" valueChangeListener="#{test.valueChange}"/> <af:commandButton text="Submit" /> </af:form>
例4-12に、対応するマネージドBeanコードを示します。
例4-12 マネージドBeanを使用したプロパティ値の設定
import javax.faces.event.ValueChangeEvent; import oracle.adf.view.rich.context.AdfFacesContext; public class TestBean { public TestBean() {} public void valueChange(ValueChangeEvent valueChangeEvent) { setChanged(true); AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance(); adfFacesContext.addPartialTarget(valueChangeEvent.getComponent()); FacesContext.getCurrentInstance().renderResponse(); } public void setChanged(boolean changed) { _changed = changed; } public boolean isChanged() { return _changed; } private boolean _changed; }
カスタム・サーバー・イベントとserverListener
タグを呼び出すJavaScriptを使用して、ロジックをサーバーに移動します。この方法は、配信されるイベントがない場合に使用します。例4-13に、JSPコードを示します。
例4-13 JavaScriptとサーバー・リスナーを使用してプロパティ値を設定するJSPコード
<af:form> <af:resource type="javascript"> function changed(event) { var inputComponent = event.getSource(); AdfCustomEvent.queue(inputComponent, "myCustomEvent", null, true); } </af:resource> <af:inputText label="label" changed="#{test2.changed}"> <af:serverListener type="myCustomEvent" method="#{test2.doCustomEvent}"/> <af:clientListener method="changed" type="valueChange"/> </af:inputText> <af:commandButton text="Submit"/> </af:form>
例4-14に、マネージドBeanコードを示します。
例4-14 カスタム・イベントを使用したプロパティ値の設定
package test; import javax.faces.context.FacesContext; import oracle.adf.view.rich.context.AdfFacesContext; import oracle.adf.view.rich.render.ClientEvent; public class Test2Bean { public Test2Bean() { } public void doCustomEvent(ClientEvent event) { setChanged(true); AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance(); adfFacesContext.addPartialTarget(event.getComponent()); FacesContext.getCurrentInstance().renderResponse(); } public void setChanged(boolean changed) { _changed = changed; } public boolean isChanged() { return _changed; } private boolean _changed; }
クライアント・コンポーネントでchanged
属性をtrue
に設定し、これがサーバーに伝播されますが、その後コマンド・コンポーネントでactionListener
を使用して、changed
属性をfalse
に戻します。例4-15に、JSPコードを示します。
例4-15 コマンド・コンポーネント上のリスナーを使用してプロパティ値を設定するJSPコード
<af:form> <af:resource type="javascript"> function changed(event) { var inputComponent = event.getSource(); inputComponent.setChanged(true); } </af:resource> <af:inputText binding="#{test3.input}" label="label"> <af:clientListener method="changed" type="valueChange"/> </af:inputText> <af:commandButton text="Submit" actionListener="#{test3.clear}"/> </af:form>
例4-16に、対応するマネージドBeanコードを示します。
例4-16 ActionLIstenerを使用したプロパティ値の設定
package test; import javax.faces.event.ActionEvent; import oracle.adf.view.rich.component.rich.input.RichInputText; public class Test3Bean { public Test3Bean() { } public void clear(ActionEvent actionEvent) { _input.setChanged(false); } public void setInput(RichInputText input) { _input = input; } public RichInputText getInput() { return _input; } private RichInputText _input; }
unsecured
プロパティを使用して、disabled
プロパティを非保護に設定します。disabled
プロパティを非保護にする必要のあるコンポーネントのコードに、このプロパティとdisabled
の値を手動で追加する必要があります。たとえば、disabled
プロパティを非保護にする必要のあるボタンのコードは次のようになります。
<af:commandButton text="commandButton 1" id="cb1" unsecure="disabled"/>
unsecure
属性をdisabled
に設定すると、悪意のあるJavaScriptがdisabled
属性を不注意で変更する可能性があります。たとえば、支出承認ページがあり、そのページで特定のマネージャが200ドル未満の請求書のみ承認できるようにするとします。そのため、現在のユーザーが請求書の承認を許可されていないかぎり、承認ボタンを無効にする必要があります。
unsecured
属性disabled
に設定していない場合、承認ボタンは、現在のユーザーが支出を承認できるかどうかを判断するロジックがあるサーバーとのラウンドトリップが発生するまで無効なままになります。ただし、ページに支出がロードされたときにはボタンを正しく表示する必要があるため、unsecure
属性をdisabled
に設定します。これで、クライアントでJavaScriptを使用して、ボタンを無効にするかどうかを判断できます。ただし、この場合は、任意のJavaScript(制御できない悪意のあるJavaScriptを含む)が同じことを行う可能性があります。
悪意のあるJavaScriptを回避するには、ボタンが悪意のあるクライアント側Javascriptによって有効にされた可能性があるため、現在のマネージャが承認を実行する前に適切な支出管理権限を持っていることを必ず再チェックする必要があることを、アプリケーションで常に想定する必要があります。支出レポート承認画面で、金額が200ドル未満であることをチェックするJavaScriptがあっても、承認ボタンのアクションではサーバー上のロジックを実行する必要があります。サーバーにロジックを追加すると、無効な属性を変更してはならない場合に、それが変更されません。
同様に、アプリケーションを実行時に変更できるようにし、ユーザーがunsecure
またはdisabled
属性、あるいはその両方を編集できるようにする場合は、サーバーとのラウンドトリップが発生した場合と同じロジックがアプリケーションによって実行されるようにする必要があります。
組込みプロパティ以外の情報をクライアントに送信する必要がある場合もあります。これは、ボーナス属性を使用して行えます。ボーナス属性は、clientAttribute
タグを使用してコンポーネントに追加できる追加属性です。パフォーマンス上の理由から、クライアントに送信されるボーナス属性は、clientAttribute
で指定されたもののみです。
clientAttribute
タグでは、サーバー側コンポーネントの属性マップに追加される名前と値のペアを指定します。サーバー側属性マップの移入に加えて、clientAttribute
タグを使用すると、ボーナス属性がクライアントに送信され、AdfUIComponent.getProperty("
bonusAttributeName
")
メソッドを使用してアクセスできます。
フレームワークで、属性値のクライアントへのマーシャリングが行われます。マーシャリング・レイヤーで、文字列、ブール、数値、日付、配列、マップなど、各オブジェクト型のマーシャリングがサポートされます。マーシャリングの詳細は、6.4.3項「データのマーシャリングとアンマーシャリングについて」を参照してください。
パフォーマンスのヒント: マーシャリングによる過度のオーバーヘッドを防ぐため、クライアント側ボーナス属性を多用しないでください。 |
注意: clientAttribute タグは、(アプリケーションで定義される)ボーナス属性にのみ使用します。クライアントで標準のコンポーネント属性にアクセスする必要がある場合、clientAttribute タグを使用するのではなく、clientComponent 属性をtrue に設定します。詳細は、4.4項「クライアント側コンポーネントのインスタンス化」を参照してください。 |
コンポーネント・パレットを使用して、ボーナス属性をコンポーネントに追加できます。
前提作業
ボーナス属性に関する知識が役立つ場合があります。詳細は、4.7項「クライアント側コンポーネントに対するボーナス属性の使用」を参照してください。
ボーナス属性を作成する手順:
構造ウィンドウで、ボーナス属性を追加するコンポーネントを選択します。
コンポーネント・パレットで、「操作」パネルから「クライアント属性」をコンポーネントに子としてドラッグ・アンド・ドロップします。
プロパティ・インスペクタで「名前」と「値」属性を設定します。
クライアント側ボーナス属性は、サーバーからクライアントへ自動的に配信されますが、その逆は行われません。つまり、クライアントでのボーナス属性の変更または設定は、サーバーに反映されません。既知(ボーナス以外)の属性のみ、クライアントからサーバーへ同期がとられます。アプリケーションで定義されたデータをサーバーに送り返す必要がある場合、カスタム・イベントを作成します。詳細は、6.4項「クライアントからサーバーへのカスタム・イベントの送信」を参照してください。
すべてのADF Faces表示コンポーネントには、コンポーネントをページに表示してユーザーに見えるようにするかどうかに関係するrendered
とvisible
の2つの属性があります。
rendered
属性のセマンティクは非常に厳密です。rendered
がfalse
に設定されている場合、サーバーへのラウンドトリップなしにコンポーネントをクライアントで表示することはできません。ページのコンテンツの動的な表示/非表示をサポートするために、フレームワークにはvisible
属性が追加されています。false
に設定されている場合、コンポーネントのマークアップはクライアントで使用可能ですが、コンポーネントは表示されません。したがって、setVisible(true)
またはsetVisible(false)
メソッドをコールすると、JavaからのコールであろうとJavaScriptからのコールであろうと、コンポーネントがブラウザ内で表示または非表示になります(rendered
がtrue
に設定されている場合)。ただし、visible
は単純にDOMのコンテンツを表示および非表示にするため、rendered
を使用した場合と常に同じ視覚的変化を提供するとはかぎりません。
パフォーマンスのヒント: JavaScriptなど、サーバーへのラウンドトリップなしに可視性を切り替える必要がある場合にのみvisible 属性をfalse に設定します。非表示のコンポーネントも、検証を含むコンポーネント・ライフサイクルを経過します。
クライアントでのみ可視性を切り替える必要がない場合は、かわりに |
例4-17に、2つのoutputText
コンポーネントを示します。一度にその一方のみがレンダリングされます。最初のoutputText
コンポーネントは、値がinputText
コンポーネントに入力されなかった場合にレンダリングされます。2番目のoutputText
コンポーネントは、値が入力されたときにレンダリングされます。
例4-17 レンダリングされる/レンダリングされないコンポーネント
<af:panelGroupLayout layout="horizontal"> <af:inputText label="Input some text" id="input" value="#{myBean.inputValue}"/> <af:commandButton text="Enter"/> </af:panelGroupLayout> <af:panelGroupLayout layout="horizontal"> <af:outputLabel value="You entered:"/> <af:outputText value="No text entered" id="output1" rendered="#{myBean.inputValue==null}"/> <af:outputText value="#{myBean.inputValue}" rendered="#{myBean.inputValue !=null}"/> </af:panelGroupLayout>
コンポーネントがクライアントでレンダリングされる場合、visible
プロパティを使用してコンポーネントをページに表示したり、非表示にできます。
例4-18に例4-17と同じ機能を示しますが、この例ではvisible
属性を使用して、表示されるコンポーネントを判断します(rendered
属性はデフォルトでtrue
に設定されるため、明示的に設定する必要はありません)。
例4-18 表示可能/表示不可能なコンポーネント
<af:panelGroupLayout layout="horizontal"> <af:inputText label="Input some text" id="input" value="#{myBean.inputValue}"/> <af:commandButton text="Enter"/> </af:panelGroupLayout> <af:panelGroupLayout layout="horizontal"> <af:outputLabel value="You entered:"/> <af:outputText value="No text entered" id="output1" visible="#{myBean.inputValue==null}"/> <af:outputText value="#{myBean.inputValue}" visible="#{myBean.inputValue !=null}"/> </af:panelGroupLayout>
ただし、visible
属性のかわりにrendered
属性を使用することは、サーバー側でのパフォーマンスを向上させるため、JavaScriptで可視性を処理することもできます。
例4-19に、コンポーネントの可視性を処理するJavaScriptのページ・コードを示します。
例4-19 JavaScriptを使用した可視性の切替え
function showText() { var output1 = AdfUIComponent.findComponent("output1") var output2 = AdfUIComponent.findComponent("output2") var input = AdfUIComponent.findComponent("input") if (input.getValue() == "") { output1.setVisible(true); } else { output2.setVisible(true) } }
コンポーネントのvisible
属性を切り替えられる条件付きJavaScript関数を作成できます。
前提作業
コンポーネントの表示方法に関する知識が役立つ場合があります。詳細は、4.8項「レンダリングおよび可視性の理解」を参照してください。
可視性を設定する手順:
可視性を切り替えるJavaScriptを作成します。例4-19に、値がない場合にoutputText
コンポーネントの可視性を有効にし、そうでない場合は別のoutputText
コンポーネントの可視性を有効にするスクリプトを示します。
JavaScript関数に必要なコンポーネントごとに、プロパティ・インスペクタで拡張セクションを開き、ClientComponent
属性をtrue
に設定します。これによって、JavaScriptで使用されるクライアント・コンポーネントが作成されます。
可視性を切り替えるコンポーネントのvisible
属性をfalse
に設定します。
例4-20に、JavaScriptを使用した可視性の切替えに使用されるページ・コード全体を示します。
例4-20 JavaScriptでの可視性の切替え
<f:view> <af:resource> function showText() { var output1 = AdfUIComponent.findComponent("output1") var output2 = AdfUIComponent.findComponent("output2") var input = AdfUIComponent.findComponent("input") if (input.value == "") { output1.setVisible(true); } else { output2.setVisible(true) } } </af:resource> <af:document> <af:form> <af:panelGroupLayout layout="horizontal"> <af:inputText label="Input some text" id="input" value="#{myBean.inputValue}" clientComponent="true" immediate="true"/> <af:commandButton text="Enter" clientComponent="true"> <af:clientListener method="showText" type="action"/> </af:commandButton> </af:panelGroupLayout> <af:panelGroupLayout layout="horizontal"> <af:outputLabel value="You entered:" clientComponent="false"/> <af:outputText value="No text entered" id="output1" visible="false" clientComponent="true"/> <af:outputText value="#{myBean.inputValue}" id="output2" visible="false" clientComponent="true"/> </af:panelGroupLayout> </af:form> </af:document> </f:view>
コンポーネントの親のvisible
属性がfalse
に設定されている場合、visible
属性がtrue
に設定されている子コンポーネントにisVisible
関数が実行されると、子が表示されていなくてもtrue
が返されます。たとえば、outputText
コンポーネントを子として含むpanelGroupLayout
コンポーネントがあり、panelGroupLayout
コンポーネントのvisible
属性はfalse
に設定され、outputText
コンポーネントのvisible
属性はデフォルトのまま(true
)とします。クライアントでは、panelGroupLayout
コンポーネントもoutputText
コンポーネントも表示されませんが、isVisible
関数がoutputText
コンポーネントに実行されると、true
が返されます。
このため、フレームワークにはisShowing()
関数が用意されています。この関数は、コンポーネントのvisible
属性がfalse
に設定されている場合、またはコンポーネントの親のvisible
がfalse
に設定されている場合、false
を返します。
JavaScriptを多用したフレームワークに共通する問題は、大規模なJavaScriptコード・ベースをクライアントに送信する最良の方法を決定することです。極端な方法は、すべてのコードを1つのJavaScriptライブラリにバンドリングすることで、この方法ではダウンロード時間が長くなります。逆の極端な方法はJavaScriptコードを多数の小さなJavaScriptライブラリに分割することで、この方法ではラウンドトリップ数が大きくなります。どちらの方法でも初期ページをロードするためのユーザーの待ち時間が不必要に長くなります。
この問題を軽減するために、ADF FacesではJavaScriptコードがパーティションに集約されます。JavaScriptライブラリ・パーティションには、コンポーネントのコードまたは通常一緒に使用される機能、あるいはその両方が含まれています。ADF Facesではデフォルトで、ダウンロード・サイズ合計とラウンドトリップ数合計のバランスをとることを意図したパーティション化が行われます。
ADF Facesのライブラリ・パーティション化方式の利点の1つは、構成可能であることです。アプリケーションによって使用するコンポーネントおよび機能が異なるため、ADF Facesのデフォルトのパーティション化がすべてのアプリケーションに最適であるとはかぎりません。このため、ADF FacesのJavaScriptライブラリのパーティション化はアプリケーションごとにカスタマイズ可能になっています。このパーティション化により、アプリケーション開発者はJavaScriptライブラリのフットプリントをアプリケーションの要件に合せて調整できます。
ADF Facesは、そのコンポーネントのJavaScriptファイルをJavaScript機能にグループ化します。JavaScript機能は、その機能を記述する論理識別子に関連付けられたJavaScriptファイルのコレクションです。たとえば、panelStretchLayout
クライアント・コンポーネントは、次の2つのJavaScriptファイルで構成されます。
oracle/adf/view/js/component/rich/layout/
AdfRichPanelStretchLayout.js
oracle/adfinternal/view/js/laf/dhtml/rich/
AdfDhtmlPanelStretchLayoutPeer.js
これらの2つのファイルは、AdfRichPanelStretchLayout
機能にグループ化されます。
JavaScriptの機能は、JavaScriptパーティションにグループ化されます。JavaScriptパーティションでは、ダウンロード・サイズとラウンドトリップ数に影響を与えることを目標に、JavaScript機能をより大きなコレクションにグループ化できます。たとえば、panelStretchLayout
コンポーネントはpanelSplitter
コンポーネントで使用されることが多く、この2つのコンポーネントの機能は、子を拡大できる他のADF Facesレイアウト・コンポーネントとともにストレッチ・パーティションにグループ化されます。実行時に、ページがロードされると、フレームワークはページで使用されるコンポーネントを決定し、必要な機能をそこから判断します(機能名は、コンポーネントのコンストラクタ名と同じです)。これらの機能を含むパーティションのみダウンロードされます。
機能およびパーティションは、構成ファイルを使用して定義されます。ADF Facesには、デフォルトの機能およびパーティション構成ファイルが含まれています。独自の実装を作成することでデフォルトのパーティションを上書きできます。カスタムADF Facesコンポーネントを作成する場合、これらのコンポーネントに独自の機能およびパーティション構成ファイルを作成できます。
デフォルトでJavaScriptのパーティション化は有効にされています。アプリケーションでJavaScriptのパーティション化を使用するかどうかは、web.xml
ファイルのコンテキスト・パラメータによって決定されます。詳細は、A.2.3.17項「JavaScriptのパーティション化」を参照してください。
adf-js-features.xml
ファイルを作成してから機能にエントリを追加することでJavaScript機能を作成できます。
注意: カスタムADF Facesコンポーネントを作成する場合に、JavaScript機能を作成できます。すべての既存のADF Facesコンポーネントには、すでにそれらのコンポーネント向けに作成された機能があり、これらは変更できません。 |
前提作業
JavaScriptのパーティション化の動作に関する知識が役立つ場合があります。詳細は、4.9項「JavaScriptライブラリのパーティション化」を参照してください。
JavaScript機能を作成する手順:
コンポーネント用のMETA-INF
ディレクトリの作成がまだの場合は、これを作成します。
META-INF
ディレクトリを右クリックし、ポップアップ・メニューから「新規」を選択します。
「新規ギャラリ」で、「一般」を展開し、「XML」→「XMLドキュメント」を選択して、「OK」をクリックします。
ヒント: 「一般」ノードが表示されない場合、ギャラリの上部の「すべてのテクノロジ」タブをクリックします。 |
ファイル名にadf-js-features.xml
と入力し、META-INF
ディレクトリに保存します。
ソース・エディタで、生成されたコードを例4-21のコードに置き換えます。
次の要素を追加すると、関連するコンポーネント・ファイルおよび依存性とともに機能が移入されます。
features:
構成ファイルのルート要素です。
feature:
features
要素の子として作成されます。この要素には1つのfeature-name
子要素が含まれている必要があり、feature-class
要素およびfeature-dependency
要素はいくつでも含めることができます。
feature-name:
feature
要素の子として作成されます。機能の名前を指定します。この値にはクライアント・コンポーネントのコンストラクタ名を使用する必要があります。
feature-class:
feature
要素の子として作成されます。この機能に含める1つのJavaScriptファイルまたはクラスの場所を指定します。複数のfeature-class
要素がある場合もあります。
feature-dependency:
feature
要素の子として作成されます。この機能が依存する別の機能の名前を指定します。たとえば、コンポーネントBでコンポーネントAを拡張する場合、コンポーネントAを示す機能はコンポーネントBへの依存性としてリストされている必要があります。依存性を記述することで、フレームワークは2つの機能が同じパーティションになくても、依存するクラスが使用できることを確認できます。
例4-22に、ポップアップ・コンポーネントを使用し、ポップアップ機能への依存性を持つ架空のカスタム・コンポーネントのfeature
要素を示します。
例4-22 JavaScript機能の構成
<features xmlns="http://xmlns.oracle.com/adf/faces/feature"> <feature> <feature-name>AcmeMyPane</feature-name> <feature-class> oracle/adfdemo/acme/js/component/AcmeMyPane.js </feature-class> <feature-class> oracle/adfdemo/acme/js/event/AcmePaneSelectEvent.js </feature-class> <feature-class> oracle/adfdemo/acme/js/component/AcmeMyPanePeer.js </feature-class> <!-- Dependencies --> <!-- Popup hints --> <feature-dependency>AdfRichPopup</feature-dependency> </feature>
adf-js-partitions.xml
ファイルを作成してから機能にエントリを追加することでJavaScriptパーティションを作成できます。
注意: ADF Facesには、デフォルトのadf-js-partitions.xml ファイルがあります(E.1.1項「adf-js-partitions.xmlファイル」を参照)。パーティションの構成を変更する場合は、独自の完全なadf-js-partitions.xml ファイルを作成する必要があります。実行時にフレームワークは、そのファイルのWEB-INF ディレクトリを検索します。見つからない場合は、デフォルトのパーティション・ファイルがロードされます。 |
前提作業
JavaScriptのパーティション化の動作に関する知識が役立つ場合があります。詳細は、4.9項「JavaScriptライブラリのパーティション化」を参照してください。
JavaScriptパーティションを作成する手順:
WEB-INF
ディレクトリを右クリックし、ポップアップ・メニューから「新規」を選択します。
「新規ギャラリ」で、「一般」を展開し、「XML」→「XMLドキュメント」を選択して、「OK」をクリックします。
ヒント: 「一般」ノードが表示されない場合、ギャラリの上部の「すべてのテクノロジ」タブをクリックします。 |
ファイル名にadf-js-partitions.xml
と入力し、WEB-INF
ディレクトリに保存します。
ソース・エディタで、生成されたコードを例4-23のコードに置き換えます。
次の要素を追加すると、関連する機能とともにパーティションが移入されます。
partitions:
構成ファイルのルート要素です。
partition:
partitions
要素の子として作成されます。この要素には1つのpartition-name
子要素および1つ以上のfeature
要素が含まれている必要があります。
partition-name:
partition
要素の子として作成されます。パーティションの名前を指定します。この値は、このパーティションのJavaScriptライブラリに一意のURLを作成するために使用されます。
feature:
partition
要素の子として作成されます。このパーティションに含める機能を指定します。複数のfeature
要素がある場合もあります。
ヒント: adf-js-features.xml ファイルで構成され、パーティションに表示されない機能は、独自のパーティションに存在するものとして扱われます。 |
例4-24に、AdfRichTree
機能およびAdfRichTreeTable
機能を含むtree
パーティションのpartition
要素を示します。
ADF Facesによって、アプリケーションの初期化時にライブラリのパーティション構成ファイルがロードされます。まず、ADF Facesによって、META-INF
ディレクトリのすべてのadf-js-features.xml
ファイルが検索され、見つかったすべてのファイルがロードされます(ADF Facesのデフォルトの機能構成ファイルを含む)。
パーティション構成ファイルについては、ADF FacesはWEB-INF
ディレクトリでadf-js-partitions.xml
という名前の1つのファイルを検索します。このファイルが見つからない場合は、ADF Facesのデフォルトのパーティション構成が使用されます。
レンダリング・トラバース中、ADF Facesはページによって必要とされるJavaScript機能に関する情報を収集します。トラバース終了時に(レンダリングされた)ページ・コンテンツによって必要とされるJavaScript機能の包括的なセットが認識されます。必要とされるJavaScript機能のセットが認識されると、ADF Facesはパーティション構成ファイルを使用して、この機能セットを必要とされるパーティションのセットにマップします。必要とされるパーティションのセットを使用して、これらのパーティションへのHTML <script>
参照は、HTMLドキュメントの末尾直前でレンダリングされます。