Oracle JDeveloper 10g JSF/EJB3.0アプリケーション開発

智野 潤子

日本オラクル株式会社
システム製品統括本部 Fusion Middleware技術部 SOA/Javaグループ
エンジニア 智野 潤子

JDeveloperが本になります。『Oracle JDeveloper 10g JSF/EJB3.0アプリケーション開発』というタイトルで2007年4月出版予定です。
こちらもよろしくお願いします。

第5回:JSFコンポーネントによるユーザー・インタフェース開発 - 2


今回は、JSFコンポーネントを用いたWebアプリケーションのユーザー・インタフェース開発の2回目として、データを表形式で表示するための方法を紹介します。

表形式でのデータの表示  

Oracle ADF Faces(以下、ADF Faces)では、データを表形式で表示するためにTableコンポーネント(af:tableタグ)を使用します。af:tableタグは、JSFリファレンス実装により提供されるDataTableコンポーネント(h:dataTableタグ)には含まれていない、次のような機能を備えています。

  • 列ヘッダーのクリックによるソート
  • 指定した件数ごとのスクロール
  • 詳細データのオープン/クローズ
  • 列データの選択(ラジオボタンで1件ずつ選択/チェックボックスによる複数選択)
図 1:ADF Faces Tableの利用例
図 1:ADF Faces Tableの利用例

<サンプル 1>は、af:tableタグの基本的な使用方法です。

<サンプル 1>

<af:table value=”#{managed_bean.list}” var=”row”>
  <af:column headerText=”従業員番号”>
    <af:outputText value=”#{row.empno}”/>
  </af:column>
  <af:column headerText=”名前”>
    <af:commandLink text=”#{row.ename}”/>
  </af:column>
  <af:column headerText=”職種”>
    <af:outputText value=”#{row.job}”/>
  </af:column>
</af:table>

af:tableタグはh:dataTableタグと同様に、value属性を使用して表示するデータのコレクションをEL式で指定します。af:tableタグのvalue属性には、次のようなコレクションを指定できます。

  • 配列
  • java.util.List
  • javax.faces.model.DataModel
  • oracle.adf.view.faces.model.CollectionModel

var属性には、コレクション内の個々のオブジェクトにアクセスするための変数名を指定します。<サンプル 1>では「row」が指定されています。
af:tableタグは1つ以上のaf:columnタグを含みます。af:columnタグは表の列を表し、headerText属性では、列ヘッダーとして表示するテキストを指定することができます。また、af:columnタグの子タグは、その列のデータを表示する際に使用するUIコンポーネントです。<サンプル 1>では、それぞれの列が表 1のように設定されています。

 表 1:<サンプル 1>における各列の設定

列ヘッダー・テキスト UIコンポーネント データ
1列目 従業員番号 af:outputText #{row.empno}
2列目 名前 af:commandLink #{row.ename}
3列目 職種 af:outputText #{row.job}

この章では次の2つのクラスを使用して、af:tableタグのさらに詳しい使用方法を説明します。EmpServiceBeanには、従業員を表すEmpオブジェクトのリストを返すgetEmpListが実装されており、「emp_service」という名前でマネージドBeanとして登録されていることを前提にしています。

図 2:サンプルで使用するJavaクラス [class-diagram.bmp]
図 2:サンプルで使用するJavaクラス [class-diagram.bmp]

■ af:tableタグの追加  

