ヘッダーをスキップ
Oracle Application Development Framework開発者ガイド
10g(10.1.3.0)
B40012-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

10 より複雑なページの作成

この章では、ページにより複雑なバインディングを追加する方法について説明します。内容には、フォームおよびコマンド・コンポーネントを作成するためのパラメータを取得するメソッドの使用方法などが含まれます。

この章の内容は次のとおりです。

10.1 より複雑なページの概要

基本的なページを作成してナビゲーション機能を追加したら、ページ間でパラメータ値を渡したり、特定のレコードを検索して戻すなどの、より複雑な機能をページに追加できます。ADFには、このような複雑な機能を実際のコードをほとんど使用せずに追加できる機能が用意されています。

たとえば、サービスBeanに対してメソッドを直接実行する、ボタンなどのコマンド・コンポーネントを作成できます。これは、データ・コントロールからメソッドをドラッグし、コマンド・ボタンとしてドロップするだけで行えます。コマンド・コンポーネントを使用して、別のページにパラメータ値を渡すこともできます。

データ・ストアからの情報を表示する基本的なフォームを作成するだけでなく、(パラメータ値によって判別される)特定のレコードのみを表示するフォーム、新規レコードを作成できるフォーム、およびユーザー入力に基づいてオブジェクトを検索して戻すフォームなども作成できます。

この章では次の内容について説明します。

10.2 マネージドBeanを使用した情報の格納

ページに正しい情報を表示するために、他のページの情報が必要になることがよくあります。そのページのページ定義ファイルにパラメータ値を設定するなどして、この情報をページに直接設定すると、本質的に情報がハードコード化されます。これにかわる方法として、この情報をマネージドBeanに格納できます。Beanがアクセス可能なスコープ内に格納されているかぎり、Beanの属性のすべての値に、EL式を使用してアクセスできます。

たとえば、SREditページでは、前のページでユーザーが選択した行のsvrId属性の値が要求されます。この値は、フォームの表示に使用されるfindServiceRequestById(Integer)メソッドのパラメータ値を提供します。また、「取消」ボタンにバインドされたメソッドは、ユーザーが正しいページに戻れるように、結果を戻す必要があります(SREditページは3つの異なるページからアクセスできます)。SRDemoアプリケーションでは、この情報を保持するマネージドBeanが存在するため、情報を送る側のページで情報を設定できます。また、SREditページでこの情報を使用することで、取消アクションに対する移動先が判別されます。この情報はBeanにハッシュ・マップとして格納されます。

マネージドBeanは、faces-config.xmlファイルを使用してアプリケーションに登録するJavaクラスです。JSFアプリケーションの起動時に、この構成ファイルおよびBeanが使用可能になり、EL式で参照できるようになります。これにより、Beanのプロパティおよびメソッドへのアクセスが可能になります。マネージドBeanが初めて参照されるときに存在しない場合は常に、マネージドBean作成機能によってそのBeanのデフォルト・コンストラクタ・メソッドがコールされ、Beanがインスタンス化されます。プロパティも宣言された場合は、宣言済のデフォルト値が移入されます。

10.2.1 マネージドBeanを使用した情報の格納方法

JDeveloperのJSF構成エディタを使用すると、マネージドBeanを作成し、同時にJSFアプリケーションに登録できます。

マネージドBeanの作成手順:

  1. faces-config.xmlファイルを開きます。このファイルは、<project_name>/WEB-INFディレクトリに格納されています。

  2. ウィンドウの最下部で、「概要」タブを選択します。

  3. 左側の要素リストで、「Managed Bean」を選択します。図10-1はfaces-config.xmlファイルのJSF構成エディタを示しています。

    図10-1 JSF構成エディタ

    JSF構成エディタでのすべてのマネージドBeanの表示
  4. 「新規」ボタンをクリックして、図10-2のように「マネージドBeanの作成」ダイアログを開きます。Beanの名前および完全修飾クラス・パスを入力します。スコープを選択し、「Javaファイルの生成」チェック・ボックスを選択して、「OK」をクリックします。

    図10-2 「マネージドBeanの作成」ダイアログ

    名前、クラスおよびスコープを入力するフィールド

    ヒント:

    マネージドBeanがアプリケーションの複数のページで使用される場合は、スコープを「セッション」に設定する必要があります。ただし、この場合はバインディング・オブジェクトのデータがrequestスコープにあり、Beanにバインディング・コンテナへの参照を含めることができないため、このBeanはリクエストのみでしか有効になりません。バインディング・コンテナの参照が必要になる場合の例は、10.5項「宣言メソッドのオーバーライド」を参照してください。

  5. 必要に応じて、「管理プロパティ」バーの左にある矢印を使用して、Beanのプロパティを表示できます。「新規」をクリックしてプロパティを作成します。[F1]を押すと、構成エディタの追加のヘルプが表示されます。


    注意:

    構成エディタを使用して管理プロパティを宣言することはできますが、対応するコードはJavaクラスで生成されません。このコードを追加するため、適切なタイプのプライベート・メンバー・フィールドを作成し、コード・エディタのポップアップ・メニューの「アクセッサの生成」メニュー項目を使用してこれらのBeanプロパティに対応するgetterおよびsetterメソッドを生成する必要があります。

10.2.2 マネージドBeanの作成時に行われる処理

構成エディタを使用してマネージドBeanを作成し、Javaファイルの生成を選択すると、JDeveloperによって、指定された名前のスタブ・クラスおよびデフォルトのコンストラクタが作成されます。例10-1は、ビュー・パッケージに格納されるMyBeanクラスに追加されたコードを示しています。

例10-1 マネージドBeanに対して生成されたコード

package view;

public class MyBean {
    public MyBean() {
    }
}

また、JDeveloperによってmanaged-bean要素がfaces-config.xmlファイルに追加されます。この宣言により、指定された名前を参照するEL式を使用して、Beanのすべてのロジックに簡単にアクセスできるようになります。例10-2は、MyBeanクラスに対して作成されたmanaged-bean要素を示しています。

例10-2 faces-config.xmlファイルでのマネージドBeanの構成

<managed-bean>
  <managed-bean-name>my_bean</managed-bean-name>
  <managed-bean-class>view.MyBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

この時点で、アプリケーションのページおよびメソッドによって要求されるロジックを追加する必要があります。その後、マネージドBeanに対して指定されたmanaged-bean-nameを参照するEL式を使用して、そのロジックを参照できます。たとえば、BeanのmyInfoプロパティにアクセスする場合のEL式は、次のようになります。

#{my_bean.myInfo}

この章の次の各項では、SRDemoアプリケーションのuserStateマネージドBean(view.UserSystemState.java)を使用して情報を保持または取得する場合の例を示します。マネージドBeanを使用して情報を保持する方法の詳細な例は、これらの各項を参照してください。

10.3 メソッドを実行するためのコマンド・コンポーネントの作成

メソッドの戻りであるコレクションをドラッグ・アンド・ドロップしてUIコンポーネントを作成する場合は、そのメソッドによってコレクションが戻されるように、ページのレンダリング時にメソッドが実行されます。一方、メソッド自体(または別のタイプのメソッド)をドラッグし、コマンド・コンポーネントとしてドロップすると、メソッドを直接起動できます。


ヒント:

メソッドをパラメータ・フォームとしてドロップすることもできます。詳細は、10.7.3項「カスタム・メソッドを使用した入力フォームの作成方法」および10.8項「検索ページの作成」を参照してください。

カスタム・メソッド以外にも、データ・コントロールには、更新オブジェクトや削除オブジェクトなどの一部の標準ビジネス・ロジックを実行する組込みメソッドが含まれる場合があります。これらのメソッドはコレクションと併用できます。たとえば、SRDemoアプリケーションには、SRPublicFacade BeanのmergeEntity(Object)メソッドが含まれており、このメソッドを使用して、任意のオブジェクトを更新してデータソース内でマージできます。

データ・コントロール・パレットからこのメソッドをドラッグしてコマンド・ボタンとしてドロップすると、ボタンが自動的にメソッドにバインドされ、ボタンをクリックするたびにメソッドが実行されるようになります。図10-3は、SRDemoアプリケーションのデータ・コントロール・パレットに表示されるメソッドの一部を示しています。

図10-3 データ・コントロール・パレットに表示されたメソッド

データ・コントロール・パレットに表示されたメソッド

