Oracle ADFによるデータ・バインディング: Part 1
データ・バインディングの仕組み

2004年7月

概要

この資料では、J2EEアプリケーションにデータ・バインディング層を提供する新しいOracle Application Development Framework(ADF)の基本を説明します。ADFの実行時および設計時のデータ・バインディング機能を概説し、その概念を簡単なサンプル・アプリケーションによって具体的に紹介します。

目次

         はじめに
         ADFデータ・バインディング・コンセプトの概要
         現在/将来の標準テクノロジーに対するサポート
         ADFバインディングの設計時のサポート機能
                 データ・コントロールの作成
                 データ・コントロール・パレットによるUIの設計
                 バインディング・コンテナ定義およびバインディング定義の作成
                 バインディング・コンテキストの内容の表示.
         オンライン・ヘルプ内のADF情報
         実際のアプリケーション例によるケーススタディ
                 サンプル・アプリケーションの概要
                 ADF/Struts統合の基本詳細
                 サンプルのアクションのアプローチに関する考察
                 カスタム・メソッドによるモデル・データのセットアップ
                 コントローラとサービスとを分離させるアクション・バインディング
                 フル・ライフサイクル・サポートのためのDataActionの使用
                 ページフロー・ダイアグラムを簡略化するDataPage
                 DataAction 機能をフル活用した宣言的手法
                 EL(式言語)を使用したWebページ内のデータの参照
         ADFデータ・バインディングに関するQ & A
         最後に

はじめに

Oracle JDeveloperに新しく導入された Oracle Application Development Framework (ADF)は、既にいくつもの実績を持つ BC4J フレームワークの柔軟性とオープン性を新しいレベルに進化させたものです。抽象化された「データ・コントロール」をバックエンド・ビジネス・サービスとして新しく導入し、その対応のために既存のデータ・バインディング・オブジェクトを汎用化することで、首尾一貫したプラッガブルなモデル層をJ2EEアプリケーション・アーキテクチャに追加しました。

図1は、ADF全体像の中で、モデル、ビュー、コントローラおよびビジネス・サービス・アーキテクチャとADFデータ・コントロール/ADFバインディングがどのように組み込まれているかを示しています。

J2EEアプリケーションのためのOracle ADFアーキテクチャ
図1: J2EE アプリケーションのためのOracle ADFアーキテクチャ

Oracle ADFでは、EJB Session Bean、WebサービスおよびADFアプリケーション・モジュール(従来のBC4Jアプリケーション・モジュール)といったテクノロジー・ベースのビジネス・サービス、またはより一般にユーザー作成のJavaBeans によるビジネス・サービスを基にしてデータ・コントロールという抽象オブジェクトを作成することが可能です。このデータ・コントロール(ADFデータ・コントロール)と、ビュー層との結合を担うADFバインディングは、ADFフレームワークのベース・クラスの上で、XMLメタデータを使用して構成されます。これらのベース・クラスには、追加コーディングなしでアプリケーション開発ニーズのほとんどを扱うことができるように機能が用意されています。必要に応じて、フレームワーク・ベース・クラスをカスタマイズしたり、まったく新しいデータ・コントロールおよびバインディング実装を追加することが可能です。

図1に示されているように、既存の代表的なビュー層テクノロジに対して、ADFバインディング層への対応機能が提供され、実行時と設計時の両面でデータ・バインディング機能を共有できるようになっています。 この共通データ・バインディング・アーキテクチャおよびそれを実施するために改善されたビジュアル設計機能はJDeveloperの「Productivity with Choice (選択可能な生産性)」というコンセプトにとって不可欠です。

この資料では、Oracle ADFデータ・バインディングの概念をよく理解し、設計時にOracle JDeveloperを使用してどのように作業するか、およびOracle ADFを使用するStrutsベースJSPアプリケーションの簡単な作業例を検討することで、データ・バインディングが実際にどのように動作するかに注目します。

ADFデータ・バインディング・コンセプトの概要

Oracle ADFの主なデータ・バインディング概念は次のとおりです。

図2は、簡単なDiscussion Forumアプリケーションにおいてこれらの概念がどのように表現されるかを示しています。 ReviewThreads.jsp ページを使用すると、Web経由で、ディスカッション・フォーラムのオープン・スレッドを参照し、1つまたは複数のスレッドの質問に対して、回答すべき特定のチームへの割り当てを行うことができます。 ページでは、ADFアプリケーション・モジュールを使用して実装されている ForumServiceという名前のサービスから、ディスカッション・フォーラム情報とそのスレッドについてのデータを取得します。このページ上のポップリストには、スレッドの回答担当として割り当てる対象の有効なチーム名のリストが入っていて、そのデータは LookupCodesと呼ばれるバックエンドWebサービスから引き出されます。

各ビジネス・サービスに対応するデータ・コントロールは、一貫した方法でそれをADFバインディング・モデル層に適合させます。 アプリケーションのバインディング・コンテキストには、 ReviewThreads.jspページが使用する ReviewThreadsという名前のバインディング・コンテナおよび、高機能Webページ(UIX XML ページ:Page2.uix)と Swing パネル(Panel3.java)が共有する UnansweredPostingsという名前のバインディング・コンテナが含まれます。 ReviewThreadsバインディング・コンテナの内容は次のとおりです。

なお属性コントロール・バインディングは、その値を提供するイテレータ・バインディングを参照します。 リスト・バインディングの場合は、2つの異なるイテレータに関係しています。 1つはリストに表示される値を提供する属性、もう1つはリストから新しい値が選択されたときに実際に更新されるターゲット属性を提供します。

ADFデータ・バインディングの実施例
図 2: ADFデータ・バインディングの実施例

図3は、この概念が実行時にどのような関係になって機能するかを示しています。 アプリケーションのバインディング・コンテキストには、使用されるデータ・コントロールおよびそれを包含するバインディング・コンテナが入っています。 各バインディング・コンテナは、特定のページが使用するデータ・コレクションを識別するイテレータ・バインディングを持っています。 各イテレータ・バインディングは、特定のデータ・コントロールから取り出されたデータに対して機能します。 また、バインディング・コンテナは、ページ内の UI コントロールと結合される コントロール・バインディングを持っています。 コントロール・バインディングは、データに結合されるタイプ(属性コントロール・バインディング)の場合、イテレータに関連づいています。コントロール・アクション・バインディングの場合は、データ・コントロールに直接関連づいて、データ・コントロールのカスタム・メソッドの起動に使用されます。

ADFバインディング実行時クラスのUML図
図 3: ADFバインディング実行時クラスのUML図

現在/将来の標準テクノロジーに対するサポート

ADFバインディングはJava標準を考慮して設計されており、JavaBeanおよびJava Collections Frameworkとやりとりできる任意のクライアント・テクノロジと共に簡単に使用できます。 たとえば、 JSP Standard Tag Library(JSTL)やJakarta Struts プロジェクトのタグ・ライブラリなどの一般的なタグ・ライブラリが Oracle ADFとシームレスに動作します。 JSTLおよびJSP 2.0の両方の核である標準の Expression Language(EL:式言語)を使用するだけで、ビジネス・サービスのデータをWebページ内で簡単に処理できます。
Swing UIよるリッチなクライアント・アプリケーションに対しては、これまでのJDeveloperリリースで提供されていたバインディング機能(JClientバインディング)に改良を加えて、基本ADFバインディング機能を拡張して、ツリー、スピナー、スライダーなどのより高度なSwingコントロールのために必要な追加のバインディングを提供しています。