JDeveloperでは、ページにaf:tableタグを容易に追加することができる「表の挿入」ウィザードを提供しています。このウィザードは次のように使用します。

  1. コンポーネント・パレットが表示されていなければ、メニュー・バーから「表示」→「コンポーネント・パレット」を選択し、コンポーネント・パレットを開きます。
  2. コンポーネント・パレット上部のドロップダウン・リストから「ADF Faces Core」を選択し、「Table」をビジュアル・エディタにドラッグ&ドロップします。
    図 3:コンポーネント・パレットで「Table」を選択
    図 3:コンポーネント・パレットで「Table」を選択
  3. 「Tableの挿入」ウィザードが起動します。「ようこそ」ページが表示された場合は、「次へ」ボタンをクリックします。
  4. 図4の「Tableの挿入」ウィザードのステップ1では、「今すぐバインド」を選択し、「値」(af:tableタグのvalue属性)、および「Var」(af:tableタグのvar属性)の値を指定します。また、「データ型のヒント」に行のデータを表すJavaBeansのクラス名を指定することで、そのプロパティの定義情報に基づいて、af:columnタグが自動的に追加されます。
    図 4:Tableの挿入ウィザード ステップ1
    図 4:Tableの挿入ウィザード ステップ1
    1.「値」フィールドの右にある「バインド」ボタンをクリックして、「Expression Builder」ダイアログを起動します。

    2.「Expression Builder」ダイアログで、画面左の「変数」ツリーから「JSFマネージドBean」→「emp_service」→「empList」を選択した状態で、「>」ボタンをクリックします。
    図 5:Expression Builderダイアログ
    図 5:Expression Builderダイアログ
    3. 画面右の「式」フィールドに「#{emp_service.empList}」と表示されていることを確認したら、「OK」ボタンをクリックして、「Tableの挿入」ウィザードに戻ります。

    4.「Var」フィールドに「row」、「データ型のヒント」にEmpクラスの完全修飾名を指定し、「次へ」ボタンをクリックします。
  5. 「Tableの挿入」ウィザードのステップ2では、ステップ1の「データ型のヒント」で指定したクラス定義をもとに、af:columnタグの設定が自動的におこなわれています。ここでは、列を表示する順序や、各ヘッダーに表示されるテキストとデータの値、およびデータを表示するUIコンポーネントを変更することができます。図 6では、ヘッダーのテキストを変更しています。
    図 6:Tableの挿入ウィザード ステップ2
    図 6:Tableの挿入ウィザード ステップ2
    「次へ」ボタンをクリックします。
  6. 「Tableの挿入」ウィザードのステップ3では、それぞれのaf:columnタグの詳細情報を指定します。ステップ2の設定項目(列の表示順や列ヘッダー・テキスト、値、UIコンポーネント)はこのステップでも変更できます。さらに、行揃えとソートに関する設定をおこなうことも可能です。
    図 7:Tableの挿入ウィザード ステップ3
    図 7:Tableの挿入ウィザード ステップ3
    • 書式設定タイプはデータの行揃えの設定で、次の3種類から選択できます。
      - text - 左揃え
      - number - 右揃え
      - icon - 中央揃え
    • 「ソート可能」をチェックして「ソート・プロパティ」を指定しておけば、その列のヘッダーをクリックするとデータを昇順/降順でソートできるようになります。
    • 「ソート・プロパティ」には、ソートの基準となるプロパティ名を指定します。たとえば、enameプロパティでソートする場合は「ename」と入力します。

    「次へ」ボタンをクリックします。
  7. 「Tableの挿入」ウィザードのステップ4では、表全体の設定をおこなうことができます。
    図 8:Tableの挿入ウィザード ステップ4
    図 8:Tableの挿入ウィザード ステップ4
    • 「範囲ナビゲーションを含める」をチェックすると、「行」で指定した数よりデータが多い場合に範囲ナビゲーションが有効になり、「前のX件/次のX件」のリンクと、表示するデータの範囲を選択するドロップダウン・リストが自動的に追加されます。図 8では、「行」に10を設定しています。
    • 「詳細の開示を含める」をチェックすると、af:tableタグのdetailStampファセットが有効になります。詳細は後述します。
    • 「選択列を含める」をチェックすると、af:tableタグのselectionsファセットが有効になり、「単一選択」か「複数選択」の選択に応じて、TableSelectOneまたはTableSelectManyコンポーネントのいずれかが追加されます。詳細は後述します。
    • 「表バインディングを含める」をチェックすると、af:tableタグのbanding属性がrowまたはcolumnに設定されます。「バンド間隔」(af:tableタグのbandingInterval属性)で指定した行数または列数ごとに、色が交互に切り替わります。図 8では「行」を選択し、「バンド間隔」を2に設定しています。

    「終了」ボタンをクリックします。これにより、JSFページにaf:tableタグが追加されます。
  8. 作成したJSF JSPページを実行すると、図9のように表示されます。
    図 9:ADF Faces Tableの実行
    図 9:ADF Faces Tableの実行
    ページに追加したaf:tableを、ビジュアル・エディタあるいは構造ウィンドウで右クリックし、コンテキスト・メニューから「プロパティ」を選択するか、構造ウィンドウでaf:tableのノードをダブルクリックすると、「Tableのプロパティ」ダイアログが起動されるので、「Tableの挿入」ウィザードで設定した値を簡単に変更することができます。