カスタム・メソッドまたは組込みメソッドのどちらでも、そのメソッドにボタンをバインドすることで、サービスBeanで関連するビジネス・ロジックを実行するコマンド・ボタンを作成できます。データ・コントロール・パレットを使用してボタンを作成すると、JDeveloperによってバインディングが自動的に作成されます。そのため、メソッドに必要なパラメータの値を設定するだけで済みます。

10.3.1 サービス・メソッドにバインドされたコマンド・コンポーネントの作成方法

要求されるビジネス・ロジックを実行するために、多くのメソッドで、そのメソッドの1つ以上のパラメータに対する値が要求されます。つまり、メソッドにバインドされたボタンを作成する際には、パラメータの値が検出される場所を指定する必要があります。

たとえば、mergeEntity(Object)メソッドを使用する場合は、更新するオブジェクトを指定する必要があります。

メソッドにバインドされたボタンの追加手順:

  1. データ・コントロール・パレットから、ページ上にメソッドをドラッグします。


    ヒント:

    表またはフォームに含まれるデータを使用するメソッドのボタンをドロップする場合は、その表またはフォームの中にボタンをドロップする必要があります。

  2. ポップアップ・メニューから「メソッド」「ADFコマンド・ボタン」を選択します。

  3. メソッドがパラメータを取得する場合は、「アクション・バインディング・ダイアログ」が開きます。アクション・バインディング・エディタで、「パラメータ」「値」列にある省略記号(...)ボタンをクリックし、EL式ビルダーを起動します。このビルダーを使用して、メソッドのパラメータの値を設定します。

    たとえば、コレクションの更新に使用されるmergeEntity(Object)メソッドのObjectパラメータに対して値を設定する場合は、次のようにします。

    1. EL式ビルダーでADF Bindingsノードを開き、次にbindingsノードを開きます。

      JSFページのページ定義ファイルに含まれるすべてのバインディングが表示されます。

    2. マージするオブジェクトを処理するイテレータのノードを開きます。

    3. currentRowノードを開きます。このノードは、イテレータ内の現在の行を表します。

    4. dataProviderプロパティを選択して、右向き矢印ボタンをクリックします。これによって、イテレータの現在の行に含まれるオブジェクトのデータに対して評価するEL式が作成されます。「OK」をクリックしてEL式ビルダーを閉じ、値にEL式を移入します。再び「OK」をクリックして、ボタンをメソッドにバインドします。


    ヒント:

    パラメータ値として何を選択するかを決める際には、次のような条件を考慮します。
    • 表の行に対してメソッドを機能させる場合は、イテレータの現在のオブジェクトではなく、表バインディングの現在の行になるようにパラメータを設定します。

    • マスター/ディテール関係のディテール・オブジェクトを表す複数の行を更新する場合は、マスター・リスト・オブジェクトになるようにパラメータを設定します。

    • 値がスコープまたはマネージドBeanに格納されている場合は、そのスコープまたはマネージドBean内の対応する属性を選択します。ただし、この値は、このメソッドの実行時に使用できる必要があります。詳細は、10.4項「コマンド・コンポーネントを使用したパラメータ値の設定」を参照してください。


10.3.2 メソッドを使用してコマンド・コンポーネントを作成した場合の処理

メソッドをコマンド・ボタンとしてドロップすると、JDeveloperによって次の処理が行われます。

  • メソッドのメソッド・アクション・バインディングが定義されます。メソッドがパラメータを取得する場合は、パラメータ値を保持するNamedData要素が作成されます。

  • ADF Facesコマンド・コンポーネント用のコードがJSFページに挿入されます。このコードは、その他のコマンド・ボタンのコードと同じです。詳細は、6.4.2.3項「EL式を使用したナビゲーション操作へのバインド」を参照してください。ただし、ボタンは、組込み操作用のアクション・バインディングのexecuteメソッドではなく、ドロップしたメソッド用のメソッド・アクション・バインディングのexecuteメソッドにバインドされます。

10.3.2.1 メソッドでのパラメータの使用方法

メソッドの戻りであるコレクションをドロップするときのように、パラメータを取得するメソッドをJSFページにドロップすると、JDeveloperによってメソッド・アクション・バインディングが作成されます(詳細は、6.2.2.1項「イテレータ・バインディングの作成および使用」を参照してください)。ただし、メソッドが実行するパラメータを要求する場合は、JDeveloperによって、各パラメータのNamedData要素も作成されます。これらの要素は、メソッドのパラメータを表します。

たとえば、mergeEntity(Object)メソッド・アクション・バインディングには、ObjectパラメータのNamedData要素が含まれます。この要素は、アクション・バインディングの作成時に指定した値にバインドされます。例10-3は、mergeEntity(Object)メソッドのドロップ時に作成され、Objectパラメータ(名前はentity)をfindServiceRequestByIdIterイテレータの現在の行のデータにバインドしたメソッド・アクション・バインディングを示しています。

例10-3 パラメータ・メソッドのメソッド・アクション・バインディング

<methodAction id="mergeEntity" InstanceName="SRPublicFacade.dataProvider"
                  DataControl="SRPublicFacade" MethodName="mergeEntity"
                  RequiresUpdateModel="true" Action="999"
                  ReturnName="SRPublicFacade.methodResults.SRPublicFacade
                        _dataProvider_mergeEntity_result">
  <NamedData NDName="entity"
             NDValue="${bindings.findServiceRequestByIdIter.
                        currentRow.dataProvider}"
             NDType="java.lang.Object"/>
</methodAction>

10.3.2.2 EL式を使用したメソッドへのバインド

ナビゲーション操作を使用してコマンド・ボタンを作成するときと同様に、メソッドを使用してコマンド・ボタンを作成すると、actionListener属性を使用して、ボタンがメソッドに自動的にバインドされます。ボタンは、指定されたメソッドのアクション・バインディングのexecuteプロパティにバインドされます。このバインディングにより、ビジネス・サービスに対してバインディングのメソッドが起動します。コマンド・ボタンのactionListener属性の詳細は、6.4.3項「実行時に行われる処理: アクション・イベントおよびアクション・リスナー」を参照してください。


ヒント:

アクション・バインディングのexecuteメソッドにボタンをバインドするかわりに、executeメソッドをオーバーライドするバッキングBean内のメソッドにボタンをバインドできます。そうすることで、元のメソッドの実行前か実行後に、ロジックを追加できるようになります。詳細は、10.5項「宣言メソッドのオーバーライド」を参照してください。

ナビゲーション操作のように、ボタンのdisabledプロパティは、EL式を使用してボタンを表示するかどうかを決定します。例10-4は、コマンド・ボタンをmergeEntity(Object)メソッドにバインドするためのEL式を示しています。

例10-4 コマンド・ボタンをメソッドにバインドするためのJSFコード

<af:commandButton actionListener="#{bindings.mergeEntity.execute}"
                  text="mergeEntity"
                  disabled="#{!bindings.mergeEntity.enabled}"/>

ヒント:

UIコンポーネントをページ上にドロップすると、前にドロップしたコンポーネントの数に基づいて、自動的にIDが指定されます。たとえば、commandButton1commandButton2のようになります。このIDは変更可能です。特にページの複数のUIコンポーネントのメソッドを含むバッキングBean内でIDを参照する場合には、より説明的なIDに変更してください。実際にIDを変更する場合は、ページのEL式でそのIDに対するすべての参照を手動で更新する必要があります。

10.3.3 実行時に行われる処理

ユーザーがボタンをクリックすると、メソッド・バインディングによって、関連付けられているメソッドが起動し、NamedData要素にバインドされている値がパラメータとして渡されます。たとえば、mergeEntity(Object)メソッドにバインドされたボタンをユーザーがクリックすると、現在のレコードの値を使用してデータソースが適切に更新されます。

10.4 コマンド・コンポーネントを使用したパラメータ値の設定

1つのページでのアクションに対して、別のページにデータを表示するメソッドなどにパラメータを設定しなければならない場合があります。図10-4のように、SRDemoアプリケーションのSRListページでは、ユーザーがクリックすると直接サービス・リクエストを編集できる、コマンド・リンクが使用されています。

図10-4 表でのコマンド・リンクの使用

表内のコマンド・リンクによる行の設定およびSREditへの移動

commandLinkコンポーネントは、SREditページへの移動、およびSREditページにデータを表示するフォームを作成するためのfindServiceRequestById(Integer)メソッドに必要なパラメータの設定の両方に使用されます。ADF FacesのsetActionListenerコンポーネントを使用して、パラメータを設定できます。