オラクルもその他のベンダーも、共通のデータ・バインディング機能をJavaプラットフォームの標準部品とすべきだと信じており、 JSR 227仕様のリーダーとして、オラクルは、これを実現すべく Java Community Processの一環として他社と協力しています。 JDeveloperのADFデータ・コントロールおよびADFバインディングは、提案されたJSR 227データ・バインディング機能の先行的実装であり、今後のADFリリースはJSR 227の最終的なAPIおよびメタデータをサポートするように展開されます。

ADFバインディングの設計時のサポート機能

JDeveloperは、Oracle ADFと強固に連携して、完全に宣言的な形式での設計サポートを提供します。 このセクションでは特に、これまでに紹介したOracle ADFバインディング・コンセプトを扱う方法に焦点を当てます。

注意:

このセクションのスクリーンショットは、この資料の以降のセクションで検討する ADFBindingIntro サンプルに基づいています。 例を簡単にしておくため、馴染み深い SCOTT スキーマの EMP 表のデータと、単純なJavaBeanのデータに基づいて説明します。


データ・コントロールの作成

ユーザーが作成したADFビジネス・コンポーネントのアプリケーション・モジュールはどれも、初期状態でデータ・コントロールとしてアクセス可能です。一方、Webサービス、JavaクラスまたはEJB Session Beanをベースとしたデータ・コントロールは、アプリケーション・ナビゲータ内でそれらを選択して、以下のどちらかの方法で明示的に作成する必要があります。

ADFアプリケーション・モジュールを使用して実装 されていないビジネス・サービス用にデータ・コントロールを作成したプロジェクトでは、 DataControls.dcxファイルが自動的に表示されます。 ファイルには、ランタイム・フレームワークが必要とする、ユーザーのデータ・コントロールについての基本メタデータの断片がいくつか入っています。 図4は、アプリケーション・ナビゲータ内でユーザーが DataControls.dcxファイルを選択したときに表示される状態を示しています。 構造ペインは、ユーザーが定義したデータ・コントロールの一覧を表示します。 興味があれば、ファイルをダブルクリックして、そのXMLコンテンツをソース・エディタ上で見ることができますが、JDeveloperの設計機能によってコンテンツが自動的に管理されているためファイルは読取り専用です。

データ・コントロールのメタデータが入ったDataControls.dcxファイル
図 4: データ・コントロールのメタデータが入ったDataControls.dcxファイル

この資料で後に扱うサンプル・アプリケーションでは、 test.model.beans.CommissionPlanという名前のJavaBeanと test.model.services.CommissionService という名前のJavaBeanを利用しています。ソース・コードは次のとおりです。

 
package test.model.services;
import java.util.*;
import test.model.beans.CommissionPlan;
public class CommissionService  {
  private static final ArrayList plans = new ArrayList(4);
  public CommissionService() {}
  public Collection getAvailableCommissionPlans() {
    return plans;
  }
  static {
    plans.add(new CommissionPlan("High",2000));
    plans.add(new CommissionPlan("Medium",1000));
    plans.add(new CommissionPlan("Low",500));    
  }
}

アプリケーション・ナビゲータ内の CommissionService.java ファイルに対して データ・コントロールの作成 のメニューを選択したとき、ADF ランタイム でこのサービスにアクセスするために必要な追加情報を記録した CommissionService.xml メタデータ・ファイルの作成を、ADFデザインタイム(設計サポート機能)が実施します。 図5 はアプリケーション・ナビゲータ内で CommissionService.xml を選択した場合に表示されるものを示しています。 構造ペインには、このサービスが公開しているプロパティとメソッドが表示されます。構造ペインで availableCommissionPlansプロパティを選択すると、プロパティ・インスペクタでは、それについての追加のメタデータが表示され、ここから編集が可能です。

データ・コントロールの構造とプロパティ
図 5: データ・コントロールの構造とプロパティ

CommissionService自身の情報からでは、 getAvailableCommissionPlansCollection型を返すことしかわからないため、この追加の「Beanクラス」メタデータ・プロパティを使用して、実行時にこのコレクションに入るBeanの種類を指定することができます(この例の場合はtest.model.beans.CommissionPlanです)。 このプロパティは、プロパティ・インスペクタを使用して手作業でセットしなければなりませんが、プロパティを介して CommissionPlanCommissionServiceに結びつけると、JDeveloperはそのJavaBeanについてのメタデータを記録するだけでなく、 CommissionPlan.xmlメタデータ・ファイルも自動作成します。

注意:

上記例はシンプルなJavaBeansをデータ・コントロールにする場合の手順ですが、ADF アプリケーション・モジュールの場合は、すでに固有のXMLメタデータ・ファイルを所有し、データ・コントロールとして公開するのに十分なメタデータを含んでいるため、そのままでデータ・コントロールとして利用可能です(追加のメタデータ・ファイルの作成は不要です)。


図6は、Oracle ADFとともに初期状態で提供されるデータ・コントロールの種類を示しています。 データ・コントロール定義用のメタデータの中で、適切なデータ・コントロール実装のインスタンスを作成するためのファクトリ・クラスの名前が指定されます。

提供されているデータ・コントロール実装のUML図
図 6: 提供されているデータ・コントロール実装のUML図


データ・コントロール・パレットによるUIの設計

必要なデータ・コントロールを作成すると、ユーザー・インタフェース・プロジェクト内で使い始めることができます。 新しく導入されたデータ・コントロール・パレットは、現在のワークスペースで使用可能なすべてのデータ・コントロールを示し、一貫した方法でデータと操作(メソッド)を提示します。

イテレータおよびコントロール・バインディング用のデータは、サービスによって公開されているプロパティから、または起動されるサービス・メソッドの戻り値から採用されます。 コントロール・アクション・バインディング用の操作は、バインディング・オブジェクトが提供している組込みアクション(CreateDeleteNextPreviousRollbackCommitなど)だけでなく、データ・コントロール実装に用意されたカスタム・メソッドであってもかまいません。 図7は、上で見た availableCommissionPlans プロパティを持つ CommissionServiceDataControl という名前のJavaBeanベースのデータ・コントロールを示しています。 その値は amountおよび nameプロパティを持つBean(CommissionPlan)のコレクションです。

ドラッグ&ドロップによるデータ・バインディングが可能なADFデータ・コントロール・パレット
図 7: ドラッグ&ドロップのデータ・バインディングが可能なADFデータ・コントロール・パレット

また EmpServiceDataControlという名前のデータ・コントロールが test.model.services.EmpServiceアプリケーション・モジュール用に自動的に利用可能になるのもわかります。 その ビュー・オブジェクト・インスタンスである Employeesプロパティは EmpnoEnameHiredateなどの属性をもつ行セットです。データ・バインディングの設計作業は、データの提供方法に関係なくどの種類のバックエンド・データ・ソースについても同様です。

データ・コントロール・パレットの一番下にあるポップリストに注目してください。 WebページまたはSwingパネルがアクティブなとき、この領域には、選択されたデータ・ソースと、アクティブなUIページ/パレットの組合せに適切で、よく使用されるUI要素の一覧が示されます。 図8 は、JSPページがアクティブなときにデータ・コレクションに対して選択可能なUI 要素を示しています。