■ af:tableタグのファセット  

af:tableタグには、次の5つのファセットが用意されています。

  • header - 表全体のヘッダーを指定
  • footer - 表全体のフッターを指定
  • detailStamp - 詳細データを追加。このファセットを有効にすると、表の各行に「表示/非表示」リンクが追加され、ユーザーのクリックで詳細データの表示/非表示の切り替えが可能
  • selections - TableSelectOneまたはTableSelectManyコンポーネントを追加することで、表に表示されているデータを選択
  • actions - テーブルに表示されたデータを操作するActionメソッドを起動するUIコンポーネント(ボタンまたはリンク)を表示するために使用

本章では、detailStampファセットとselectionsファセットの使用法について説明します。

detailStampファセットによる詳細データの表示

af:tableタグにdetailStampファセットを追加すると、図 10のように「詳細」列が加わり、各行に「表示/非表示」リンクが入ります。detailStampファセット内に記述されたコンポーネントは「表示」リンクをクリックしたときにのみ表示されるようになります。

図 10:detailStampファセットによる詳細データの表示行
図 10:detailStampファセットによる詳細データの表示

JDeveloperで、af:tableタグにdetailStampファセットを追加する方法は、次の2通りがあります。

a. 構造ウィンドウでdetailStampを追加するaf:tableをダブルクリックし、起動した「Tableのプロパティ」ダイアログの「書式設定」ページで、「詳細の開示を含める」をチェック

b. 図11のように、構造ウィンドウでdetailStampを追加するaf:tableを右クリックし、コンテキスト・メニューから「ファセット - Table」→「Detail Stamp」を選択

図 11:af:tableタグにdetailStampファセットを追加
図 11:af:tableタグにdetailStampファセットを追加

給与のデータ(Empオブジェクトのsalプロパティ)を詳細情報として表示する場合は、salプロパティを表示していたcolumnタグを削除し、代わりに<サンプル 2>の太字部分のようにコードを変更します。

<サンプル 2>

<af:table value=”#{managed_bean.list}” var=”row”>
  <af:column headerText=”社員番号”>
    <af:outputText value=”#{row.empno}”/>
  </af:column>
  <af:column headerText=”名前”>
    <af:outputText value=”#{row.ename}”/>
  </af:column>
  <!-- 中略 -->
  <f:facet name=”detailStamp”>
    <af:outputText value=”${row.sal}”/>
  </f:facet>
</af:table>

TableSelectOneコンポーネントによるデータの単一選択

Webアプリケーションでは、テーブル形式で表示されたデータの中から選択されたデータの詳細情報を、表示するページや編集ページに遷移させることがよくあります。そのような場合、af:tableタグのselectionsファセットにTableSelectOneコンポーネント(af:tableSelectOneタグ)を追加します。af:tableSelectOneタグを使用すると、図 12のように「選択」列が追加され、それぞれの行にラジオボタンが表示されます。

図 12:af:tableSelectOneタグによる行の単一選択
図 12:af:tableSelectOneタグによる行の単一選択