ヒント:

SRDemoアプリケーションのこのページではsetActionListenerコンポーネントは使用されていません。SREditページに対してこのパラメータを設定するために、複数のページで同じロジックが要求されるため、かわりに、マネージドBeanのメソッドによって、これと同じ機能が提供されます。1つのページで必要とされるロジックが他のページでも必要とされる場合は、そのロジックをマネージドBeanに配置する方が効果的な場合があります。マネージドBeanの使用方法の詳細は、10.2項「マネージドBeanを使用した情報の格納」を参照してください。

10.4.1 コマンド・コンポーネントを使用したパラメータの設定方法

setActionListenerコンポーネントを使用して、他のオブジェクトに値を設定できます。このコンポーネントは、コマンド・コンポーネントの子である必要があります。

setActionListenerコンポーネントの使用手順:

  1. データ・コントロール・パレットまたはコンポーネント・パレットを使用して、コマンド・コンポーネントを作成します。

  2. コンポーネント・パレットからsetActionListenerコンポーネントをドラッグして、コマンド・コンポーネントの子としてドロップします。

  3. 「ActionListenerの挿入」ダイアログで、「自」にパラメータ値を設定します。

  4. 「至」にパラメータ値の設定場所を設定します。


    ヒント:

    作成されるページのページ定義ファイルに直接パラメータ値を設定するかわりに、マネージドBeanまたはスコープにパラメータ値を格納することを考慮してください。次のページに直接設定すると、それ以降、ナビゲーションを簡単に変更できなくなります。詳細は、10.2項「マネージドBeanを使用した情報の格納」を参照してください。また、バインディング・コンテナ内のデータは、そのコンテナが準備されたリクエストでのみ有効です。そのため、データを設定してから次のページがレンダリングされるまでの間に、データが変更される場合があります。

  5. パラメータ値が別のページのパラメータ付きフォームを作成するためのメソッドで必要とされる場合、フォームを作成するときに、パラメータに手順4「至」属性の値を設定します。詳細は、10.6項「パラメータを取得するメソッドを使用したフォームまたは表の作成」を参照してください。

10.4.2 パラメータの設定時に行われる処理

setActionListenerコンポーネントを使用すると、移動する前にコマンド・コンポーネントによって値が設定されます。From属性を渡す値のソースに設定すると、コンポーネントからその値へのアクセスが可能になります。To属性をターゲットに設定すると、コマンド・コンポーネントによってターゲットに値が設定されるようになります。例10-5は、JSFページのコマンド・リンクのコードを示しています。このコマンド・リンクは、現在の行のデータにfrom値としてアクセスし、To属性を使用してデータをマネージドBeanの属性の値として設定します。

例10-5 setActionListenerコンポーネントを使用したコマンド・リンクのJSFページ・コード

<af:commandLink actionListener="#{bindings.setCurrentRowWithKey.execute}"
                action="edit"
                text="#{row.svrId}"
                disabled="#{!bindings.setCurrentRowWithKey.enabled}"
                id="commandLink1">
  <af:setActionListener from="#{row.svrId}"
                           to="#{userState.currentSvrId}"/>
</af:commandLink>

10.4.3 実行時に行われる処理

ユーザーがコマンド・コンポーネントをクリックすると、移動する前に、setActionListenerコンポーネントによってパラメータ値が設定されます。例10-5では、setActionListenerによって現在の行のsvrId属性が取得され、その値がuserStateマネージドBeanのcurrentSvrId属性の値として設定されます。これにより、このページの現在の行のsvrIdを必要とするすべてのメソッドは、EL式#{userState.currentSvrId}を使用してこれにアクセスできます。

たとえば、findServiceRequestById(Integer)メソッドをドロップしてSREditページのフォームを作成する場合は、Integerパラメータの値として#{userState.currentSvrId}を入力します。詳細は、10.6項「パラメータを取得するメソッドを使用したフォームまたは表の作成」を参照してください。

10.5 宣言メソッドのオーバーライド

メソッドをコマンド・ボタンとしてドロップすると、関連付けられているバインディング・オブジェクトのexecuteメソッドに、そのボタンが自動的にバインドされます。このバインディングにより、関連するバインディング・コードを記述せずに、JSFページを宣言的に作成できるようになります。ただし、メソッドの実行前または実行後に、ロジックの追加が必要になる場合もあります。たとえば、表の複数の行を選択して削除するには、各行にアクセスして現在の行にするコードを、削除メソッドの実行前に追加する必要があります。詳細は、7.6.4項「selectionファセットにおけるtableSelectManyコンポーネントの使用方法」を参照してください。

JDeveloperでは、関連付けられているアクション・バインディングへのアクセスを提供するマネージドBeanの新規メソッドおよびプロパティを作成して、宣言メソッドにロジックを追加できます。デフォルトでは、この生成されたコードによって、対応するバインディングのメソッドが実行されます。その後、このコードの前か後にロジックを追加できます。バインディングのexecuteプロパティではなく、この新規メソッドに、JDeveloperによってコマンド・コンポーネントが自動的にバインドされます。その後、ユーザーがボタンをクリックすると、新規メソッドが実行されます。

次に、BeanSRDemoアプリケーションの一部の例を示します。それぞれの例では、まずバインディング・コンテナを挿入し、宣言メソッドの実行前または実行後にロジックを追加するメソッドが、バッキングBeanに含まれています。

10.5.1 宣言メソッドのオーバーライド方法

宣言メソッドをオーバーライドするには、マネージドBeanにコマンド・コンポーネントがバインドされる新規メソッドを保持させる必要があります。ページにバッキングBeanが関連付けられている場合は、JDeveloperによって、バインディング・オブジェクトへのアクセスに必要なコードがバッキングBeanに追加されます。ページにバッキングBeanが関連付けられていない場合は、作成を促す指示が表示されます。


注意:

現在、コマンド・コンポーネントのAction属性の値としてEL式が設定されている場合は、JDeveloperによってEL式が上書きされないため、次の手順を使用できません。次の手順を行う前に、この値を削除する必要があります。