データ・コントロール・パレットによるデータ・バインディングUIコントロールのドロップ
図 8: データ・コントロール・パレットによるデータ・バインディングUIコントロールのドロップ

もちろん、Swingパネルまたは高機能Webページ(UIX XML ページ)上で作業を行っている場合には、それらに適切な別のUI要素セットが示されます。 また、コレクションの代わりにパレット内で Enameamountなどの 属性操作(Operation) を指定した場合も、それに応じた選択項目が表示されます。

バインディング・コンテナ定義およびバインディング定義の作成

バインディング・コンテナ定義およびバインディング定義を作成するには、暗黙的な方法と明示的な方法の2通りがあります。

- 暗黙的方法

データ・バインディングUI要素をデータ・コントロール・パレットから ビジュアル・エディタ構造ペイン、または コード・エディタへドラッグ&ドロップすると、JDeveloper が暗黙的にバインディング定義および(必要に応じて)それを格納するバインディング・コンテナ定義を作成します。 つまり次のことを行います。

図9は、構造ペインの UIモデル タブを使用して、現在のページに対応するバインディング・コンテナ内のバインディング定義を表示する方法を示しています。ビジュアル・エディタでshowEmployees.jsp ページが開かれているとき、構造ペインのUIモデルタブに対応付けられている showEmployeesUIModelバインディング・コンテナおよびそれに含まれる各種バインディングが示されます。

では、データ・コントロール・パレットと構造ペインのUIモデルタブの違いは何でしょう? データ・コントロール・パレットはワークスペース内のすべてのデータ・コントロールを表示し、バインディング用に利用可能なすべてのデータを提示します。 UIモデルタブは、現在のページのバインディング・コンテナの内容を示し、現在のページが表示または修正の対象としているデータのサブセットを表します。

現行ページのバインディング情報を表示する構造ペインのUIモデルタブ
図 9: 現行ページのバインディング情報を表示する構造ペインのUIモデルタブ

バインディング定義は、バインディング・コンテナXMLファイル内にメタデータとして記述されますが、XMLファイルをユーザーが編集する必要はありません。 たとえば上の showEmployees.jspページが使用する EmployeesIter という名前のイテレータ・バインディング上にプロパティを設定するには、構造ペイン内のバインディングをクリックし、 図10 に示されているようにプロパティ・インスペクタを使用して、その設定を表示または編集します。

注意:

バインディング・エディタ・ダイアログからしか設定できないバインディング・プロパティもあります。 バインディング・エディタ・ダイアログを立ち上げるには、プロパティ・インスペクタ内の 編集... タスク・リンクをクリックする、または構造ペイン内のバインディング・オブジェクト上の右クリック・メニューから 編集...を選択します。


現行のバインディング定義に対するプロパティ・インスペクタ
図10: 現行のバインディング定義に対するプロパティ・インスペクタ

上のプロパティ・インスペクタ内の EmployeesIter イテレータ・バインディングの モデル参照プロパティの値を見ると、 EmpServiceDataControlデータ・コントロール内の Employeesという名前のデータ・コレクションを参照していることがわかります。

行の表示に使用される レンジ・バインディングである Employeesという名前のコントロール・バインディングをクリックすると、プロパティ・インスペクタ内でイテレータ名プロパティとして EmployeesIterが設定されていることがわかります。 コントロール・バインディングはこれらのプロパティ値を介してイテレータ・バインディングに関連付けられ、さらにイテレータ・バインディングはそれを提供するデータ・コントロール内のデータに結びつけられます。

バインディングのデフォルト名が気に入らない場合は、プロパティ・インスペクタを使用して ID プロパティの値を変更できます。

注意:

バインディングの名前を変更する場合は、UIページまたはパネル内でその名前を参照している場所を確実に更新してください。


- 明示的方法

自動的なドラッグ&ドロップ・アプローチのほかに、バインディング・コンテナ定義およびその中のバインディング定義を手動で作成する方法もあります。 エディタ上でページまたはパネルがアクティブなとき、構造ペインの UIモデルタブをクリックして" <バインディングなし>"が表示された場合は、現行ページにはバインディング・コンテナがまだ対応付けられていないことを意味します。 データ・コントロール・パレットからドラッグ&ドロップを使用したくない場合は、 図11の " <バインディングなし>"を右クリックして UI モデルの作成メニュー項目を選択できます。 これは、プロジェクト・プロパティのデフォルト・パッケージ設定によって指示されているディレクトリ内に <YourPageNameOrPanelName>UIModel.xmlファイルが作成される結果になります。

手動でのバインディング・コンテナの作成(UI Model)
図 11: 手動でのバインディング・コンテナの作成(Uモデル)

構造ペインのUIモデルタブ内で右クリック・メニューを使用して、任意のバインディング・コンテナ内に新しいバインディング定義を作成できます。 バインディング・コンテナ自体を表しているツリーのルート・ノードを選択し、 図12に示されているように バインディングの作成 メニューから項目を選択できます。

バインディング・コンテナ内にバインディングを手動で作成
図 12: バインディング・コンテナ内にバインディング定義を手動で作成

このメニューから選択可能な項目を使用すれば、 図13に示されているバインディング・オブジェクトの主な種類をすべて作成することができます。これらのフレームワーク・バインディング・クラスは、バインディング・コンテナ定義のXMLファイル内に記述された、バインディング定義情報(メタデータ)に基づいて実行時に連結されます。 概して必要ではありませんが、カスタム・バインディング実装または提供されているバインディング・クラスを拡張するカスタマイズ・バージョンも準備できます。

主なランタイム・バインディング・オブジェクトのUML図
図 13: 主なランタイム・バインディング・オブジェクトのUML図

バインディングを手動で作成するとき、バインディングの定義に必要なプロパティのいくつかを取得するためバインディング・エディタが表示されます。 手動作成されたバインディングのデフォルト名はプロパティ・インスペクタを使用して変更できます。 バインディングを削除する必要がある場合は、バインディングを選択して、右クリック・メニューから「削除」を選択します。

バインディング・コンテキストの内容の表示

ユーザーがデータ・コントロールを使用してバインディング・コンテナを作成すると、JDeveloperによって、その情報がメタデータとして DataBindings.cpxファイルに記録されます。 アプリケーション・ナビゲータ内の DataBindings.cpxファイルをクリックすると、アプリケーションのバインディング・コンテキストの内容が構造ペインに表示されます。 図14 は、ADFBindingIntroアプリケーションが2つのデータ・コントロールを持ち、1つのバインディング・コンテナ(UIモデル)を使用していることを示しています。

バインディング・コンテキストを定義しているDataBindings.cpxファイル
図 14: バインディング・コンテキストを定義しているDataBindings.cpxファイル

DataBindings.cpxファイルは、このアプリケーションで使用中のデータ・コントロールの目次の役割を果たします。 実行時、データ・コントロールとバインディング・コンテナ用のメタデータ定義が遅延ロードされます。

オンライン・ヘルプ内のADF情報

簡単な作業例による説明に入る前に、JDeveloperオンライン・ヘルプについて紹介しておきます。ここには、ADFデータ・コントロールとADFバインディングについての詳細だけでなく、各種クライアントおよびバックエンド・ビジネス・サービス実装の組み合わせでとともにそれらを使用する方法についてのチュートリアルも提供されていることに注意してください。