selectionsファセットにTableSelectOneファセットを追加するには、構造ウィンドウでaf:tableをダブルクリックし、起動された「Tableのプロパティ」ダイアログの「書式設定」ページで、「選択列を含める」をチェックしてから「単一選択」を選択します。
選択されたデータに対する処理を実装するためには、次のような手順が必要です。

  1. af:tableタグをマネージドBeanのプロパティとして公開
  2. 処理を起動するためのUIコンポーネント(ボタンまたはリンク)を画面に追加
  3. UIコンポーネントのActionメソッドを記述

「JSF JSPの作成」ウィザードのステップ2で、「新規マネージドBeanでUIコンポーネントの自動公開」または「既存のマネージドBeanでUIコンポーネントの自動公開」オプションを選択した場合は、af:tableタグはマネージドBeanのプロパティとして自動的に公開されています。「マネージドBeanでUIコンポーネントを自動公開しない」を選択した場合には、手動での設定が必要です。af:tableタグをマネージドBeanのプロパティとして公開するには、af:tableタグをビジュアル・エディタまたは構造ウィンドウで選択し、プロパティ・インスペクタで「Binding」の右のフィールドをクリックすると表示される「...(編集)」をクリックします。

図 13:プロパティ・インスペクタでBinding属性を編集
図 13:プロパティ・インスペクタでBinding属性を編集

これにより、「Binding」ダイアログが表示されるので、af:tableをプロパティとして公開するマネージドBeanとプロパティ名を指定し、「OK」ボタンをクリックします。

図 14:Bindingダイアログ
図 14:Bindingダイアログ

図 14では、マネージドBeanとして「emp_service」を、プロパティとして「table」を指定しています。これにより、af:tableタグのbinding属性の値として「#{emp_service.table}」が指定され、EmpServiceBeanクラスには<サンプル 3>のようにtableプロパティとsetter/getterメソッドが追加されます。

<サンプル 3>

public class EmpServiceBean {
  private oracle.adf.view.faces.component.core.data.CoreTable table;

  // 中略

  public void setTable(CoreTable table) {
    this.table = table;
  }

  public CoreTable getTable() {
    return table;
  }
}

次に、処理を起動するためのUIコンポーネントを追加します。図15のように構造ウィンドウで、追加されたaf:tableSelectOneを右クリックし、コンテキスト・メニューから「af:tableSelectOneの中に挿入」→「CommandButton」を選択します。

図 15:af:commandButtonの追加
図 15:af:commandButtonの追加

これにより、af:commandButtonタグが追加され、図16のようにテーブルの一番上に表示されます。このaf:commandButtonがクリックされたときに起動されるActionメソッドを実装するには、ビジュアル・エディタでaf:commandButtonをダブルクリックします。

図 16:追加されたaf:commandButtonをダブルクリック
図 16:追加されたaf:commandButtonをダブルクリック

JDeveloperでは、af:commandButtonなどのボタンをビジュアル・エディタでダブルクリックすると、「バインドActionプロパティ」ダイアログが起動されます。ボタンがクリックされたときに起動されるActionメソッドを実装する場合は、「マネージドBean」とメソッドの名前を指定します。図 17では、マネージドBeanとして「emp_service」を、メソッドとして「commandAciton」を指定しています。

図 17:バインドActionプロパティのダイアログ
図 17:バインドActionプロパティのダイアログ

「バインドActionプロパティ」ダイアログで「OK」ボタンをクリックすると、af:commandButtonタグのaction属性に「#{emp_service.commandAction}」が指定され、マネージドBeanのJavaソース(EmpServiceBean.java)にメソッドの雛形が追加されます。<サンプル 4>は、テーブルから選択された従業員の名前を標準出力に出力しています。

<サンプル 4>

public String commandAction() {
  Emp emp = (Emp) getTable().getRowData(); // 選択されたオブジェクト
  System.out.println(emp.getEname());
  Return null;
}