宣言メソッドのオーバーライドの手順:

  1. オーバーライドするメソッドをJSFページ上にドラッグし、UIコマンド・コンポーネントとしてドロップします。

    これにより、コンポーネントが作成され、コンポーネントのActionListener属性を使用して、ADFモデル・レイヤーの関連するバインディング・オブジェクトにバインドされます。

    データ・コントロール・パレットのメソッドを使用したコマンド・コンポーネントの作成方法の詳細は、10.3項「メソッドを実行するためのコマンド・コンポーネントの作成」を参照してください。

  2. JSFページでコンポーネントをダブルクリックします。

    「バインドActionプロパティ」ダイアログで、バッキングBeanおよびコンポーネントをバインドするメソッドを指定します。指定方法は次のいずれかです。

    • 自動バインディングがそのページで有効化されている場合は、図10-5のように、バッキングBeanはすでに自動選択されています。

      図10-5 自動バインディングが有効化されているページの「バインドActionプロパティ」ダイアログ

      自動バインディングを使用するページの「バインドActionプロパティ」ダイアログ
      • 新規メソッドを作成するには、「メソッド」フィールドにメソッドの名前を入力します。このフィールドには、最初にデフォルト名が表示されています。

        または

      • 既存のメソッドを使用するには、「メソッド」フィールドのドロップダウン・リストからメソッドを選択します。

      • 「ADFバインディング・コードの生成」を選択します。

    • そのページで自動バインディングが使用されていない場合は、図10-6のように、既存のバッキングBeanから選択するか、新たに作成できます。自動バインディングの詳細は、4.5.4項「自動コンポーネント・バインディング機能の使用方法」を参照してください。

      図10-6 自動バインディングが無効化されているページの「バインドActionプロパティ」ダイアログ

      自動バインディングを使用しないページの「バインドActionプロパティ」ダイアログ
      • 「新規」をクリックして、新しいバッキングBeanを作成します。「マネージドBeanの作成」ダイアログが表示されます。このダイアログを使用して、Beanおよびクラスに名前を付け、Beanのスコープを設定します。

        または

      • 既存のバッキングBeanおよびメソッドをドロップダウン・リストから選択します。


    注意:

    新規のマネージドBeanを作成する場合は、Beanのスコープをrequestに設定する必要があります。スコープをrequestに設定する理由は、生成されたコードによって参照されるバインディング・コンテナ・オブジェクト内のデータがrequestスコープにあり、リクエスト以外では有効にならないためです。

    また、JDeveloperでは、コマンド・コンポーネントにActionListener属性の値がある場合、常にボタンのバインド先がバインディングのexecuteプロパティであると認識されます。そのため、このバインディングを削除した場合は、ADFバインディング・コードを生成することを選択できなくなります。その場合は、コマンド・コンポーネントをダブルクリックする前に、コードを手動で挿入するか、ActionListenerのダミーの値を設定する必要があります。


  3. バッキングBeanおよびメソッドを識別したら、「バインドActionプロパティ」ダイアログで「OK」をクリックします。

    ソース・エディタでマネージドBeanが自動的に開きます。例10-6は、Beanに挿入されたコードを示しています。この例では、コマンド・ボタンがmergeEntityメソッドにバインドされます。

    例10-6 バインディング・オブジェクトへのアクセス用にバッキングBeanで生成されたコード

      public BindingContainer getBindings() {
    
          return this.bindings;
      }
    
      public void setBindings(BindingContainer bindings) {
          this.bindings = bindings;
      }
    
      public String commandButton_action1() {
          BindingContainer bindings = getBindings();
          OperationBinding operationBinding =
              bindings.getOperationBinding("mergeEntity");
          Object result = operationBinding.execute();
          if (!operationBinding.getErrors().isEmpty()) {
              return null;
          }
          return null;
      }
    
  4. バインディング・オブジェクトにアクセスする前または後に、ロジックを追加できます。


    ヒント:

    EL式の結果を取得するには、例10-7のように、ValueBindingクラスを使用する必要があります。

    例10-7 マネージドBeanのEL式の結果へのアクセス

    FacesContext fc = FacesContext.getCurrentInstance();
      ValueBinding expr =
        fc.getApplication().
          createValueBinding("#{bindings.SomeAttrBinding.inputValue}");
    DCIteratorBinding ib = (DCIteratorBinding)
      expr.getValue(fc);
    

    処理ロジックに加えて条件付きロジックを記述して、特定の条件に基づいて複数の結果の中から1つを戻すことができます。たとえば、処理中にエラーが発生した場合にはnullを、処理が正常終了した場合は別の結果値を戻すことができます。nullの戻り値により、ナビゲーション・ハンドラはナビゲーション・ケースを評価せずに、そのまま現在ページを再表示します。


    ヒント:

    特定のナビゲーション・ケースをトリガーするには、メソッドによって戻される結果値が、ナビゲーション・ルールの結果値と大/小文字の区別も含めて完全に一致する必要があります。

    この時点で、コマンド・ボタンは、ActionListener属性ではなく、Action属性を使用して新しいメソッドにバインドされています。Action属性の値(結果文字列など)がすでに存在していた場合は、その値が新規メソッドの戻りとして追加されます。値が存在していなかった場合は、戻りがnullのままになります。

10.5.2 宣言メソッドをオーバーライドした場合の処理

宣言メソッドをオーバーライドすると、#{bindings}(バインディング・コンテナへの参照)の管理プロパティ値を使用してバッキングBeanに管理プロパティが追加され、強く型付けされたBeanプロパティがBindingContainer型のクラスに追加されます。このプロパティは、JSFランタイムによって管理プロパティ式#{bindings}の値を使用して設定されます。また、JDeveloperによって、UIコマンド・アクション・メソッドにもロジックが追加されます。このロジックには、現在のバインディング・コンテナにアクセスするための、強く型付けされたgetBindings()メソッドが含まれます。

例10-8は、選択したマネージドBeanに自動的に追加されたコードを示しています。戻りのString "back"は、メソッドに自動的に追加されたものです。

例10-8 バインディング・オブジェクトへのアクセス用にバッキングBeanで生成されたコード

private BindingContainer bindings;
...
public String commandButton1_action() {
    BindingContainer bindings = getBindings();
    OperationBinding operationBinding =
            bindings.getOperationBinding("mergeEntity");
    Object result = operationBinding.execute();
    if (!operationBinding.getErrors().isEmpty()) {
        return null;
    }

    return "back";
}

ActionListener属性ではなく、Action属性を使用して新しいメソッドにUIコマンド・コンポーネントがリバインドされます。たとえば、例10-9は、mergeEntityメソッドをドロップして作成されたコマンド・ボタンに対する、JSFページのコードを示しています。actionListener属性はmergeEntityメソッドにバインドされており、action属性にはbackString結果が含まれます。ユーザーがボタンをクリックすると、メソッドが単純に実行され、このナビゲーション・ケースのtoViewIdとして定義されているページに移動します。

例10-9 宣言メソッドにバインドされたコマンド・ボタンのJSFページ・コード

<af:commandButton actionListener="#{bindings.mergeEntity.execute}"
                  text="persistEntity"
                  disabled="#{!bindings.persistEntity.enabled}"
                  id="commandButton1"
                  action="back"/>

例10-10は、ページのバッキングBeanのメソッドをオーバーライドした後のコードを示しています。ここでは、action属性は、バッキングBeanのメソッドにバインドされています。

例10-10 オーバーライド後のメソッドにバインドされたコマンド・ボタンのJSFページ・コード

<af:commandButton text="persistEntity"
                  disabled="#{!bindings.mergeEntity.enabled}"
                  binding="#{backing_create.commandButton1}"
                  id="commandButton1"
                  action="#{backing_create.commandButton1_action}"/>

このコードによって行われる処理は次のとおりです。

  • バインディング・コンテナにアクセスします。

  • 関連付けられているメソッドのバインディングを検索し、実行します。

  • ナビゲーションに使用できるメソッドの戻りを追加します。デフォルトでは戻りはnullですが、ボタンのAction属性にすでに結果文字列が存在する場合は、その属性が戻り値として使用されます。このコードは、必要に応じて変更できます。戻された結果の使用方法の詳細は、9.4項「動的ナビゲーションの使用」を参照してください。


ヒント:

オーバーライド済メソッドを使用するボタンをクリックすると、次のエラーが表示されます。

SEVERE: マネージドBean main_beanを作成できませんでした。参照先オブジェクト: '#{bindings}'のスコープが参照元オブジェクトより短くなっています。

これは、オーバーライドするメソッドを含むマネージドBeanのスコープが、requestより大きい(つまり、sessionまたはapplicationである)ためです。メソッドで参照されるバインディング・コンテナ内のデータのスコープがrequestであるため、このマネージドBeanのスコープはrequestか、より小さいスコープに設定する必要があります。


10.6 パラメータを取得するメソッドを使用したフォームまたは表の作成

フォームまたは表に内容を表示するために、情報の取得が必要になる場合があります。このようなページについては、パラメータを取得するメソッドから戻されたコレクションを使用して、フォームまたは表を作成します。パラメータ値は、別のページまたはメソッドにより設定されます。

たとえば、SREditページのフォームは、findServiceRequestsById(Integer)メソッドから戻されたコレクションを使用して作成されています。戻されるのは、すべてのサービス・リクエストではなく、ユーザーが前のページで選択したサービス・リクエストのみです。前のページのコマンド・リンクは、パラメータ(Integer)を設定します。このパラメータは、サービス・リクエストのIDを提供します。コマンド・コンポーネントを使用したパラメータ値の設定の詳細は、10.4項「コマンド・コンポーネントを使用したパラメータ値の設定」を参照してください。

10.6.1 パラメータを取得するメソッドを使用したフォームまたは表の作成方法

パラメータを要求するフォームまたは表を作成するには、戻すレコードを判別するために、パラメータの値へのアクセスが必要になります。たとえば、フォームまたは表を作成する前に、一部のオブジェクトのパラメータ値を設定する別のページのコマンド・ボタンにロジックを追加して、そのオブジェクトにメソッドがアクセスできるようにすることが必要になる場合があります。詳細は、10.4項「コマンド・コンポーネントを使用したパラメータ値の設定」を参照してください。この処理が終了したら、フォームまたは表のパラメータ値を設定できます。