メインメニューから ヘルプ目次を選択すると、 図15に示されているようなヘルプ・ナビゲータが表示されます。

ヘルプ・ナビゲータ・ウィンドウ
図 15: ヘルプ・ナビゲータ・ウィンドウ

ヘルプ・トピックを選択した後、エディタ領域に新しいタブが表示され、ヘルプ資料を読むことができます。
特に以下のトピックは、最初に参考にする項目として有効ですので紹介しておきます。

注意:

構造ペインのUI モデル タブからバインディングを選択した後、 [F1] キーを押せば、バインディングの種類に対応したオンライン・ヘルプにジャンプできます。 構造ペインでバインディングを右クリックして、 Javadocの参照...を選択すると、その特定のバインディングをサポートしているフレームワークのベース・バインディング・オブジェクトについてのJavadocにジャンプできます(Javadocがインストールされている場合)。


実際のアプリケーション例によるケーススタディ

ここでは、Oracle ADFバインディング・コンテナを活用したシンプルなStrutsベースのWebアプリケーションを考えます。 ユーザーは各自でサンプルを試してみるために必要なファイルが入った ADFBindingIntro.zipファイルをダウンロードできます。

注意:

接続ナビゲータの"データベース" の下にscott という名前の接続を作成する必要があります。 それは、ユーザーがアクセスできるデータベース上のSCOTT/TIGER スキーマを指していなければなりません。


サンプル・アプリケーションの概要

ADFBindingIntroサンプル・アプリケーションは、 showEmployees.jspという名前のJSPページで構成されています。そのページは、ADFアプリケーション・モジュールに基づいたデータ・コントロールと単純なJavaBeanに基づいたデータ・コントロール、つまり2つの異なるデータ・コントロールのデータを表示します。

図16 は、JDeveloperのビジュアル・エディタでJSPページのメイン・ページがどのように表示されるかを示しています。 このページはアプリケーションのビュー層を実装しています。この後で紹介しますが、これはモデル層およびコントローラ層からはきれいに切り離されています。

showEmployees.jspページ
図 16: showEmployees.jspページ

新しいStrutsページ・フロー図を使用して、6つの異なるStrutsアクションを構築しました。データ・レンダリングのため6つともすべて最終的には同じ showEmployees.jspページに転送されます。 StrutsアプリケーションからADFバインディング・コンテナを使用するときの各種オプションを示すため、6つの異なるアクションを用意しました。これらは大きく2つのカテゴリに分類されます。

両方のアプローチに対して、更に3つのタイプの実装例を提示しています。これによって、ADF/Struts プロジェクトで何が可能なのか、今後どのアプローチがよりよいのか、の理解の助けになるかと思います。

図17は、この6つのアクションと1つのJSPページを含む、サンプル・アプリケーションの全体ページ・フローを示しています(一番上の forwardAction は、基本的に単に後続の6つのアクションにフォワードするだけです)。

サンプル・アプリケーションのStrutsページ・フロー
図 17: サンプル・アプリケーションのStrutsページ・フロー

注意:

この資料では触れていませんが、コントローラ層がないModel 1 スタイルのJSPアプリケーションからADFバインディング・コンテキストとその中のバインディング・コンテナを使用することも可能です。


図18に示されている index.htmlページは、 異なる6つのアクションのすべてを実行できるよう、リンク付きの開始ページを提供しています。これらのリンクをクリックすると、/forwardAction を経由して(図17を参照)、適切なアクションに転送されます。前半の3つの例は、ADFが提供するクラスを使用せずに、ライフサイクルをコーディングで実装しています。後半の3つの例は、同じ処理を、今度はコーディングせずにADFが提供する DataAction を利用して実施しています。この後半3つのアクションについての詳細は、この後で説明します。

サンプル用のindex.htmlページ
図 18: サンプル用のindex.htmlページ

ADF/Struts統合の基本詳細

Struts用のOracle ADFランタイム・コントローラ・サポートは、JDeveloper 9.0.3/9.0.4のBC4J/Strutsサポートとは少し異なる方法で実装されるため(BC4J/Strutsサポートの詳細については、 BC4J Toy Store Demo(英語) ホワイト・ペーパーに記載)、それらの違いを指摘しておきます。

JDeveloper 9.0.3/9.0.4では、BC4J/Strutsアプリケーションを構築する開発者は BC4JRequestProcessorというカスタマイズされた Strutsリクエスト・プロセッサを使用して、データ・バインディング・コンテキストを初期化し、適切なアプリケーション・モジュールを獲得していました。 ただし、カスタム・リクエスト・プロセッサの使用は、開発者がBC4J/StrutsとStruts Tilesまたはその他のテクノロジを統合しようとしたときに問題を生じました。

ADFでは、Struts統合は次の主要要素によって構成されています。

次のセクション以降で、ADFBindingIntroサンプル・アプリケーション内の6つのアクションを使って、これらの要素の使用方法を紹介します。

サンプルのアクションのアプローチに関する考察

次にADF/Strutsランタイム統合機能がどの部分で利用されているかに注目しながら、サンプル・アクションおよびその動作の仕組みを調べていきます。

- ADFBindingFilterのセットアップ

StrutsアクションがADFバインディング・コンテキストにアクセスできるようにするためには、 web.xml ファイル内で ADFBindingFilterを適切に設定する必要があります。これはJDeveloper設計ツールによって 自動的に 行われます。 ViewController.jpr プロジェクト内の web.xmlファイルを確認すると、以下の必須エントリを見ることができます。なお、この ADFBindingFilter に対して設定されている encoding 初期パラメータによって、リクエストで送られるデータの文字コードを指定することができます。

 
    :
<!-- ADF Binding Filter Class Setup -->
<filter>
  <filter-name>ADFBindingFilter</filter-name>
  <filter-class>oracle.adf.model.servlet.ADFBindingFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>Shift_JIS</param-value>
  </init-param>
</filter>
<!-- 
  |  ADF Binding Filter Setup to engage the filter when
  |  the Struts "action" servlet is used.
  +-->
<filter-mapping>
  <filter-name>ADFBindingFilter</filter-name>
  <servlet-name>action</servlet-name>
</filter-mapping>
    :
<!-- Servlet setup for the Struts action servlet -->
<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    :
</servlet>
<!-- Servlet setup to map *.do URL's to the Struts action servlet -->
<servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>
    :

ADFBindingFilterは、このアプリケーションのバインディング・コンテキスト定義として使用するcpxファイルを決めるために、 CpxFileName というサーブレット・コンテキスト・パラメータの値を調べます。 このサンプル・アプリケーションの場合は、 web.xmlファイル内に以下の行が見つかります。

 
<context-param>
  <param-name>CpxFileName</param-name>
  <param-value>DataBindings</param-value>
</context-param>

これは、 DataBindings.cpxファイルを読み込んでバインディング・コンテキストの内容を検出することを意味します。

- アクションに対するバインディング・コンテナの指定

アクションによって使用されるADFバインディング・コンテナの名前を宣言的に設定できるようにするために、アクションに対して(classNameによって) DataActionMapping実装クラスを使用するように指定し、子タグとして <set-property>タグを追加して modelReferenceプロパティに値を割り当てます。 modelReferenceの値は、 DataBindings.cpxファイル内にリストされているバインディング・コンテナの1つの短縮名でなければなりません。 必要なのは短縮名だけです。 バインディング・コンテナが最初に使用されるときに、そのファイルの完全パッケージ修飾名がバインディング・コンテキストから検索されます。