TableSelectManyコンポーネントによるデータの複数選択

テーブル内のデータを一括で削除する場合など、アプリケーションの要件によってはテーブル内に表示されたデータから複数のものを選択する必要がある場合があります。そのようなときには、af:tableタグのselectionsファセットにTableSelectManyコンポーネント(af:tableSelectManyタグ)を追加すると、図 18のように各行にチェックボックスが追加されます。

図 18:af:tableSelectManyタグによる行の単一選択
図 18:af:tableSelectManyタグによる行の単一選択

selectionsファセットにTableSelectOneファセットを追加するには、構造ウィンドウでaf:tableをダブルクリックし、起動された「Tableのプロパティ」ダイアログの「書式設定」ページで、「選択列を含める」をチェックしてから「複数選択」を選択します。
af:tableSelectOneと同様に、ユーザーが選択したデータを取得するには、次の3つのステップが必要です。

  1. af:tableコンポーネントをマネージドBeanのプロパティとして公開
  2. 処理を起動するためのUIコンポーネント(ボタンまたはリンク)を画面に追加
  3. UIコンポーネントのActionメソッドを記述

それぞれの手順の詳細は、af:tableSelectOneで説明しているため、ここではActionメソッドの実装例のみを紹介します。<サンプル 5>は、af:tableSelectManyタグによって選択したEmpオブジェクトの名前を標準出力に出力します。

<サンプル 5>

public class EmpServiceBean {
  private oracle.adf.view.faces.component.core.data.CoreTable table;
  public void setTable(CoreTable table) { this.table = table; }
  public CoreTable getTable() { return table; }

  // 中略

  public String commandAction() {
    // 選択された行のキーを取得
    Iterator iter = table.getselectionState().getKeySet().iterator();
    Object oldKey = table.getRowKey();
    while (iter.hasNext()) {
      Object key = iter.next();
      table.setRowKey(key); // 備考参照
      Emp emp = (Emp) table.getRowData(); //選択されたオブジェクトの1つ
      System.out.println(emp.getEname());
    }
    table.setRowKey(oldKey);
    return null;
  }
}

<note>
af:tableタグで表示される行のデータには、それぞれキーが割り振られており、ユーザーが選択した行のキーはrowKeyプロパティで管理しています。getRowDataメソッドは、rowKeyプロパティにセットされているキーに応じてデータを戻します。af:tableSelectOneタグで選択された行のキーは、自動的にrowKeyプロパティに設定されます。しかし、rowKeyプロパティはキーを1つだけしか保持できません。af:tableSelectManyタグによって複数の行が選択されている場合は<サンプル 5>のように選択された行のキーのコレクションを取得し、getRowDataメソッドをコールする前に、rowKeyプロパティを設定する必要があります。
</note>

インデックスに戻る

まとめ  

前回から2回にわたり、ADF Facesを使用したWebアプリケーションのユーザー・インタフェースの開発について説明しました。ADF Facesが提供するUIコンポーネントを使用すると、これまでJavaScriptによるプログラミングが必要だった機能を簡単に実現することがご確認いただけたのではないでしょうか。
ADF Facesはほかにも、入力フォーム用のコンポーネントや部分ページレンダリングなどの多彩な機能を備えています。マニュアルなどを参考にして、ぜひ実際にお試しください。

<note>次世代ADF Faces
オラクルではすでに、ADF Facesの次期バージョンの開発プロジェクトを進めています。この次世代ADF Facesの最大の目標は、デスクトップ・アプリケーションのもつ操作性をWebページで実現するためのUIコンポーネントを提供することです。
次世代ADF Facesのコンポーネントでは、次のような機能が提供される予定です。

  • メニュー
  • 列の幅や表示順を自由に変更できる表
  • ドラッグ&ドロップのサポート
図 19:次世代ADF Facesによるアプリケーション
図 19:次世代ADF Facesによるアプリケーション

</note>

インデックスに戻る