パラメータを使用するフォームまたは表の作成手順:

  1. 1つまたは複数のパラメータを取得するメソッドの戻りであるコレクションをデータ・コントロール・パレットからドラッグし、いずれかのタイプのフォームまたは表としてドロップします。

  2. 「フォーム・フィールドの編集」ダイアログまたは「表の列の編集」ダイアログで、必要に応じてフォームまたは表を構成し、「OK」をクリックします。

    これらのダイアログの使用方法を表示するには、「ヘルプ」をクリックします。

    メソッドによってパラメータが取得されるため、アクション・バインディング・エディタが開き、パラメータ値を設定するよう求められます。

  3. アクション・バインディング・エディタの「値」フィールドの省略記号(...)ボタンをクリックしてEL式ビルダーを開き、各パラメータの値を入力します。パラメータの値を表すノードを選択します。

    たとえば、例10-5「setActionListenerコンポーネントを使用したコマンド・リンクのJSFページ・コード」では、setActionListenerComponentによって、userStateBeanのsvrIdパラメータ値がcurrentSvrId属性として設定されています。この値にアクセスするには、パラメータの値として#{userState.currentSvrId}を使用します。

    アクション・バインディング・エディタは、この値を使用して、メソッドの実行時にパラメータを表すNamedData要素を作成します。コマンド・ボタンにバインドされたメソッドとは異なり、メソッドの戻りであるコレクションをドロップしているため、関連付けられているイテレータがページのロードとともに実行されると、このメソッドが実行されます。パラメータ値の設定は、ページがレンダリングされる前に行います。つまり、NamedData要素は、送る側のページによって値が設定された場所から値を取得する必要があります。

10.6.2 パラメータを取得するメソッドを使用したフォームの作成時の処理

パラメータを取得するメソッドの戻りを使用してフォームを作成すると、JDeveloperによって次の処理が行われます。

  • メソッドのアクション・バインディング、メソッドの結果のメソッド・イテレータ・バインディング、およびオブジェクトの各属性の属性バインディングが作成されるか、表の場合は表バインディングが作成されます。メソッドによって要求される各パラメータのNamedData要素も作成されます。

  • ADF Facesコマンド・コンポーネントを使用して、JSFページにフォームのコードが挿入されます。

例10-11は、findServiceRequestsById(Integer)メソッドをドロップしたときに作成されるアクション・メソッド・バインディングを示しています。この例では、findSvrIdの値がUserStateマネージドBeanのcurrentSvrId属性に設定されています。

例10-11 メソッド戻りのメソッド・アクション・バインディング

<bindings>
  <methodAction id="findServiceHistoryById"
                InstanceName="SRPublicFacade.dataProvider"
                DataControl="SRPublicFacade"
                MethodName="findServiceHistoryById" RequiresUpdateModel="true"
                Action="999"
                ReturnName="SRPublicFacade.methodResults.SRPublicFacade_
                            dataProvider_findServiceHistoryById_result">
    <NamedData NDName="svrIdParam" NDValue="${userState.currentSvrId}"
               NDType="java.lang.Integer"/>
  </methodAction>
...
</bindings>

NamedData要素は、要求側のページで設定されたように、userState Beanの現在のサービス・リクエストIDに対して評価します。

10.6.3 実行時に行われる処理

ユーザーがコマンド・ボタンをクリックしたときに実行されるメソッドとは異なり、フォームの作成に使用されるメソッドは、ページがロードされるときに実行されます。ページに対してデータを戻すためにメソッドが実行されると、メソッドはNamedData要素のEL式を評価し、その値をパラメータとして使用します。その後、メソッドは正しいデータを戻すことができます。メソッドが複数のパラメータを取得する場合は、パラメータごとに評価が行われ、メソッドのパラメータが設定されます。

たとえば、SREditページのロード時には、userStateマネージドBeanのcurrentSvrIdフィールドの値が使用され、findServiceRequestsById(Integer)メソッドによって要求されるパラメータの値として設定されます。メソッドが実行されると、パラメータの値と一致するレコードのみが戻されます。フォームを作成するためにメソッドの戻りをドロップしたため、戻りは表示されるサービス・リクエストになります。

10.7 新規レコード用入力フォームの作成

ユーザーが新規レコードの情報を入力し、そのレコードをデータソースにコミットするためのフォームを作成できます。データ・コントロールのセッションBeanが作成されると、デフォルトで、データ・コントロールのオブジェクトに対するコンストラクタ・メソッドが作成されます。たとえば、SRDemoアプリケーションのSRPublicFacadeセッションBeanには、製品、専門分野、サービス履歴、ユーザーおよびサービス・リクエストのコンストラクタ・メソッドがあります。コンストラクタは、メソッドに渡せるオブジェクトを宣言的に作成する方法を提供します。たとえば、セッションBeanにデフォルトで含まれているpersistEntity(Object) CRUDメソッドを使用すると、新規レコードをデータベースに保存できます(デフォルトのセッションBeanメソッドに関する詳細は、3.2.1.2項「セッション・ファサード・メソッドの生成」を参照してください)。コンストラクタ・メソッドを使用して入力フォームを作成する場合は、オブジェクトを作成し、オブジェクトの変数を入力された値に初期化するために、メソッドがコールされます。その後、データソースで新規レコードを作成するpersistEntityメソッドに、コンストラクタの結果を簡単に渡すことができます。

ただし、場合によっては、新規オブジェクトの作成方法をより詳細に制御する必要があります。たとえば、特定の属性に値をプログラム的に移入するとします。この場合、オブジェクトの作成を処理するカスタム・メソッドを作成できます。

カスタム・メソッドを使用して入力フォームを作成するには、メソッドから戻されたコレクションをドロップするかわりに、メソッド自体をパラメータ・フォームとしてドロップします。メソッドにバインドされたコマンド・ボタンがJDeveloperによって自動的に追加され、ユーザーがこのボタンをクリックすると、作成したカスタムメソッドが実行されます。

たとえば、SRDemoアプリケーションのSRPublicFacadeデータ・コントロールには、createServiceRequest(String, Integer, Integer)メソッドが含まれています。Stringは問題の説明の値、Integerは製品ID、2つ目のIntegerはリクエストを作成したユーザーのIDをそれぞれ表します。このメソッドにより、オブジェクトの属性に移入するパラメータの値を使用して、ServiceRequestオブジェクトの新規インスタンスが作成されます。製品IDおよびユーザーのIDは、ユーザーではなくメソッドによって設定されます。

10.7.1 コンストラクタを使用した入力フォームの作成方法

データ・コントロールのコンストラクタは、そのデータ・コントロールの「コンストラクタ」フォルダにあります。コンストラクタは、オブジェクトの作成に使用されるデータ・コントロールのデフォルト・メソッドにアクセスします(詳細は、3.2.1.2項「セッション・ファサード・メソッドの生成」を参照してください)。図10-7は、SRPublicFacadeデータ・コントロールのコンストラクタを示しています。

図10-7 データ・コントロール・パレットに表示されたコンストラクタ

Product、ExpertiseAreaおよびServiceHistoryの各コンストラクタ

コンストラクタを使用した入力フォームの作成手順:

  1. データ・コントロール・パレットから、JSFページ上に適切なコンストラクタをドラッグします。コンストラクタはフォームとしてのみドロップできるため、ポップアップ・メニューは表示されません。

  2. 「フォーム・フィールドの編集」ダイアログで、ラベル、バインディングおよびUIコンポーネントを設定します。「送信ボタンを含める」は選択しないでください。

  3. データ・コントロール・パレットから、persistEntity(Object)メソッドをドラッグします。このメソッドは、コンストラクタによって作成されたオブジェクトをデータベースに保存します。

  4. ポップアップ・メニューから「メソッド」「ADFコマンド・ボタン」を選択します。

  5. アクション・バインディング・エディタの「値」フィールドにある省略記号(...)ボタンをクリックしてEL式ビルダーを起動し、entityパラメータの値を入力します。ここではentityパラメータをコンストラクタの結果にするために、図10-8のように、コンストラクタのアクション・バインディングの下にある「結果」を選択します。

    図10-8 Productコンストラクタからの結果

    Productアクションの下の結果属性

ヒント:

別のページからこのページへ移動する場合に、元のページに戻ったときに新しく作成されたオブジェクトが表示されるようにするには、元のページのイテレータのcacheResults属性をfalseに設定する必要があります。

たとえば、すべての製品を表示するページがあり、ユーザーがそのページから別のページに移動して製品を作成できるとします。移動先のページのボタンをクリックすると、製品が作成されて、製品リストのページに戻ります。作成したばかりの製品がユーザーに対して表示されるようにするには、製品リストのイテレータ・バインディングをcacheResults=falseに設定する必要があります。この設定により、元のページに戻ったときにイテレータが強制的に再実行され、新しく作成した製品が表示されます。


