この章では、ページにより複雑なバインディングを追加する方法について説明します。内容には、フォームおよびコマンド・コンポーネントを作成するためのパラメータを取得するメソッドの使用方法などが含まれます。
この章の内容は次のとおりです。
基本的なページを作成してナビゲーション機能を追加すると、マネージドBeanに情報を格納したり、宣言アクションをオーバーライドするなどの、より複雑な機能をページに追加できます。ADFには、このような複雑な機能を実際のコードをほとんど使用せずに追加できる機能が用意されています。
たとえば、ServiceRequest
コレクションに対するDelete
操作をコマンド・ボタンとしてドラッグ・アンド・ドロップすることにより、SRMainページに「Delete」ボタンが作成されます。次に、このDelete
操作をオーバーライドすることにより、ボタンがクリックされたときに、キャッシュからサービス・リクエストが削除され、さらにトランザクションがコミットされるようにします。また、SRMainページは、SRDemoアプリケーション内の多くのページからアクセスできます。userState
マネージドBean(UserSystemState.java
)には、元ページの値が保持されます。オーバーライドされたDelete
操作には、ユーザーが正常にSRMainページを閉じることができるように、元ページの値にアクセスするためのロジックも用意されています。
この章では次の内容について説明します。
パラメータ値またはフラグを格納するためのマネージドBeanの作成および使用方法
アプリケーション・モジュールでカスタム・メソッドを起動するコマンド・コンポーネントの作成方法
パラメータ値の設定方法
コマンド・コンポーネントにバインドされた操作またはカスタム・メソッドへのロジックの追加方法
多くの場合、ページにはその他のページからの情報が必要です。そのページのページ定義ファイルにパラメータ値を設定するなどして、この情報をページに直接設定すると、本質的に情報がハードコード化されます。これにかわる方法として、この情報をマネージドBeanに格納できます。Beanがアクセス可能なスコープ内に格納されているかぎり、Beanの属性のすべての値に、EL式を使用してアクセスできます。
ヒント: マネージドBeanを使用して格納する情報は、管理用の情報のみにする必要があります。すべてのアプリケーション・データおよび処理データは、アプリケーションのビジネス・レイヤーのロジックによって処理される必要があります。 |
たとえば、SRMainページは、ユーザーを正しいページに戻すために、ユーザーの移動元のページを認識している必要があります。SRDemoアプリケーションでは、この情報を保持するマネージドBeanが存在するため、情報を送る側のページで情報を設定できます。また、SRMainページでこの情報を使用することで、移動先が判別されます。
マネージドBeanは、faces-config.xml
ファイルを使用してアプリケーションに登録するJavaクラスです。JSFアプリケーションの起動時に、この構成ファイルが解析されてBeanが使用可能になり、EL式で参照できるようになります。これにより、Beanのプロパティおよびメソッドへのアクセスが可能になります。マネージドBeanが初めて参照されるときに存在しない場合は常に、マネージドBean作成機能によってそのBeanのデフォルト・コンストラクタ・メソッドがコールされ、Beanがインスタンス化されます。プロパティも宣言された場合は、宣言済のデフォルト値が移入されます。
JDeveloperのJSF構成エディタを使用すると、マネージドBeanを作成し、同時にJSFアプリケーションに登録できます。
マネージドBeanの作成手順:
faces-config.xml
ファイルを開きます。このファイルは、<project_name>/WEB-INF
ディレクトリに格納されます。
ウィンドウの最下部で、「概要」タブを選択します。
左側の要素リストで、「Managed Bean」を選択します。図17-1はfaces-config.xmlファイルのJSF構成エディタを示しています。
「新規」ボタンをクリックして、図17-2のように「マネージドBeanの作成」ダイアログを開きます。Beanの名前および完全修飾クラス・パスを入力します。スコープを選択し、「Javaファイルの生成」チェック・ボックスを選択して、「OK」をクリックします。
ヒント: マネージドBeanがアプリケーションの複数のページで使用される場合は、スコープをSession に設定する必要があります。ただし、この場合はバインディング・オブジェクトのデータがrequest スコープにあり、Beanにバインディング・コンテナへの参照を含めることができないため、このBeanはリクエストのみでしか有効になりません。バインディング・コンテナの参照が必要になる場合の例は、17.5項「宣言メソッドのオーバーライド」を参照してください。 |
必要に応じて、「管理プロパティ」バーの左にある矢印を使用して、Beanのプロパティを表示できます。「新規」をクリックしてプロパティを作成します。[F1]を押すと、構成エディタの追加のヘルプが表示されます。
注意: 構成エディタを使用して管理プロパティを宣言することはできますが、対応するコードはJavaクラスで生成されません。このコードを追加するため、適切なタイプのプライベート・メンバー・フィールドを作成し、コード・エディタのポップアップ・メニューの「アクセッサの生成」メニュー項目を使用してこれらのBeanプロパティに対応するgetterおよびsetterメソッドを生成する必要があります。 |
構成エディタを使用してマネージドBeanを作成し、Javaファイルの生成を選択すると、JDeveloperによって、指定された名前のスタブ・クラスおよびデフォルトのコンストラクタが作成されます。例17-1は、ビュー・パッケージに格納されるMyBean
クラスに追加されたコードを示しています。
また、JDeveloperによってmanaged-bean
要素がfaces-config.xml
ファイルに追加されます。この宣言により、指定された名前を参照するEL式を使用して、Beanのすべてのロジックに簡単にアクセスできるようになります。例17-2は、MyBean
クラスに対して作成されたmanaged-bean
要素を示しています。
例17-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を使用して情報を保持する方法の詳細な例は、これらの各項を参照してください。
アプリケーションにカスタム・メソッドが含まれている場合、これらのメソッドはデータ・コントロール・パレットに表示されます。これらのメソッドは、コマンド・ボタンとしてドラッグ・アンド・ドロップできます。ユーザーがボタンをクリックすると、メソッドが実行されます。カスタム・メソッドの詳細は、第8章「アプリケーション・モジュールによるビジネス・サービスの実装」を参照してください。
たとえば、SRDemoアプリケーションのSRServiceアプリケーション・モジュールには、deleteServiceHistoryNotes(Set keySet)
メソッドが含まれます。このメソッドにより、1行以上の行が選択されたときにこれらの行が削除され、トランザクションがコミットされるようになります。ユーザーがこのメソッドを実行できるようにするには、図17-3のように、データ・コントロール・パレットからdeleteServicehistoryNotes(Set)
メソッドをドラッグします。
注意: SRDemoアプリケーションでは、マネージドBeanでdeleteServiceHistoryNotes(Set) メソッドをオーバーライドすることにより、このメソッドにビュー・レイヤー・ロジックが追加されます。また、条件付きナビゲーション・ロジックを使用する必要がある場合、カスタム・メソッドをオーバーライドすることもできます。詳細は、17.5項「宣言メソッドのオーバーライド」を参照してください。 |
要求されるビジネス・ロジックを実行するために、多くのメソッドで、そのメソッドの1つ以上のパラメータに対する値が要求されます。つまり、メソッドにバインドされたボタンを作成する際には、パラメータの値が検出される場所を指定する必要があります。
たとえば、deleteServicehistoryNotes(Set)
メソッドを使用する場合、削除する行セットを指定する必要があります。
データ・コントロール・パレットから、ページ上にメソッドをドラッグします。
ヒント: 表またはフォームに含まれるデータを使用するメソッドのボタンをドロップする場合は、その表またはフォームの中にボタンをドロップする必要があります。 |
ポップアップ・メニューから「メソッド」→「ADFコマンド・ボタン」を選択します。
メソッドがパラメータを取得する場合は、「アクション・バインディング・ダイアログ」が開きます。アクション・バインディング・エディタで、「パラメータ」の「値」列にある省略記号(...)ボタンをクリックし、EL式ビルダーを起動します。このビルダーを使用して、メソッドのパラメータの値を設定します。
メソッドをコマンド・ボタンとしてドロップすると、JDeveloperによって次の処理が行われます。
メソッドのメソッド・アクション・バインディングが定義されます。メソッドがパラメータを取得する場合は、パラメータ値を保持するNamedData
要素が作成されます。
ADF Facesコマンド・コンポーネント用のコードがJSFページに挿入されます。このコードは、その他のコマンド・ボタンのコードと同じです。詳細は、13.4.2.3項「EL式を使用したナビゲーション操作へのバインド」を参照してください。ただし、ボタンは、組込み操作用のアクション・バインディングのexecute
メソッドではなく、ドロップしたメソッド用のメソッド・アクション・バインディングのexecute
メソッドにバインドされます。
パラメータを取得するメソッドをJSFページにドロップすると、メソッド・アクション・バインディングが作成されます。このバインディングにより、ユーザーがコマンド・コンポーネントをクリックしたときにメソッドが実行されるようになります。メソッドが実行するパラメータを要求する場合は、JDeveloperによって、各パラメータのNamedData
要素も作成されます。これらの要素は、メソッドのパラメータを表します。
たとえば、deleteServiceHistoryNotes
メソッド・アクション・バインディングには、Set
パラメータのNamedData
要素が含まれます。この要素は、アクション・バインディングの作成時に指定した値にバインドされます。例17-3は、deleteServiceHistoryNotes
(Set)
メソッドをドロップし、ページのバッキングBeanの履歴表UIコンポーネントのselectionState
プロパティのkeySet
プロパティにSet
パラメータ(keySet
)をバインドしたときに作成されるメソッド・アクション・バインディングを示しています(このメソッドを使用して複数の行(キー・セット)を削除する方法の詳細は、14.6.5項「selectionファセットにおけるtableSelectManyコンポーネントの使用方法」を参照)。
例17-3 パラメータ・メソッドのメソッド・アクション・バインディング
<methodAction id="deleteServiceHistoryNotes" InstanceName="SRService.dataProvider" DataControl="SRService" MethodName="deleteServiceHistoryNotes" RequiresUpdateModel="true" Action="999"> <NamedData NDName="keySet" NDValue="${backing_SRMain.historyTable.selectionState.keySet}" NDType="java.util.Set"/> </methodAction>
操作を使用してコマンド・ボタンを作成するときと同様に、メソッドを使用してコマンド・ボタンを作成すると、actionListener
属性を使用して、ボタンがメソッドに自動的にバインドされます。ボタンは、指定されたメソッドのアクション・バインディングのexecute
プロパティにバインドされます。このバインディングにより、アプリケーション・モジュールに対してバインディングのメソッドが起動します。コマンド・ボタンのactionListener
属性の詳細は、13.4.3項「実行時の処理: アクション・イベントおよびアクション・リスナー」を参照してください。
ヒント: アクション・バインディングのexecute メソッドにボタンをバインドするかわりに、execute メソッドをオーバーライドするバッキングBean内のメソッドにボタンをバインドできます。そうすることで、元のメソッドの実行前か実行後に、ロジックを追加できるようになります。詳細は、17.5項「宣言メソッドのオーバーライド」を参照してください。 |
ナビゲーション操作のように、ボタンのdisabled
プロパティは、EL式を使用してボタンを表示するかどうかを決定します。例17-4は、コマンド・ボタンをdeleteServiceHistoryNotes(Set)
メソッドにバインドするためのEL式を示しています。
1つのページでのアクションに対して、アプリケーション機能を判別するためのパラメータを設定する必要が生じる場合があります。たとえば、SRSearchページの結果表が表示されるのは、userState
マネージドBeanのsearchFirstTime
フラグの値がfalse
である場合のみです。検索ページのレンダリング時にこのBeanがインスタンス化されると、このBeanのisSearchFirstTime
メソッドによってこのパラメータがチェックされます。このパラメータがnull
の場合(ページが初めてレンダリングされる場合)は、値がtrue
に設定されます。
この場合、この検索を実行するために使用されるコマンド・ボタンにネストされているsetActionListener
コンポーネントを使用してsearchFirstTimeフラグがfalse
に設定され、検索の実行後に結果表が表示されるようになります。マネージドBeanの使用方法の詳細は、17.2.1項「マネージドBeanを使用した情報の格納方法」を参照してください。
setActionListener
コンポーネントを使用して、その他のオブジェクトの値を設定できます。このコンポーネントは、コマンド・コンポーネントの子である必要があります。
setActionListenerコンポーネントの使用手順:
データ・コントロール・パレットまたはコンポーネント・パレットを使用して、コマンド・コンポーネントを作成します。
コンポーネント・パレットからsetActionListener
コンポーネントをドラッグして、コマンド・コンポーネントの子としてドロップします。
「至」をパラメータの設定対象に設定します。
ヒント: 作成されるページのページ定義ファイルに直接パラメータ値を設定するかわりに、マネージドBeanまたはスコープにパラメータ値を格納することを考慮してください。次のページに直接設定すると、それ以降、ナビゲーションを簡単に変更できなくなります。詳細は、17.2項「マネージドBeanを使用した情報の格納」を参照してください。また、バインディング・コンテナ内のデータは、そのコンテナが準備されたリクエストでのみ有効です。そのため、データを設定してから次のページがレンダリングされるまでの間に、データが変更される場合があります。 |
setActionListener
コンポーネントを使用すると、移動する前にコマンド・コンポーネントによって値が設定されます。From
属性を渡す値のソースまたは実際の値に設定すると、コンポーネントからその値へのアクセスが可能になります。To
属性をターゲットに設定すると、コマンド・コンポーネントによってターゲットに値が設定されるようになります。例17-5は、JSFページのコマンド・コンポーネントのコードを示しています。このコマンド・コンポーネントは、false
値を取得し、この値をuserState
マネージドBeanのsearchFirstTime
フラグの値として設定します。
ユーザーがコマンド・コンポーネントをクリックすると、移動する前に、setActionListener
コンポーネントによってパラメータ値が設定されます。例17-5では、setActionListener
によって現在の行のfalse
値が取得され、その値がuserState
マネージドBeanのsearchFirstTime
属性の値として設定されます。これにより、レンダリングするかどうかを決定するためにこの値を認識する必要があるコンポーネントは、EL式#{userState.searchFirstTime}
を使用してこれにアクセスできます。完全な例は、18.5項「検索ページの結果表の条件付き表示」を参照してください。
操作またはメソッドをコマンド・ボタンとしてドロップすると、操作またはメソッドのexecute
メソッドに、そのボタンが自動的にバインドされます。ただし、ロジックの実行前または実行後に、ロジックの追加が必要になる場合もあります。たとえば、Delete
操作が正常に実行された後、ユーザーが別のボタンをクリックしなくてもすむように、Commit
操作を実行する必要がある場合があります。
JDeveloperでは、バインディング・コンテナにアクセスするマネージドBeanでメソッドおよびプロパティを新規作成することにより、宣言的操作にロジックを追加できます。デフォルトでは、この生成されたコードによって、操作またはメソッドが実行されます。その後、このコードの前か後にロジックを追加できます。元の操作またはメソッドのexecute
プロパティではなく、この新規メソッドにコマンド・コンポーネントが自動的にバインドされます。その後、ユーザーがボタンをクリックすると、新規メソッドが実行されます。
次に、BeanSRDemoアプリケーションの一部の例を示します。それぞれの例では、まずバインディング・コンテナを挿入し、宣言メソッドの実行前または実行後にロジックを追加するメソッドが、バッキングBeanに含まれています。
SRCreateConfirm.java:
createSR_action
メソッドは、createServiceRequest
メソッドをオーバーライドし、メソッドの実行後にJSFUtils
ヘルパー・クラスのパラメータ値としてサービス・リクエストのIDを設定します。
SRMain.java:
onDeleteRequest
メソッドはDelete
操作をオーバーライドします。最初にDelete
アクションを実行します。エラーが発生した場合、ページを再表示します。エラーがない場合、アプリケーション・モジュールに対してCommit
操作を実行します。エラーが発生した場合、ページを再表示します。エラーがない場合、ユーザーはUserState
マネージドBeanでReturnNavigationRule
値として保持されているページに戻されます。
宣言メソッドをオーバーライドするには、マネージドBeanにコマンド・コンポーネントがバインドされる新規メソッドを保持させる必要があります。ページにバッキングBeanが関連付けられている場合は、JDeveloperによって、バインディング・オブジェクトへのアクセスに必要なコードがバッキングBeanに追加されます。ページにバッキングBeanが関連付けられていない場合は、作成を促す指示が表示されます。
注意: 現在、コマンド・コンポーネントのAction 属性の値としてEL式が設定されている場合は、JDeveloperによってEL式が上書きされないため、次の手順を使用できません。次の手順を行う前に、この値を削除する必要があります。 |
宣言メソッドのオーバーライドの手順:
オーバーライドする操作またはメソッドをJSFページ上にドラッグし、UIコマンド・コンポーネントとしてドロップします。
これにより、コンポーネントが作成され、コンポーネントのActionListener
属性を使用して、ADFモデル・レイヤーの関連するバインディング・オブジェクトにバインドされます。
データ・コントロール・パレットでメソッドを使用したコマンド・コンポーネントの作成方法の詳細は、17.3項「メソッドを実行するためのコマンド・コンポーネントの作成」を参照してください。
操作からのコマンド・コンポーネントの作成方法の詳細は、13.4.2項「データ・コントロール・パレットでコマンド・ボタンを作成した場合の処理」を参照してください。
JSFページでコンポーネントをダブルクリックします。
「バインドActionプロパティ」ダイアログで、バッキングBeanおよびコンポーネントをバインドするメソッドを指定します。指定方法は次のいずれかです。
自動バインディングがそのページで有効化されている場合は、図17-4のように、バッキングBeanはすでに自動選択されています。
新規メソッドを作成するには、「メソッド」フィールドにメソッドの名前を入力します。このフィールドには、最初にデフォルト名が表示されています。
または
既存のメソッドを使用するには、「メソッド」フィールドのドロップダウン・リストからメソッドを選択します。
「ADFバインディング・コードの生成」を選択します。
そのページで自動バインディングが使用されていない場合は、図17-5のように、既存のバッキングBeanから選択するか、新たに作成できます。自動バインディングの詳細は、11.5.4項「自動コンポーネント・バインディング機能の使用方法」を参照してください。
「新規」をクリックして、新しいバッキングBeanを作成します。「マネージドBeanの作成」ダイアログが表示されます。このダイアログを使用して、Beanおよびクラスに名前を付け、Beanのスコープを設定します。
または
既存のバッキングBeanおよびメソッドをドロップダウン・リストから選択します。
バッキングBeanおよびメソッドを識別したら、「バインドActionプロパティ」ダイアログで「OK」をクリックします。
ソース・エディタでマネージドBeanが自動的に開きます。例17-6は、Beanに挿入されたコードを示しています。この例では、コマンド・ボタンがDelete操作にバインドされます。
例17-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("Delete"); Object result = operationBinding.execute(); if (!operationBinding.getErrors().isEmpty()) { return null; } return null; }
バインディング・オブジェクトにアクセスする前または後に、ロジックを追加できます。
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
のままになります。
宣言メソッドをオーバーライドすると、#{bindings}
(バインディング・コンテナへの参照)の管理プロパティ値を使用してバッキングBeanに管理プロパティが追加され、強く型付けされたBeanプロパティがBindingContainer
型のクラスに追加されます。このプロパティは、JSFランタイムによって管理プロパティ式#{bindings}
の値を使用して設定されます。また、JDeveloperによって、UIコマンド・アクション・メソッドにもロジックが追加されます。このロジックには、現在のバインディング・コンテナにアクセスするための、強く型付けされたgetBindings()
メソッドが含まれます。
例17-8は、選択したマネージドBeanに自動的に追加されたコードを示しています。戻りのString
"Complete"
は、これがaction
属性の値であるため、メソッドに自動的に追加されたものです。
例17-8 バインディング・オブジェクトへのアクセス用にバッキングBeanで生成されたコード
private BindingContainer bindings; ... public String createSRButton_action() { BindingContainer bindings = getBindings(); OperationBinding operationBinding = bindings.getOperationBinding("createServiceRequest"); Object result = operationBinding.execute(); if (!operationBinding.getErrors().isEmpty()) { return null; } return "Complete"; }
このコードによって行われる処理は次のとおりです。
関連付けられているメソッドのバインディングを検索し、実行します。
ナビゲーションに使用できるメソッドの戻りを追加します。デフォルトでは戻りはnull
ですが、ボタンのAction
属性にすでに結果文字列が存在する場合は、その属性が戻り値として使用されます。このコードは、必要に応じて変更できます。戻された結果の使用方法の詳細は、16.4項「動的ナビゲーションの使用」を参照してください。
ActionListener
属性ではなく、Action
属性を使用して新しいメソッドにUIコマンド・コンポーネントがリバインドされます。たとえば、例17-9は、createServiceRequest
メソッドをドロップして作成されたコマンド・ボタンに対する、JSFページのコードを示しています。actionListener
属性はcreateServiceRequest
メソッドにバインドされており、action
属性にはComplete
のString
結果が含まれます。ユーザーがボタンをクリックすると、メソッドが単純に実行され、このナビゲーション・ケースのtoViewId
として定義されているページに移動します。
例17-9 宣言メソッドにバインドされたコマンド・ボタンのJSFページ・コード
<af:commandButton actionListener="#{bindings.createServiceRequest.execute}" text="createServiceRequest" disabled="#{!bindings.createServiceRequest.enabled}" id="createSRButton" action="Complete"/>
例17-10は、ページのバッキングBeanのメソッドをオーバーライドした後のコードを示しています。ここでは、action
属性は、バッキングBeanのメソッドにバインドされています。
例17-10 オーバーライド後のメソッドにバインドされたコマンド・ボタンのJSFページ・コード
<af:commandButton text="createServiceRequest" disabled="#{!bindings.createServiceRequest.enabled}" id="createSRButton" action="#{backing_SRCreateConfirm.createSRButton_action}"/>
ヒント: オーバーライド済メソッドを使用するボタンをクリックすると、次のエラーが表示されます。
これは、オーバーライドするメソッドを含むマネージドBeanのスコープが、 |