以下は struts-config.xml ファイル内の"/showEmpsActionCentric" アクションの設定部分で、sample.controller.ShowEmpsActionCentricAction アクション・クラスによって実装されています。

 
<action path="/showEmpsActionCentric"
        type="sample.controller.ShowEmpsActionCentricAction"
        className="oracle.adf.controller.struts.actions.DataActionMapping"
        name="DataForm">
  <set-property property="modelReference"
                value="showEmployeesUIModel"/>
  <forward path="/showEmployees.jsp" name="success"/>
</action>
- バインディング・コンテナへのアクセス

アクション用のバインディング・コンテナにアクセスする場合は、次のようなコードを使用できます。

 
/**
 * Setup the binding container for use. Name of the binding container
 * to use is gotten from the modelReference property on the Struts
 * action mapping (through the extended DataActionMapping in the
 * oracle.adf.controller.struts.actions package).
 */
private void initializeBindingContainer(ActionMapping mapping,
             HttpServletRequest request) {
  if (mapping instanceof DataActionMapping) {
    DataActionMapping daMapping = (DataActionMapping)mapping;
    String bindingContainerName = daMapping.getModelReference();
    DCBindingContainer bc = getBindingContainer(request);
    if (bc == null) {
      BindingContext ctx = HttpBindingContext.getContext(request);
      bc = DCUtil.findBindingContainer(ctx, bindingContainerName);
      if (bc != null) {
        /*
         * Put a reference to the binding container under the
         * request-scoped attribute named "bindings" so JSP pages
         * can easily refer to bindings in the binding container
         * using EL expressions like ${bindings.Empno}
         */
        request.setAttribute(BINDINGS, bc);
      }
    }
  }
}

コードは、アクションから modelReferenceプロパティを参照し、 getBindingContainer()ヘルパー・メソッドを使用してバインディング・コンテナがこのリクエスト中にすでにセットアップ済みかどうかを調べます。 セットアップ済みでなければ、ビュー層のページが${bindings.BindingName}のようなEL(式言語)を使用してバインディング・コンテナにアクセスできるように、 DCUtil.findBindingContainer()を呼び出して" bindings"属性をリクエスト・スコープ内にセットします。

- データ・コントロールのアクセス

バインディング・コンテナがあれば、その中に含まれているバインディングをどれでも見つけることができます。 バインディング・コンテナに含まれるデータ・コントロールはイテレータ・バインディング経由でアクセス可能です。 また、より明示的に、名前でバインディング・コンテキストから見つけ出すこともできます。次のサンプル・コードは、データ・コントロールを名前で見つけ出し、それがある実装クラスのタイプであるかどうか(この例の場合は、ADFアプリケーション・モジュールに基づくデータ・コントロールであるかどうか)を判別し、そのインターフェースを返す方法を示しています。

 
protected ApplicationModule getApplicationModule(String dataControlName,
                                                 HttpServletRequest request) {
  DCDataControl dc = HttpBindingContext.getContext(request).findDataControl(dataControlName);
  /*
   * Test to see if our data control is an instance of the ADF Business Components
   * Data Control before trying to cast the data provider to a specific
   * service interface
   */
  if (dc instanceof DCJboDataControl) {
    return (ApplicationModule) dc.getDataProvider();
  }
  return null;
}
- 基本ADFアクション・ライフサイクルのセットアップ

HTTPリクエストの受け渡しライフサイクルの基本手順は次のとおりです。

  1. バインディング・コンテナの初期化
  2. カスタム・コントローラの処理と ActionForwardの決定
  3. バインディング・コンテナの解放

手動コーディングのアクションのすべてはこの方法に準ずる必要があり、そのサンプルとして、デフォルトのStruts Action#execute()メソッドをオーバーライドしてこの基本ライフサイクルを定義する BasicADFActionクラスを作成してあります。

 
public final ActionForward execute(ActionMapping mapping, ActionForm form,
             HttpServletRequest request, HttpServletResponse response)
             throws Exception {
  return handleLifecycle(mapping, form, request, response);
}

ここでは、execute()final で宣言して、このサブクラスが必ずライフサイクル処理をとおるようにしています。この中でよばれる handleLifecycle メソッドは次のようなコードです。

 
protected ActionForward handleLifecycle(ActionMapping mapping, ActionForm form,
             HttpServletRequest request, HttpServletResponse response)
             throws Exception {
  initializeBindingContainer(mapping,request);
  ActionForward fwd = performActionLogic(mapping,form,request,response);
  refreshBindingContainer(request);
  return fwd;
}

3つのカスタム・アクション

は、必要なカスタム・コントローラ処理を提供するために BasicADFActionを拡張して、handleLifecycle 内から呼ばれる performActionLogic() メソッドをオーバーライドしています。

- アクションへのコントローラ・コードの記述例

このデモで実装する基本機能は、従業員(Employees)データ一覧を順序付けて表示することです。 sortという名前のHTTPパラメータの値がない場合または文字 "a"に等しい場合、昇順ソートを実行します。 sortパラメータの値が文字 "d"に等しい場合は、降順ソートを実行します。

ShowEmpsActionCentricActionは、JDeveloperリリース9.0.3/9.0.4を使用している開発者がよく知っている方法でこの機能を実現する方法を示しています。

 
public class ShowEmpsActionCentricAction extends BasicADFAction  {
  protected ActionForward performActionLogic(ActionMapping mapping, ActionForm form,
         HttpServletRequest request, HttpServletResponse response)
         throws Exception {
    ApplicationModule am = getApplicationModule("EmpServiceDataControl", request);
    ViewObject vo = am.findViewObject("Employees");
    String sortDirection = request.getParameter("sort");
    if (sortDirection == null || sortDirection.equals("a")) {
      vo.setOrderByClause("sal asc");
    }
    else {
      vo.setOrderByClause("sal desc");
    }
    vo.executeQuery();
    return mapping.findForward("success");
  }
}

このアクション・コードは(BasicADFActionから継承された適切なヘルバー・メソッドを使用して) アプリケーション・モジュールを見つけ出し、"Employees"というインスタンス名を持つビュー・オブジェクトのORDER BY句の設定に進みます。

カスタム・メソッドによるモデル・データのセットアップ

一般に、アクションを実行するサーバーとは別のリモート・サーバーでバックエンド・ビジネス・サービスが実行される場合、それに対する多数のメソッド呼び出しをするような、ネットワーク経由での「おしゃべり」をできるだけ避けるように注意する必要があります。このため、ADFアプリケーション・モジュールにはカスタム・サービス・メソッドのクライアントへの公開をサポートしています。カスタム・メソッドの中ですべてのモデル情報の変更操作を行うことにより、バックエンド・ビジネス・サービスがあるリモート・サーバーへの呼び出しは一度のラウンドトリップで実施できます。 ShowEmpsTypesafeActionは、アプリケーション・モジュールのカスタム・メソッドprepareModelForShowEmployeesPageを起動する ShowEmpsTypesafeActionの改良形です。

 
public class ShowEmpsTypesafeAction extends BasicADFAction  {
  protected ActionForward performActionLogic(ActionMapping mapping, ActionForm form,
         HttpServletRequest request, HttpServletResponse response)
         throws Exception {
    /*
     * "EmpService" is the custom business service interface created by
     * the ADF Business Components wizard when you mark a custom method
     * like "prepareModelForShowEmployeesPage" as exported to the client.
     */
    EmpService svc = (EmpService)getApplicationModule("EmpServiceDataControl", request);
    svc.prepareModelForShowEmployeesPage(request.getParameter("sort"));
    return mapping.findForward("success"); 
  }
}
コントローラとサービスとを分離させるアクション・バインディング