10.7.2 コンストラクタ使用時に行われる処理

コンストラクタを使用して入力フォームを作成すると、JDeveloperによって次の処理が行われます。

  • コンストラクタ・メソッドのアクション・バインディング、コンストラクタ・メソッドの結果のメソッド・イテレータ・バインディング、およびオブジェクトの各属性の属性バインディングが作成されます。また、実行可能バインディングに起動アクションが作成され、このアクションによって、このコンストラクタ・メソッドがモデルのレンダリング・フェーズで実行されます。

  • ADF Faces inputTextコンポーネントを使用して、JSFページにフォームのコードが挿入されます。

たとえば、SRDemoで製品の単純な入力フォームを作成するには、図10-9のように、データ・コントロール・パレットから製品コンストラクタ・メソッドをパラメータ・フォームとしてドロップし、そのフォームの下に、persistEntityメソッドをボタンとしてドロップできます。


注意:

この例で示したページは、実際のSRDemoアプリケーションには含まれていません。

図10-9 単純な製品作成フォーム

ID、名前、イメージおよび説明を入力できる製品作成フォーム

例10-12は、この入力フォームのページ定義ファイルを示しています。起動アクション・バインディングが実行されると、アクション・バインディングを使用してコンストラクタ・メソッドがコールされます。その後、コンストラクタ・メソッドの結果が、イテレータにバインドされます。persistEntity(Object)メソッドをコマンド・ボタンとしてドロップすると、メソッドがイテレータを介してコンストラクタの結果にアクセスできるようになります。

例10-12 コンストラクタのページ定義コード

<executables>
   <invokeAction Binds="Product" id="invokeProduct" Refresh="renderModel"
                 RefreshCondition="${!adfFacesContext.postback and empty
                                               bindings.exceptionsList}"/>
   <methodIterator DataControl="SRPublicFacade"
                   BeanClass="oracle.srdemo.model.entities.Product"
                   Binds="Product.result" id="ProductIter"
                   Refresh="renderModel"
                   RefreshCondition="${!adfFacesContext.postback and empty
                                               bindings.exceptionsList}"/>
</executables>
<bindings>
  <methodAction DataControl="SRPublicFacade" id="Product" MethodName="Product"
                RequiresUpdateModel="true" Action="999"
                ReturnName="SRPublicFacade.methodResults.SRPublicFacade_
                                                         Product_result"
                ClassName="oracle.srdemo.model.entities.Product"/>
  <attributeValues id="description" IterBinding="ProductIter">
    <AttrNames>
      <Item Value="description"/>
    </AttrNames>
  </attributeValues>
  <attributeValues id="image" IterBinding="ProductIter">
    <AttrNames>
      <Item Value="image"/>
    </AttrNames>
  </attributeValues>
  <attributeValues id="name" IterBinding="ProductIter">
    <AttrNames>
      <Item Value="name"/>
    </AttrNames>
  </attributeValues>
  <attributeValues id="prodId" IterBinding="ProductIter">
    <AttrNames>
      <Item Value="prodId"/>
    </AttrNames>
  </attributeValues>
  <methodAction id="persistEntity" InstanceName="SRPublicFacade.dataProvider"
                DataControl="SRPublicFacade" MethodName="persistEntity"
                RequiresUpdateModel="true" Action="999"
                ReturnName="SRPublicFacade.methodResults.SRPublicFacade_
                                       dataProvider_persistEntity_result">
    <NamedData NDName="entity" NDValue="${bindings.Product.result}"
               NDType="java.lang.Object"/>
  </methodAction>
</bindings>

コンストラクタ・メソッドが起動されると、必ずオブジェクトが作成されます。ただし、データがキャッシュされ、それによってメソッドによるサーバーへのポストバックが可能になるため、ユーザーが別のオブジェクトを作成するなどの目的でページに再びアクセスすると、コンストラクタ・メソッドによって同じオブジェクトが再び作成されます。また、エラーが発生すると、エラー・メッセージを使用してページが再レンダリングされるため、オブジェクトが再び作成されます。

複製を回避するために、起動アクションのrefreshConditionプロパティは、サーバーへのポストバックが存在せず、エラー・メッセージがないかぎり、コンストラクタが1回しか起動されないように設定されています。EL式は例10-12を参照してください。

イテレータのリフレッシュ条件は同じです。この設定により、ユーザーがページに再アクセスしたときに、ポストバックで使用されたキャッシュ・データがイテレータによって表示されなくなり、かわりに、データが含まれていないフォームが表示されます。

10.7.3 カスタム・メソッドを使用した入力フォームの作成方法

カスタム・メソッドを使用して入力フォームを作成する場合は、ユーザーによって移入されるデータを使用できるメソッドをドラッグし、パラメータ・フォームとしてドロップします。この場合は、オブジェクトを作成する必要があるため、戻りをドロップすることはできません。メソッド自体をドロップします。

カスタム・メソッドを使用した入力フォームの作成手順:

  1. データ・コントロール・パレットから、JSFページ上に適切なメソッドをドラッグします。

  2. ポップアップ・メニューから、「パラメータ」「ADFパラメータ・フォーム」を選択します。

    「フォーム・フィールドの編集」ダイアログが開きます。このダイアログでラベル、バインディングおよびUIコンポーネントをカスタマイズしてから、フォームを作成できます。JDeveloperによって、メソッドにバインドされたコマンド・ボタンが自動的に追加されます。

10.7.4 メソッドを使用してパラメータ・フォームを作成した場合の処理

メソッドをパラメータ・フォームとしてドロップすると、JDeveloperによって次の処理が行われます。

  • データ値を保持する変数、メソッドのメソッド・バインディング、および関連付けられている属性の属性バインディングが、ページ定義ファイルで定義されます。

  • ADF Faces inputTextコンポーネントおよびADF Facesコマンド・ボタン・コンポーネントを使用して、JSFページにフォームのコードが挿入されます。このコードは、その他の入力フォームまたはコマンド・ボタンのコードと同じです。

10.7.4.1 変数およびパラメータの使用方法

パラメータを取得するメソッドの戻りであるコレクションをドロップした場合と同様に、JSFページ上にメソッド自体をドロップすると、JDeveloperによって各パラメータのNamedData要素が作成されます。ただし、10.6項「パラメータを取得するメソッドを使用したフォームまたは表の作成」のように別のページで値が提供されるのとは異なり、ユーザーがパラメータ値を指定するため、各NamedData要素は、対応する属性の属性バインディングにバインドされます。

このバインディングにより、メソッドは、実行のパラメータに対する正しい属性の値にアクセスできます。

たとえば、createServiceRequestメソッド・アクション・バインディングには、使用する各パラメータのNamedData要素が含まれます。そして、NamedData要素は、EL式を使用して、対応する属性バインディングにバインドされます。例10-13は、メソッド・アクション・バインディングおよび createServiceRequestメソッドのドロップ時に作成される属性バインディングの一部を示しています。

例10-13 ページ定義ファイルでのメソッド・アクション・バインディング

<bindings>
  <methodAction id="createServiceRequest" MethodName="createServiceRequest"
                RequiresUpdateModel="true" Action="999"
                DataControl="SRPublicFacade"
                InstanceName="SRPublicFacade.dataProvider"
                ReturnName="SRPublicFacade.methodResults.SRPublicFacade_
                         dataProvider_createServiceRequest_result">
    <NamedData NDName="problemDescription" NDType="java.lang.String"
               NDValue="${bindings.createServiceRequest_problemDescription}"/>
    <NamedData NDName="productId" NDType="java.lang.Integer"
               NDValue="${bindings.createServiceRequest_productId}"/>
    <NamedData NDName="createdBy" NDType="java.lang.Integer"
               NDValue="${bindings.createServiceRequest_createdBy}"/>
  </methodAction>
  <attributeValues id="problemDescription" IterBinding="variables">
    <AttrNames>
      <Item Value="createServiceRequest_problemDescription"/>
    </AttrNames>
    </attributeValues>
    <attributeValues id="productId" IterBinding="variables">
      <AttrNames>
        <Item Value="createServiceRequest_productId"/>
    </AttrNames>
      ...
  </attributeValues>
</bindings>

コレクションの属性と同じように、メソッドの属性もイテレータを参照します。ただし、関連付けられているメソッドが戻すコレクションにアクセスして反復処理を行うメソッド・イテレータを参照するのではなく、作成タイプのメソッドの属性は、変数にアクセスして反復処理を行います。このタイプのメソッドではまだオブジェクトが戻されていないため、ページに入力された値を保持するものはありません。変数はデータ・ホルダーとして機能します。

JDeveloperによって、メソッドが取得する各パラメータの変数が作成されます。変数は変数イテレータの子として宣言され、ローカルであるため、関連付けられているバインディング・コンテキストのみで有効になります。例10-14は、createServiceRequest(String, Integer, Integer)メソッドの使用時に作成される変数イテレータおよび変数を示しています。

例10-14 ページ定義ファイルでの変数イテレータおよび変数

<executables>
  <variableIterator id="variables">
    <variable Type="java.lang.String"
              Name="createServiceRequest_problemDescription"
              IsQueriable="false"/>
    <variable Type="java.lang.Integer" Name="createServiceRequest_productId"
              IsQueriable="false"/>
    <variable Type="java.lang.Integer" Name="createServiceRequest_createdBy"
              IsQueriable="false"/>
  </variableIterator>
</executables>

10.7.5 実行時に行われる処理

ユーザーがデータを入力してフォームを送信すると、変数に値が移入され、NamedData要素の値に対するEL式を使用して、属性バインディングによってメソッドのパラメータの値が提供されるようになります。

SRDemoアプリケーションのサービス・リクエスト作成プロセスでは、プロセス・トレインが使用され、これによって実際のリクエストの作成が3つの手順に分割されます(11.5項「複数ページ・プロセスの作成」を参照してください)。説明の便宜上、ここではプロセスが1つのページに含まれていると仮定します。対応するinputTextコンポーネントにユーザーが説明を入力し、Create Productボタンをクリックすると、次の処理が実行されます。

  • problemDescriptionVar変数にユーザーが入力した値が移入されます。

  • problemDescription属性バインディングが変数イテレータを参照し、特にItem値としてproblemDescriptionVar変数を参照するため、次のように、属性バインディングによって説明が取得されます。

    <attributeValues id="problemDescription" IterBinding="variables">
      <AttrNames>
        <Item Value="createServiceRequest_problemDescription"/>
      </AttrNames>
    </attributeValues>
    
  • 次のように、NamedData要素のNameには、problemDescription属性バインディングのアイテム値に対して評価するEL式が含まれているため、値にもアクセスできます。

    <NamedData NDName="problemDescription" NDType="java.lang.String"           NDValue="${bindings.createServiceRequest_problemDescription}"/>
    
  • createServiceRequestメソッドは、対応するNamedData要素から値を取得する各パラメータを使用して実行されます。

10.8 検索ページの作成

パラメータを取得してレコードを検索するメソッドを使用して、検索フォームを作成できます。また、その結果を表に表示できます。このタイプの検索フォームでは、ユーザーが各パラメータの情報を入力する必要があります。図10-10は、ID、ステータスおよび問題の説明を指定してすべてのサービス・リクエストを検索できる、SRSearch検索フォームを示しています。

図10-10 SRSearchフォーム

SRSearchによるID、ステータスおよび問題の検索

10.8.1 検索フォームの作成方法

検索するロジックを含む既存のメソッドをドロップして検索フォームを作成し、パラメータに基づいてレコードを戻すことができます。このメソッドは、データ・コントロールにすでに存在している必要があります。図10-11は、図10-10に示した検索フォームの作成に使用する、findServiceRequestSearch(Integer, String, String)メソッドを示しています。ID、ステータスおよび説明を指定すると、このメソッドにより、すべてのサービス・リクエストが検索され、戻されます。

図10-11 データ・コントロール・パレット内でのパラメータを取得する検索メソッドの表示

パラメータを使用してデータを戻すカスタム検索メソッド

検索フォームを作成するには、メソッドをパラメータ・フォームとしてドロップします。その後、戻されたコレクションを表としてドロップし、結果を表示します。セッション中にユーザーが初めてSRSearchページにアクセスしたときには、このページに結果表は表示されません。条件付きで結果表を非表示にする手順は、10.9項「検索ページの結果表の条件付き表示」を参照してください。

検索フォームおよび結果表の作成手順:

  1. データ・コントロール・パレットからパラメータを取得する検索メソッドをドラッグします。

  2. ポップアップ・メニューから、「パラメータ」「ADFパラメータ・フォーム」を選択します。

  3. データ・コントロール・パレットからメソッドの戻りをドラッグし、いずれかのタイプの表としてドロップします。

10.8.2 パラメータ・メソッド使用時に行われる処理

メソッドをパラメータ・フォームとしてドロップすると、JDeveloperによって次の処理が行われます。

  • データ値を保持する変数、メソッドのメソッド・バインディング、および関連付けられている属性の属性バインディングが、ページ定義ファイルで定義されます。

  • ADF Faces inputTextコンポーネントおよびADF Faces commandButtonコンポーネントを使用して、JSFページにフォームのコードが挿入されます。このコードは、その他の入力フォームまたはコマンド・ボタンのコードと同じです。

メソッドの戻りであるコレクションをドロップする場合と同様に、パラメータを取得するメソッドをJSFページ上にドロップすると、JDeveloperによってメソッド・アクション・バインディングが作成されます。ただし、実行するパラメータがメソッドによって要求されるため、JDeveloperによって、各パラメータのNamedData要素も作成されます。これらの要素は、メソッドのパラメータを表します。各要素は、対応する属性の値バインディングにバインドされます。このバインディングにより、メソッドは、実行のパラメータに対する正しい属性の値にアクセスできます。

たとえば、findServiceRequestSearchメソッド・アクション・バインディングには、取得する各パラメータのNamedData要素が含まれます。NamedData要素のstatusParamは、EL式を使用して、findServiceRequestSearch_statusParam属性バインディングにバインドされます。例10-15は、メソッド・アクション・バインディングおよびfindServiceRequestSearchメソッドをパラメータ・フォームとしてドロップしたときに作成される属性バインディングの一部を示しています。

例10-15 ページ定義ファイルでのメソッド・アクション・バインディング

<bindings>
  <methodAction id="findServiceRequestSearch"
                    MethodName="findServiceRequestSearch"
                    RequiresUpdateModel="true" Action="999"
                    DataControl="SRPublicFacade"
                    InstanceName="SRPublicFacade.dataProvider"
                    ReturnName="SRPublicFacade.methodResults.SRPublicFacade_
                             dataProvider_findServiceRequestSearch_result">
    <NamedData NDName="svrIdParam" NDType="java.lang.Integer"
               NDValue="${bindings.findServiceRequestSearch_svrIdParam}"/>
    <NamedData NDName="statusParam" NDType="java.lang.String"
               NDValue="${bindings.findServiceRequestSearch_statusParam}"/>
    <NamedData NDName="problemParam" NDType="java.lang.String"
               NDValue="${bindings.findServiceRequestSearch_problemParam}"/>
  </methodAction>
...
  <attributeValues id="svrIdParam" IterBinding="variables">
    <AttrNames>
      <Item Value="findServiceRequestSearch_svrIdParam"/>
    </AttrNames>
  </attributeValues>
  <attributeValues id="problemParam" IterBinding="variables">
    <AttrNames>
      <Item Value="findServiceRequestSearch_problemParam"/>
    </AttrNames>
  </attributeValues>
...
</bindings>

戻りではなくメソッドをドロップしたため、属性によって、コレクションにアクセスして反復処理を行うメソッド・イテレータではなく、変数にアクセスして反復処理を行う変数イテレータが参照されます。これは、メソッドは(戻されたコレクションとは異なり)オブジェクトのインスタンスにアクセスする必要がなく、ページに入力された値を保持するものがないためです。変数はこれらのデータ・ホルダーとして機能します。

JDeveloperによって、各メソッド・パラメータの変数が作成されます。変数は変数イテレータの子として宣言され、ローカルであるため、関連付けられているバインディング・コンテキストのみで有効になります。例10-16は、変数イテレータおよびfindServiceRequestSearchメソッドの使用時に作成される変数を示しています。変数イテレータは、フォームおよびボタンの両方で使用されます。

例10-16 ページ定義ファイルでの変数イテレータおよび変数