ADFのバインディング機能の一つにアクション・バインディングというものがあります。これは、クライアント層と、データ・コントロールのサービス・メソッドの間を緩衝材のような役割をはたします。データ・コントロールのサービス・メソッドを直接クライアントから呼ぶのではなく、それらを切り離して、代わりにアクション・バインディングを使用することが可能です。アクション・バインディングは、実行時にメタ・データから実際のメソッドの情報を取得し、それを起動します(必要ならばパラメータを受け渡します)。そして、その結果を取得します。

ShowEmpsActionBindingAction のコードでは、以下のように、サービスのメソッド起動のためにアクション・バインディングを使用しています。

 
public class ShowEmpsActionBindingAction extends BasicADFAction {
  protected ActionForward performActionLogic(ActionMapping mapping, ActionForm form,
         HttpServletRequest request, HttpServletResponse response)
  throws Exception {
    invokeActionBinding("prepareModelForShowEmployeesPage",
                        request.getParameter("sort"), request);
    return mapping.findForward("success");
  }
}

この中で呼び出されている invokeActionBinding メソッドは、ベースである BasicADFAction に用意されています。 invokeActionBinding を見ると、メソッドに対して受け渡すべきパラメータを ArrayList にして提供していることがわかります。この例では、起動されるメソッドの戻り値はない(void)ので、何もせずにその後の処理に進んでいますが、戻り値が期待される場合には、アクション・バインディング・オブジェクトに対する getResult() を使って取得可能です。

フル・ライフサイクル・サポートのためのDataActionの機能の使用

"/showEmployeesTypesafe"という名前のサンプル内の4つ目のStrutsアクションは、手動コーディングによるアクション・アプローチの代わりに汎用ADF DataActionの機能を使用して実装されます。 DataActionは、上の BasicADFAction内に用意した基本的なロジックに加えて、さらに完全なリクエスト処理ライフサイクルを実装しています。 構造的にBasicADFActionに似たアプローチを使用して、DataActionベース・クラス( oracle.adf.controller.struts.action パッケージ)はベースStrutsアクションの execute() メソッドをオーバーライドし、いくつかのライフサイクル・メソッドを呼び出して、すべてのリクエストで必要な共通手順を施行します。

DataActionによるライフサイクル処理は次のとおりです。

このサンプルでは、CustomizedDataAction という、 DataAction を拡張したクラスを用意して、先ほど紹介した BasicDataAction と同様、invokeActionBinding というメソッドを用意しています。 ShowEmployeesActionBindingAction はこの CustomizedDataAction の拡張クラスで、prepareModel という(DataActionの)メソッドをオーバーライドしています。

 
public class ShowEmployeesActionBindingAction extends CustomizedDataAction {
  protected void prepareModel(DataActionContext ctx) throws Exception {
    invokeActionBinding("prepareModelForShowEmployeesPage",
      ctx.getHttpServletRequest().getParameter("sort"), ctx);
    super.prepareModel(ctx);
  }
}

ADF DataAction では、ライフサイクル期間内の多くの情報の受け渡しを効率化するために、DataActionContext というオブジェクトを利用するよう設計されています。このオブジェクトは、現行のHTTPリクエストの処理中のみ存在し、データ・アクションに渡すべきものにアクセス可能なsetXXX/getXXX メソッドを含んでいます。上記のコード内では、getHttpServletRequest() でHTTPリクエスト・オブジェクトにアクセスし、sort パタメータの値を取得しています。 他にも、DataActionContext には、getBindingContext()getBindingContainer() といった有用なメソッドや、次のどこを進むべきかを決定できるように Struts の ActionForward を設定したり、Struts のエラー出力などに関連する情報を設定するためのメソッドも用意されています。

手動コーディングで実装した例と、DataAction を利用する例との一番の違いは、DataAction を利用すれば、コードを書く手間が大きく軽減されるという点でしょう。この機能豊富なベース実装が提供されているため、開発者は、地道なリクエスト処理のためのコーディングを省略して、アプリケーションで必要なコードだけのために Struts の標準的な Action の拡張/オーバーライドをすればよいことになります。

ページフロー・ダイアグラムを簡略化するDataPage

Strutsアクションは、一般に以下のケースで使用されます。

Webページのデザイン・パターンのひとつで、「ポストバック」と呼ばれるものがあります。これは、ひとつのページに対するデータの初期化ロジックとページ・イベント処理を同じアクションで処理する手法です。 Oracle ADFの DataForwardActionDataActionの拡張クラス)は、このパターンに従い、それによって、ページフロー・ダイアグラムを簡略化します。

DataForwardAction は、ADF DataAction のライフサイクル処理機能と Struts ForwardActionの暗黙的なページ転送が合わさった形のものです。デザイン上、DataForwardAction は常にページ表示のために特定のページに転送し、そのページでは、ページ・イベントの処理のために同じアクション(DataForwardAction)に戻って送られる(ポストバックする)よう、フォームやリンクが設定されます。 JDeveloper のページフロー・ダイアグラムでは、このようなアクションとページの対を "DataPage" アイコンで表現しています。

図19のように、DataPageのアイコン上にマウスをポイントすると、アクション・クラス名と関連ページが表示されます。 この方法を用いると、サンプル内の /showEmployeesTypesafe アクションは、これまでに紹介したアクションと同じ "/showEmployees.jsp" への転送を暗黙的に実施しているのがわかります。

DataPageに対するアクションとページ情報のツールチップ表示
図 19: DataPageに対するアクションとページ情報のツールチップ表示

注意:

Struts ForwardActionと同じように、DataPageに対するページ・パスがStrutsアクション・マッピングのプロパティのひとつとして記述されます。これは、struts-config.xmlでは次のようになります。

 
  <action path="/showEmployeesTypesafe"
          className="oracle.adf.controller.struts.actions.DataActionMapping"
          type="sample.controller.ShowEmployeesTypesafeAction"
          name="DataForm"
          parameter="/showEmployees.jsp">
    <set-property property="modelReference" value="showEmployeesUIModel"/>
  </action>