<executables>
  <variableIterator id="variables">
    <variable Type="java.lang.Integer"
              Name="findServiceRequestSearch_svrIdParam" IsQueriable="false"/>
    <variable Type="java.lang.String"
              Name="findServiceRequestSearch_statusParam"
              IsQueriable="false"/>
    <variable Type="java.lang.String"
              Name="findServiceRequestSearch_problemParam"
              IsQueriable="false"/>
  </variableIterator>
...
</executables>

その後、戻されたコレクションを結果表用にドロップすると、JDeveloperによって、戻されたコレクションを反復処理するメソッド・イテレータが追加されます。結果は表に含まれるため、表バインディングも作成されます。例10-17は、メソッド・イテレータおよび表バインディングに対して生成されたコードを示しています。

例10-17 戻されたコレクションのページ定義コード

<executables>
  <variableIterator id="variables">
...
  </variableIterator>
  <methodIterator id="findServiceRequestSearchIter"
                  Binds="findServiceRequestSearch.result"
                  DataControl="SRPublicFacade" RangeSize="10"
                  BeanClass="oracle.srdemo.model.entities.ServiceRequest"/>
</executables>
<bindings>
...
  <table id="findAllServiceRequest1" IterBinding="resultsIterator">
    <AttrNames>
      <Item Value="assignedDate"/>
      <Item Value="problemDescription"/>
      <Item Value="requestDate"/>
      <Item Value="status"/>
      <Item Value="svrId"/>
    </AttrNames>
  </table>
...
</bindings>

同じメソッドが使用されているため、表をドロップしたときに、新しいメソッド・バインディングは作成されません。詳細は、7.2.2項「データ・コントロール・パレットを使用した表の作成時に発生する処理」を参照してください。

10.8.3 実行時に行われる処理

ユーザーがデータを入力してフォームを送信すると、変数に値が移入され、NamedDataElementの値に対するEL式を使用して、属性バインディングによってメソッドのパラメータの値が提供されるようになります。


ヒント:

検索フォームおよび結果表が同じページにある場合、ユーザーがそのページに初めてアクセスしたときに、イテレータからのすべてのレコードが表に表示されます。ユーザーが実際に検索を実行するまで結果表が表示されないようにすることができます。手順は、10.9項「検索ページの結果表の条件付き表示」を参照してください。

ユーザーが対応するinputTextコンポーネントにステータスとしてClosedを入力し、コマンド・ボタンをクリックすると、次の処理が実行されます。

  • findServiceRequestSearch_status変数に値Closedが移入されます。

  • 次のように、この属性バインディングは、変数イテレータを参照するため、statusの値を取得できます。

      <attributeValues id="status" IterBinding="variables">
        <AttrNames>
          <Item Value="findServiceRequestSearch_statusParam"/>
        </AttrNames>
      </attributeValues>
    
  • 次のように、NamedData要素には属性バインディングのアイテム値に対して評価するEL式が含まれているため、パラメータは値にもアクセスできます。

    <NamedData NDName="status" NDType="java.lang.String"
        NDValue="${bindings.findServiceRequests_statusParam}"/>
    
  • NamedData要素から値を取得するパラメータを使用して、findServiceRequestSearchメソッドが実行されます。

  • findServiceRequestSearchメソッドによって、パラメータ値と一致するレコードのコレクションが戻されます。

  • findServiceRequestSearchIterイテレータによってコレクションが反復処理されるため、表に結果が表示されるようになります。実行時の表の詳細は、7.2.2項「データ・コントロール・パレットを使用した表の作成時に発生する処理」を参照してください。

10.9 検索ページの結果表の条件付き表示

検索フォームおよび結果表が同じページにある場合、ユーザーがそのページに初めてアクセスしたときに、イテレータからのすべてのレコードが表に表示されます。ユーザーが実際に検索を実行するまで結果表が表示されないようにすることができます。図10-12は、ユーザーが初めてアクセスしたときのSRSearchページの表示を示しています。

図10-12 結果表が表示されていない検索ページ

結果表が表示されていないSRSearchページ

ユーザーが検索を実行すると、図10-13のように結果表が表示されます。

図10-13 結果表が表示された検索ページ

検索の実行後に表示された結果表

10.9.1 条件付き表示機能の追加方法

条件付きで結果表を表示するには、UIコンポーネント(表自体または表コンポーネントを保持する別のコンポーネント)について、ユーザーによる検索ページへのアクセスが1回目かどうかに対して評価するEL式を入力する必要があります。マネージドBeanのフィールドには、式で使用された値が保持されます。

条件付きで結果表を表示する手順:

  1. 同じページで検索フォームおよび結果表を作成します。手順は、10.8項「検索ページの作成」を参照してください。

  2. マネージドBeanで、ユーザーによるページへのアクセスが1回目の場合に設定されるフラグを作成します。たとえば、SRDemoアプリケーションのuserStateマネージドBeanには、SEARCH_FIRSTTIME_FLAGパラメータが含まれます。ページをレンダリングするかどうかを判断するために、ページのEL式は、このパラメータの値を認識する必要があります(手順4を参照)。このBeanがEL式に対してインスタンス化されると、isSearchFirstTimeメソッドによってこのフィールドがチェックされます。フィールドがnullの場合は、値がTrueに設定されます。マネージドBeanの作成方法の詳細は、10.2項「マネージドBeanを使用した情報の格納」を参照してください。

  3. JSFページで、setActionListenerコンポーネントを、この検索の実行に使用されるコマンド・コンポーネントに挿入します。from属性を#{false}に設定します。to属性を、手順2で作成したマネージドBeanのフィールドに設定します。これにより、このボタンがクリックされるたびに、このフィールドがfalseに設定されます。setActionListenerコンポーネントの使用方法の詳細は、10.4項「コマンド・コンポーネントを使用したパラメータ値の設定」を参照してください。

    例10-18は、SRSearchページの「検索」ボタンのコードを示しています。

    例10-18 setActionListenerコンポーネントを使用した値の設定

    <af:commandButton actionListener="#{bindings.findServiceRequestSearch.execute}"
                     text="#{res['srsearch.searchLabel']}">
      <af:setActionListener from="#{false}"
                               to="#{userState.searchFirstTime}"/>
    </af:commandButton>
    
  4. JSFページでRendered属性の値としてEL式を使用し、変数が特定の値の場合のみUIコンポーネント(表または表を保持するUIコンポーネント)によってレンダリングが行われるようにします。

    例10-19は、SRSearchページでpanelGroupコンポーネントのRendered属性の値に使用されるEL式を示しています。

    例10-19 検索結果表を条件付きで表示するためのJSFコード

    <af:panelGroup rendered="#{!userState.searchFirstTime}">
    

    このEL式により、searchFirstTimeフラグの値がFalseの場合のみ、panelGroupコンポーネントによってレンダリングが行われます。

10.9.2 条件付きで結果表を表示した場合に行われる処理

マネージドBeanを使用して値を保持すると、その他のオブジェクトによる値の設定および値へのアクセスがともに可能になります。たとえば、パラメータ値の引渡しと同様に、setActionListenerコンポーネントを使用してマネージドBeanに値を設定すると、コンポーネントのrendered属性のEL式がその値にアクセスできるようになります。

たとえば、ユーザーが初めてSRSearchページにアクセスした場合は、次の処理が行われます。

  • 表を保持するpanelGroupコンポーネントには、そのrendered属性のEL式が含まれており、EL式がuserState Beanを参照するため、このBeanがインスタンス化されます。

  • ユーザーはまだページにアクセスしていないため、userState BeanのSEARCH_FIRSTTIME_FLAGフィールドは未設定であり、値はnullです。

  • 値がnullであるため、このBeanのisSearchFirstTimeメソッドによって、値がtrueに設定されます。

  • EL式が評価され、SRSearchページが表示されますが、SEARCH_FIRSTTIME_FLAGフィールドがtrueであることから、ネストされた表などのパネル・グループはレンダリングされません。

  • ユーザーが検索条件を入力して「検索」ボタンをクリックすると、関連付けられているsetActionListenerコンポーネントによって、userState BeanのsearchFirstTime値がfalseに設定されます。

  • コマンド・ボタンの結果が定義されていないため、ユーザーは同じページにとどまります。

  • この時点ではsearchFirstTimeの値がfalseに設定されているため、結果を使用してページが再レンダリングされると、panelGroupコンポーネントによって結果を含む表が表示されます。