以下のコードでわかるように、ShowEmployeesTypesafeAction クラスはDataForwardActionを使用して定義されており、データ・コントロールのサービス・メソッドを呼ぶという、すでに説明済みの手法( ShowEmpsTypesafeAction と同じアプローチ)を使用しています。

 
public class ShowEmployeesTypesafeAction extends DataForwardAction {
  protected void prepareModel(DataActionContext ctx) throws Exception {
    /*
     * "EmpService" is the custom business service interface created by
     * the ADF Business Components wizard when you mark a custom method
     * like "prepareModelForShowEmployeesPage" as exported to the client.
     */
    EmpService svc = (EmpService)ctx.getBindingContext()
                                    .findDataControl("EmpServiceDataControl")
                                    .getDataProvider();
    svc.prepareModelForShowEmployeesPage(ctx.getHttpServletRequest().getParameter("sort"));
    super.prepareModel(ctx);
  }
DataAction 機能をフル活用した宣言的手法

最後の例である /showEmployeesDeclarative アクションについて説明します。この DataPage は、これまでにみたアクションと同じ機能を実現しますが、そのためにカスタム・コードを一切必要としません。DataActionDataForwardAction (DataPage を表すアクション)は、データ・コントロールのメソッド機能を宣言的に設定可能なように設計されています。

これまでに /showEmpsActionBinding/showEmployeesActionBinding の例で見てきたように、ADF アクション・バインディング によって、 データ・コントロールのメソッドへの相互作用はカプセル化されます。メソッド起動の仕組みを完全に宣言的に設定可能なように、DataAction は次のような追加機能を実装しています。

では、ここで、/showEmployeesDeclarative データ・アクションによって施行されるメソッド起動の設定について説明しましょう。 EmpServiceDataControl データ・コントロールの prepareModelForShowEmployeesPage メソッドをデータ・コントロール・パレットからドラッグして、ページ・フロー図の"/showEmployeesDaclarative" データ・アクションにドロップすると、JDeveloper設計ツールによって struts-config.xml ファイル内に必要なプロパティが自動的にセットアップされるため、DataActionが実行時に prepareModelForShowEmployeesPageメソッドを呼び出すことができるようになります。 上で見た modelReferenceプロパティのほか、下の <action>エントリからわかるように、 methodNameresultLocationnumParamsおよび paramNames[0]などの追加プロパティがあります。 numParamsの値は、 prepareModelForShowEmployeesPageメソッドが1つの引数を受け付け、そのメソッドがフレームワークによって呼び出されたときに paramNames[0]プロパティがそのプロパティの値を評価するEL表現を提供することを示しています。 式 ${param.sort}は、 sortという名前のHTTPリクエスト・パラメータを参照するための標準のEL構文です。

 
<action path="/showEmployeesDaclarative"
        className="oracle.adf.controller.struts.actions.DataActionMapping"
        name="DataForm" 
        parameter="/showEmployees.jsp"
        type="oracle.adf.controller.struts.actions.DataForwardAction">
   <set-property property="modelReference" 
                 value="showEmployeesUIModel"/>
   <set-property property="methodName"
                 value="showEmployeesUIModel.prepareModelForShowEmployeesPage"/>
   <set-property property="resultLocation"
                 value="${requestScope.methodResult}"/>
   <set-property property="numParams"
                 value="1"/>
   <set-property property="paramNames[0]"
                 value="${param.sort}"/>
</action>

/showEmployeesDaclarative用のコントローラ・コードを何も作成しなくても、モデルに対して準備作業を行うためにデータ・コントロール・メソッドが呼び出され、レンダリングのために制御をshowEmployees.jspページに転送すべくデフォルトの「success」への転送が戻される結果になります。

注意:

この例であげたメソッド prepareModelForShowEmployeesPage は戻り値がない(void)ものでしたが、戻り値があって、その値を使ってデータ表示が行われるようなケースでは、通常、DataAction でメソッド起動の処理を行い、その結果を DataPage に転送するような構成をとることが推奨されています。

DataActionライフサイクルの各種のメソッドを理解するため、 DataActionクラス内の executeメソッドの実装コードを調べることができます。 ADFバインディングやADF Strutsコントローラに関するソース・コードまたはJavadocに手早くジャンプするには、メイン・メニューから ナビゲートJavaクラスに移動を選択するか、ショートカット・キー [Ctrl]-Minusを押します。 図20 に示されているダイアログが表示され、 名前 フィールドにクラスの名前の入力を開始できます(クラスのパッケージ名を指定する必要はありません)。 [Enter]キーを押すと、目的のクラスのソース・コード(またはJavadoc)が開きます。

どのクラスのソースも手早く検出できる
図 20: どのクラスのソースも手早く検出可能

注意:

ADFバインディング、ADF データ・コントロールおよびADF Strutsコントローラ・サポートのソース・コードはリリースと一緒に提供されます。 便宜上、Strutsコントローラ・ソース・コードも用意されています。


EL(式言語)を使用したWebページ内のデータの参照

サンプルの showEmployees.jspページは、Beanおよびコレクションの参照用に標準 Expression Language(EL:式言語)をサポートしている JSTL "core" タグ・ライブラリ内のタグを使用できます。 たとえば式を短くするため、ページの一番上に次のようなコードがあることに気付くでしょう。

 
<%-- 
 | Capture Employees and CommissionPlans bindings
 | into variables with shorter names
 +--%>
<c:set var="e" value="${bindings.Employees}"/>
<c:set var="c" value="${bindings.availableCommissionPlans}"/>

これは、 Employeesレンジ・バインディング・オブジェクトおよびavailableCommissionPlans レンジ・バインディング・オブジェクトを表わす "e" および "c"という名前の変数を作成します。 式${bindings.Employees}は、 bindingsというオブジェクト内の Employeesというメンバー・プロパティを参照します。

BasicADFActionでは、バインディング・コンテナの検出後、リクエスト・スコープ属性に bindingsという名前でバインディング・コンテナの値をセットしたことを思い出してください。 ユーザーの代わりに DataActionが同じ属性名 bindingsを使用して、これと同じタスクを実行してくれます。 これにより、JSPページは式 ${bindings}を使用することで、バインディング・コンテナを参照できるようになります。また、ドット表記を用いて、 ${bindings.BindingName}のような記述で、バインディング・コンテナ内のどのバインディングも参照できるようになります。 <c:set>を使用して、ページ内の式 ${bindings.Employees}の値に短い変数名 "e"を割り当てることにより、長い ${bindings.Employees.labels.Ename}の代わりに以降は ${e.labels.Ename}のような式を書くこともできます。

このように、表ヘッダー内でレンジ・バインディングの labelsプロパティを参照することで、バインディング・オブジェクトの有効な情報をページから利用可能になることがわかります。 ViewController.jprファイル内の index.html ファイルをクリックして実行し、そのページ内のリンクの1つをクリックして目的のアクションを実行すると、 図21のようなページが表示されるはずです。

単なる属性名 EmpnoEnameおよび Salの代わりに"Id"、"Employee Name"および "Salary"として列タイトルが表示されることに注目してください。 これは、Empエンティティ・オブジェクトの属性に、判読可能なラベルとしてUIコントロール・ヒントを定義してあるためです。 このように、バインディングに対する labels プロパティを使用することによって、UIヒント情報の取得が可能になります。

注意:

任意のバインディングに関してEL表現経由で利用可能なすべてのプロパティを見るには、構造ペインのUIモデル タブ内のバインディングをクリックして [F1]キーを押してヘルプを表示してください。


実行時のshowEmployees.jspページ出力
図 21: 実行時のshowEmployees.jspページ出力

表のレンダリングは、JSTL <c:forEach>タグの使用によって達成されます。 たとえば従業員表の行は、次のタグでレンダリングされます。

 
<!--
  | REMEMBER that "e" is a local variable assigned to ${bindings.Employees}
  | range control binding at the top of this JSP page
  +-->
<c:forEach var="x" items="${e.rangeSet}" varStatus="idx">
  <tr class="r<c:out value='${idx.index % 2}'>" >
    <td><c:out value="${x.Empno}"/></td>
    <td><c:out value="${x.Ename}"/></td>
    <td><c:out value="${x.Sal}"/></td>
  </tr>
</c:forEach>

Employeesレンジ・バインディングの rangeSetプロパティは、ビュー・オブジェクトの現在の範囲内の行をコレクションとして公開します。 <c:forEach>タグの var="x"属性が " x"という名前のループ変数を割り当てた後、そのループ内のタグがELのドット表記を使用して各行内の属性値を参照します。また、 <c:forEach>タグ内の varStatus="idx" という属性によって、このループ内の ステータスを表す変数 " idx" が割り当てられています。JSTL仕様により、この変数の index 値によって、現在行がイテレータ内の何行目であるかを知ることができます。次のコードに注目してください:

 
<tr class="r<c:out value='${idx.index % 2}'/>">

ここでは、<tr> タグ内の class属性に対して、JSTL <c:out> タグが埋め込みの形で使用されています。idx.index 値を 2 でわったあまりが 1 であるか 0 であるか(その行が奇数番目の行か偶数番目の行か)によって、その結果適用される CSSクラスが"r1" か "r0" かに変化するようになっています。これにより、このサンプルのデータ行は、行ごとに異なるカラーで示されます。この CSSクラスは css/blaf.css スタイルシート内に定義されています。

このアプリケーションに用意されている機能を体験するため、"Salary"見出しの右にある小さい矢印をクリックして、行の昇順と降順を切り替えてみてください。 "EMP行が5行しか見えないのはなぜ?"と疑問に思うかもしれませんが簡単なことです。 showEmployees.jspページ用のUIモデル構造ペインタブの EmployeesIterイテレータ・バインディングをクリックしてプロパティ・インスペクタを見れば、"レンジ・サイズ" プロパティが5にセットされているのがわかります( 図10 )。ADFバインディングの場合、データ・バインディングのすべてのメカニズムが明確に解釈され、バインディング・コンテナ内のバインディング・メタデータに組み込まれています。 UIクライアント・ページおよびパネルは、処理対象のバインディングを参照するだけで済みます。

Tips:

さらに、DataAction は、バインディング・コンテキストを表現する data という名前の変数を自動的に公開しています。 それはつまり、${data.SomeBindingContainer.someBinding.inputValue}のようなEL表現を使用して、 バインディング・コンテキスト内の SomeBindingContainerバインディング・コンテナ内の someBinding という名前のバインディングの現在の値が参照可能なことを意味します。


ADFデータ・バインディングに関するQ & A

新しいADFデータ・バインディング機能に関する質問とその回答です。


Q: 9.0.3/9.0.4アプリケーションをアップグレードするとどうなりますか?
A:

既存のJDeveloperアプリケーションを9.0.3/9.0.4リリースからアップグレードすると、 *.jprファイルのフォーマットは若干変更されますが、既存コードに対する移行は行われません。 これは、 9.0.3/9.0.4スタイルの「アプリケーション・モジュールへのダイレクト」データ・バインディングを使用して9.0.3/9.0.4アプリケーションは動作し続けることを意味します。 データ・バインディングのこのスタイルは引き続きサポートされていますが、もちろん、ADFで提供される新しいバックエンド・サービスとの一貫した組み込み、バインディング・オブジェクトが提供しているもっとクリーンなビュー/モデル分離、JSTL/ELのシームレスな使用には対応していません。

9.0.3/9.0.4で使用していたコンポーネント・パレットとJSPタグ・インサイトは、既存アプリケーションの機能強化および拡張のため継続して使用できます。 バインディング・コンテナ、バインディング・オブジェクトおよびデータ・コントロールの機能を使用するには、新しいADFバインディング層を使い始める必要があります。

 
Q: ADFバインディングと一緒にJBO DataTagsライブラリを使用できますか?
A:

JBO DataTagsライブラリは上位互換性を維持するため、9.0.3/9.0.4スタイルの「アプリケーション・モジュールへのダイレクト」データ・バインディング・アプローチは引き続きサポートされますが、バインディング・コンテナおよびバインディング経由でADFバインディングをサポートするようには拡張されていません。

 
Q: Model 1 スタイルのJSPアプリケーション内でADFバインディングを使用できますか?
A:

もちろんできます。 ADFバインディング・アーキテクチャはコントローラ層からきれいに分離されているため、ADFバインディングをユーザーのModel 1スタイルJSPアプリケーションに組み込むことができます。 新しい <adf:uimodelreference>タグを使用すれば、Model 1 スタイルJSPページ内のバインディング・コンテナを初期化できます。 構文は次のとおりです。

 
<adf:uimodelreference model="BindingContainerName"/>

Model 1 スタイルJSPアプリケーション用のルーチンとして、UIイベントを扱うコードを(Bean内にまたはJSPページ内で直接)作成して、バインディング・コンテナ内のバインディングをプログラムによって連動させる必要があります。 ADFでは。これを簡略化させる方法を提供しています。Model 1 スタイルのJSPページ一つ一つに対して、oracle.adf.controller.lifecycle.PageLifeCycle を拡張したBean を作成し、シンプルなメソッド invokeActionBinding(ctx, "<ActionBindingName>") をコールするように on<ActionBindingName> メソッドを用意します。次に、 <adf:uimodelreference>タグのもう一つの属性である lifecycle プロパティでこのBeanを指定します。

 
<adf:uimodelreference model="BindingContainerName"
                      lifecycle="your.package.yourLifeCycleBean"/>

これにより、実行時に正しくアクションが起動されます。この方法の詳細は、 US OTNのページで紹介されています。

 
Q: GUI(JClient)アプリケーション用にもまた2つの異なるバインディング・スタイルがありますか?
A:

「はい」とも「いいえ」ともいえます。

いいえ。ADFバインディング・アーキテクチャは、JDeveloper 9.0.3/9.0.4のJClientによって使用されている既存のデータ・バインディング・アーキテクチャを一般化したものです。つまり、JClientバインディングは今や、汎用ADFバインディングの特化です。 JClientの既存のFormBinding(フォーム/パネルに関連したバインディングのコンテナ)は汎用化され、BindingContainer コンセプトに組み込まれています。 FormBindingは今ではBindingContainerのサブクラスです。

はい。9.0.3/9.0.4のJClientは、FormBindingバインディング・コンテナで定義されるバインディングの記述にXMLによる宣言的アプローチを使用していません。 バインディング・メタデータのすべては、パネルのjbInit()メソッド内のバインディング・ファクトリ・メソッド・コールに引き渡された引数の値として前もって取得されています。 ADFの宣言的アプローチも、9.0.3/9.0.4のコードによるアプローチも、両方とも、コントロール・バインディングを作成し(必要に応じてイテレータ・バインディングも作成し)、バインディングをFormBindingバインディング・コンテナに入れます。 9.0.3/9.0.4のバインディング・オブジェクト作成のスタイルは継続して利用可能ですが、新しいJClientデータ・バインディングはバインディング・コンテナが提供している一貫したメタデータ駆動のアプローチを使用してパネル用にバインディングを設定します。

 

最後に

この資料が新しいADFバインディング・アーキテクチャの機能および設計時の解明に少しでも役立つことを期待しています。