この章では、Oracle Application Development Frameworkのアーキテクチャと主要機能について説明します。特に、JDeveloper 10gリリース3(10.1.3)を使用してOracle ADF、Enterprise JavaBeans、Oracle TopLinkおよびJSFを利用するWebアプリケーションを構築する場合の典型的な開発プロセスについて説明します。
この章の内容は次のとおりです。
Oracle Application Development Framework(Oracle ADF)は、J2EE標準とオープン・ソース・テクノロジを基盤とするエンドツーエンドのアプリケーション・フレームワークであり、サービス指向アプリケーションの実装を簡略化および迅速化する目的で設計されています。Web、ワイヤレス、デスクトップ、Webサービスなどのインタフェースを使用してデータの検索、表示、作成、変更および検証を行うエンタープライズ・ソリューションを開発する場合、Oracle ADFを利用することでその作業が容易になります。Oracle JDeveloper 10gとOracle ADFを組み合せて使用すると、設計からデプロイに至る開発ライフサイクル全体に対応した環境が提供され、ドラッグ・アンド・ドロップによるデータ・バインディング、ビジュアルUI設計、チーム開発などの組込み機能を使用できます。
Oracle ADFを使用してアプリケーションを構築すると、業界のベスト・プラクティスに従うように、モデル、ビューおよびコントローラ・アーキテクチャに準拠した機能の明確な分離が実現します。図1-1は、このアーキテクチャを構成する各ADFモジュールの場所を示しています。このフレームワークのコア・モジュールは、JSR-227仕様を実装した宣言的なデータ・バインディング機能であるOracle ADF Modelです。Oracle ADF Modelレイヤーにより、統一化されたアプローチを使用して、各ユーザー・インタフェースをコード記述なしで任意のビジネス・サービスにバインドできます。Oracle ADFを構成するその他のモジュールは、次のとおりです。
Oracle ADF Controller: StrutsおよびJSFをOracle ADF Modelに統合します。
Oracle ADF Faces: JSFで構築されるWebアプリケーションにコンポーネント・ライブラリを提供します。
Oracle ADF Swing: Swingで構築されるデスクトップ・アプリケーションにOracle ADF Modelを拡張します。
Oracle ADF Business Components: Oracle Formsなどの4GLツールに精通した開発者のためにビジネス・サービスの構築作業を簡略化します。
Webユーザー・インタフェースの設計場所であるアプリケーションのビュー・レイヤーでは、従来のJavaServer Pages(JSP)または最新のJavaServer Faces(JSF)標準を使用して開発を行うことができます。または、デスクトップUIの外観や対話方式を選択し、既製のSwingコンポーネントまたはライブラリを使用して開発を行うことで、希望のルック・アンド・フィールを実現することも可能です。どの方法を選択しても、WYSIWYGベースのビジュアル・デザイナを操作して、ドラッグ・アンド・ドロップによるデータ・バインディングを実行できます。JSFが推奨される理由の1つとして、ADF Facesモジュールにより提供される100近くのJSFコンポーネントの包括的なライブラリを使用できることがあげられます。
ADF Facesコンポーネントには、ルック・アンド・フィールのスキン管理などの高度な機能や、最新のAjaxプログラミング技術の使用により変更されたページの一部のみを増分的に更新する機能などが含まれます。コンポーネント・ライブラリでは、複数のJSFレンダー・キットをサポートしているため、Webブラウザを使用するユーザーとPDA通信デバイスを使用するローミング・ユーザーの両方に対応できます。これらのコンポーネントにより、HTMLやJavaScriptを記述することなく、魅力的で高機能なWeb UIおよびワイヤレスUIを驚くほど簡単に構築できます。
Webアプリケーションのページ・フロー処理を主要機能とするコントローラ・レイヤーでは、一般的に使用されているApache StrutsフレームワークとJSFに搭載された組込みのページ・ナビゲーション機能の両方がOracle ADFと統合されています。どちらの場合でも、JDeveloperのビジュアル・ページ・フロー・ダイアグラマを使用してページ・フローを設計できます。また、ADF Controllerモジュールの適切なプラグインを使用して、ADF Modelのデータ・バインディング機能をコントローラ・レイヤーのページ処理ライフサイクルに統合できます。
モデル・レイヤーのOracle ADF Modelは、データ・コントロールと呼ばれるJSR-227のサービス抽象化機能を備えており、一般的なビジネス・サービス・テクノロジ用としてすぐに使用できるデータ・コントロール実装を提供します。どのテクノロジを採用する場合でも、JDeveloperとOracle ADFを組み合せて使用することで、ユーザー・インタフェースの作成時にドラッグ・アンド・ドロップによる宣言的なデータ・バインディング機能を使用できます。サポートされるテクノロジは、次のとおりです。
Enterprise JavaBeans(EJB)セッションBean
ほとんどのJ2EEアプリケーションではトランザクション・サービスが必要となるため、宣言的なトランザクション制御が提供されるEJBセッションBeanを選択することは適切です。ビジネス・サービス用のEJBセッションBeanファサードの背後で、Plain Old Java Objects(POJO)またはEJBエンティティBeanを使用してビジネス・ドメイン・オブジェクトを表現します。JDeveloperでは、EJBセッションBeanの作成、初期セッション・ファサード実装の生成、およびJavaクラスまたはエンティティBeanの作成を行うための統合サポートが提供されます。また、JDeveloperでOracle TopLinkを使用して、これらのクラスのオブジェクト・リレーショナル(O/R)・マッピングを構成することもできます。
JavaBeans
Javaベースのサービス・クラスも簡単に操作できます(必要に応じてOracle TopLinkのマッピング機能を利用できます)。
Webサービス
アプリケーションに必要とされるサービスが標準のWebサービス・インタフェースを公開している場合、サービス・エンドポイントに関連するWeb Services Description Language(WSDL)のURLをOracle ADFに指定するだけで、それらと対話して結果を表示するユーザー・インタフェースの構築を開始できます。
XML
XMLや、Webサービスとして公開されていないカンマ区切りの値(CSV)のデータをアプリケーションで操作する場合でも、その作業は簡単です。プロバイダURLとオプションのパラメータを指定するだけで、それらのデータを操作できます。
ADFアプリケーション・モジュール
これらのサービス・クラスは、ADF Business Componentsモジュールの機能であり、ビジネス・ルールを自動適用するSQL問合せ結果の更新可能なデータセットを公開します。
このガイドの残りの部分では、新しいWebアプリケーションを構築するJ2EE開発者に推奨されるテクノロジをOracle ADFと組み合せて使用する方法に重点を置いて説明します。これらの推奨されるテクノロジは、ビュー・レイヤーとコントローラ・レイヤーにおけるJavaServer Faces、およびビジネス・サービス実装におけるEJBセッションBeanとマップされたJavaクラスの組合せです。ただし、この章では、読者が典型的な開発プロセスに慣れるように、これらのテクノロジで構築されたごく単純なOracle ADFアプリケーションについて説明します。
注意: Oracle Forms、Oracle Designer、Visual Basic、PowerBuilderなどの4GLツールの使用経験のあるJ2EE開発者の場合は、Oracle ADF Business Componentsモジュールにより提供される追加の宣言的な開発機能を使用することをお薦めします。『Oracle Application Development Framework Forms/4GL開発者のための開発者ガイド』には、このモジュールを利用するビジネス・サービス層でOracle ADFと追加のフレームワーク機能を組み合せて使用する方法が記載されています。このガイドは、http://www.oracle.com/technology/products/adf/learnadf.html で参照できます。 |
経験豊富なJava開発者が、コードを記述せずに宣言的な開発を選択するには、確かに多少の慣れが必要です。ただし、ほとんどの開発者は、宣言的な開発が時間を節約するための有効な手段であると認めるはずです。また、開発者の大部分は、SpringやApache StrutsなどのフレームワークおよびJSP Standard Tag Library(JSTL)などのタグ・ライブラリの使用経験を通じて、宣言的な技術に触れたことがあると考えられます。JavaServer Facesには、同様の宣言的な機能が組み込まれており、Oracle ADFはその機能に宣言的なデータ・バインディングを追加することで、JavaServer Facesを補完します。
Springフレームワークを使用する場合、開発者は、オブジェクト間の依存性を宣言的に指定するBean定義XMLファイルを通じてJavaBeansのインスタンス化を構成します。汎用のフレームワーク・コードは、実行時にこのXMLファイルを読み取って指示どおりにBeanをインスタンス化し、Bean間の依存性を解決します。このデザイン・パターンは、依存性注入(DI)として一般的に知られています。Springでは、汎用的な実装を活用する宣言的な構成方法を使用して、アプリケーションのBeanを設定します。
Strutsのstruts-config.xml
ファイルを使用する場合、開発者は、アクション・ハンドラ・クラスに対するHTTPリクエストのマッピングと、その他のページ・フロー情報を構成します。汎用のStrutsフロント・コントローラ・サーブレットは、実行時にこの構成XMLファイルの情報を使用して指示どおりにリクエストをルーティングします。Strutsを使用すると、宣言的に構成されたStrutsインフラストラクチャにルーティングされるリクエストについては考慮せずに済むため、特定のリクエストを処理するための一部のコード記述に集中できます。
JSTLタグ・ライブラリを使用する場合、開発者は、次のコード例に示すとおり、宣言的な式を使用してページにモデル・データを繰り返し表示できます。
<c:when test="${not empty UserList}"> <c:forEach var="user" items="${UserList.selectedUsers}"> <tr> <td><c:out value="${user.name}"/></td> <td><c:out value="${user.email}"/> </tr> </c:forEach> </c:when>
開発者は、Javaスクリプトレット・コードとタグを雑多に組み合せてページに記述するかわりに、${not empty UserList}
、${UserList.selectedUsers}
、${user.name}
などの式をタグ属性に埋め込みます。汎用の式評価機能により、実行時にそれぞれboolean
、List
およびString
値で結果が戻されるため、コードを記述することなくBeanとそのプロパティにアクセスできます。もともとJSTLタグ・ライブラリの一部として導入されたこの宣言的な式言語(略称EL)と同じものが、改良されてJSPおよびJSF標準の現在のバージョンに組み込まれています。
JavaServer Facesでは、属性、イベント、および一貫性のある実行時APIを備えたWeb UIコンポーネントの導入により、Webユーザー・インタフェースを簡単に作成できます。扱いにくいタグやスクリプトを操作するかわりに、JSF標準に準拠したすぐに使用できるデータ認識型のコンポーネントのライブラリを使用してWebページを組み立てることが可能です。Webアプリケーション構築を簡略化するという目的を達成するため、JavaServer Faces標準を共同で設計した業界の専門家たちは、宣言的な開発技術を数多く取り入れました。実際、JSFでは、前述の3つの機能(Beanのインスタンス化と依存性注入、ページ・リクエスト処理とページ・ナビゲーション、および標準の式言語の使用)がすべてサポートされます。
JSFコンポーネントの値は、実行時にそのvalue
属性によって決定されます。コンポーネントにはその値として静的テキストを割り当てることができますが、通常、value
属性には、表示データを決定するために実行時インフラストラクチャにより評価されるEL式が含まれます。たとえば、現在ログイン中のユーザーの名前を表示するoutputText
コンポーネントには、その機能を実現するために、value
属性に#{UserInfo.name}
という式を設定できます。EL式を使用してコンポーネントの任意の属性に値を割り当てることができるため、データ駆動型の動的なユーザー・インタフェースを簡単に作成できます。たとえば、コンポーネントのrendered
属性に#{not empty UserList.selectedUsers}
などのブール値のEL式を設定すると、表示するBeanのコレクションが空のときにはそのコンポーネントを非表示にできます。UserList
というBeanの選択ユーザーのリストが空の場合、rendered
属性はfalseと評価されるため、コンポーネントはページに表示されません。
コントローラ・レイヤーのアプリケーション・ロジックの管理を容易にするため、JSFでは、Springフレームワークに似た宣言的なBean作成メカニズムを採用しています。このメカニズムを使用するには、BeanをJSFのfaces-config.xml
ファイルに構成します。これらのBeanは、EL式によって最初に参照されるときに必要に応じてJSFランタイムでそのインスタンス化が管理されるため、マネージドBeanと呼ばれます。JSFには、宣言的な依存性注入機能も含まれます。マネージドBeanには、管理プロパティを設定できますが、その実行時の値は開発者が指定したEL式に基づいてJSFランタイムにより割り当てられます。管理プロパティは、それぞれ独自の管理プロパティを持つ他のBeanに依存することもあります。この場合、関連するBeanのツリーが適切な順序で作成されることは、JSFランタイムにより保証されます。
図1-2に示すとおり、JSFのマネージドBeanには、2つの主な役割があります。
特定のページに密接に関連付けられたリクエスト・スコープのマネージドBeanは、そのプロパティやメソッドで実行時にページをサポートすることから、口語的表現でバッキングBeanと呼ばれます。ページ内のUIコンポーネントとバッキングBeanのプロパティおよびメソッド間の関係は、コンポーネントの適切な属性に含まれる次のようなEL式により決定されます。
value="#{
expr
}"
表示または変更対象のデータを保持するプロパティを参照します。
action="#{
expr
}"
イベントを処理するメソッドを参照します。
binding="#{
expr
}"
表示と非表示の切替えや色の選択など、プログラム的に操作する必要のあるUIコンポーネントの対応インスタンスを保持するプロパティを参照します。
ページのバッキングBeanの役割を果さないマネージドBeanは、単なるアプリケーション・ロジックBeanとみなされます。これらのBeanには、単一のページに限定されないコードやプロパティが含まれます。また、これらのBeanは、(この用途にかぎられませんが)単一のリクエストの範囲を超えてコントローラ・レイヤーにメソッド結果をキャッシュし、複数のページから使用できるビジネス・サービス・メソッドを一元的に事前処理または事後処理するためのビジネス・サービス・ラッパーとして機能することがあります。
JSFページのリクエスト処理に関連する標準の処理フェーズを拡張するため、マネージドBeanの使用に加え、PhaseListener
というクラスにWebアプリケーション・コードを記述することも可能です。JSFランタイムが各ページで処理するこれらの標準ステップは、ページのライフサイクルと呼ばれます。実際、ほとんどのJSFアプリケーションでは、最終的になんらかのカスタム・フェーズ・リスナーを実装してライフサイクルをカスタマイズします。特に、ページを最初に表示するときのレンダリング用モデル・データを準備するなどのタスクを実行する場合、通常はこのカスタマイズを行います。
Oracle ADF Modelレイヤーは、汎用フレームワーク機能を制御するXML構成ファイルを使用することで、他のJ2EEテクノロジと同じ宣言パターンに準拠しています。注目に値する唯一の相違点は、ADF Modelの場合、データ・バインディング・レイヤーでの値の追加に重点が置かれていることです。ADF Modelでは、ユーザー・インタフェース・テクノロジとビジネス・サービス実装の分離を可能にするJSR-227の2つの概念(データ・コントロールと宣言的バインディング)が具体化されています。
データ・コントロールは、そのpublicインタフェースを記述する標準のメタデータ・インタフェースを使用して、ビジネス・サービスの実装テクノロジを抽象化します。このインタフェースには、プロパティ、メソッドおよび関連する型についての情報が含まれます。設計時に、ビジュアル・ツールでサービス・メタデータを操作し、UIコンポーネントをデータ・コントロールのpublicメンバーに宣言的にバインドします。実行時に、汎用のOracle ADF Modelレイヤーによって、適切なXMLファイルからデータ・コントロールおよびバインディングを記述した情報が読み取られ、ユーザー・インタフェースとサービスを結合する双方向の関係が実装されます。この結合方法には、次の3つの主要なメリットがあります。
記述コードが減少するため、テストおよびデバッグする行数も減少します。
どのUIテクノロジおよびビジネス・サービス・テクノロジでも、同じように処理できます。
独自コードを記述することなく、有益な実行時機能を使用できます。
すべてのエンタープライズ・アプリケーションに必要とされるデータ・バインディングの主要な機能を自動化するバインディング・オブジェクトには、次の3つの基本的な種類があります。
通常、ハイパーリンクやボタンなどのUIコンポーネントでは、アクション・バインディングを使用します。これにより、ユーザーがコンポーネントをクリックすると、コードなしでビジネス・サービスが起動します。データを表示するUIコンポーネントでは、属性バインディングを使用します。イテレータ・バインディングを使用すると、データ・コレクションのスクロール処理やページ移動、または概要情報から詳細情報へのドリルダウンを可能にするユーザー・インタフェースを簡単に作成できます。
ページのUIコンポーネントをサポートするバインディングのグループは、ページ定義ファイルというページ固有のXMLファイルに記述されます。ADF Modelにより提供される汎用のBeanファクトリでは、このファイルを実行時に使用してページのバインディングをインスタンス化します。これらのバインディングは、各ページのリクエスト時にEL式の#{bindings}
を使用してアクセス可能なバインディング・コンテナというリクエスト・スコープのマップ内に保持されます。EL式は、常に現在のページのバインディング・コンテナに対して評価されます。図1-3は、ELの値バインディング式により、ページのUIコンポーネントがバインディング・コンテナのバインディング・オブジェクトにどのように関連付けられるかを示しています。
図1-4は、ADF Modelで宣言的なデータ・バインディングを使用する場合のJSFアプリケーションのアーキテクチャを示しています。Oracle ADF ModelとJavaServer Facesを組み合せると、実際のアプリケーションに必要とされる典型的なマネージドBeanコードを大量に記述せずに済みます。実際、組込みのアクションまたはサービス・メソッドの起動によって処理できないプログラム的なコントローラ・ロジックを実行する場合を除き、作成するほとんどのページでバッキングBeanを使用する必要はありません(コードを記述しなくともADF Modelによって自動的に処理されます)。また、ADF Modelのデータ・コントロールによって適切な機能が実装されるため、ビジネス・サービスをラップするアプリケーション・ロジックBeanも必要ありません。さらに、ADF Modelには、必要とされるほとんどの共通操作をページ定義メタデータの情報に基づいて宣言的な方法で実行する汎用のJSFフェーズ・リスナーが付属するため、通常は独自のJSFフェーズ・リスナーを記述する必要もありません。
これまでに、JSFアプリケーションに対応するADF Modelのデータ・バインディングの基礎について説明しました。次に、ADF Modelにより提供される付加価値の高い機能の全体像について説明します。次からの各項には、開発生産性を大幅に向上させる主要な機能領域の概要が含まれます。
JDeveloperによる包括的な設計時サポートには、ADF Modelの宣言的なデータ・バインディングに対応する次の機能が含まれます。
EJBセッションBean、Javaサービス・クラス、Webサービス、URLに基づくXMLまたはCSVデータ、およびADFアプリケーション・モジュールのデータ・コントロールを簡単に作成できます。追加の情報が必要とされる場合は、わかりやすいウィザードにより1つ1つの手順が示されます。
データ・コントロールとして公開されているすべてのビジネス・サービスが一覧表示されます。このパレットのサービス・プロパティ、メソッド、メソッド・パラメータおよびメソッド結果をドラッグすることで、適切にバインドされたユーザー・インタフェース要素を作成できます。読取り専用または編集可能なフォーム、表、マスター/ディテール表示、および個別にバインドされたUIコンポーネント(単一選択リストと複数選択リスト、チェック・ボックス、ラジオ・グループなど)を簡単に作成できます。検索フォーム、データ作成ページ、およびメソッド起動用のパラメータ・フォームを作成することも簡単です。他のチームのページ設計者と共同で作業している場合は、ページ内の既存のコンポーネントに属性をドロップすることで、事後的にそれらの属性をバインドできます。UIコンポーネントが作成されるだけでなく、強力なUNDO機能をサポートするページ定義ファイルに適切な宣言的バインディングが自動的に作成および構成されるため、バインディングとUIコンポーネントの同期を維持しながらユーザー・インタフェースを繰り返しテストして改良できます。
構造ウィンドウにページ定義メタデータが一覧表示されます。これにより、適切なエディタまたはプロパティ・インスペクタを使用して宣言的なバインディング・プロパティを構成できます。目的の構造にバインディングを挿入することで、新規バインディングを作成できます。
構造および有効な値に関してコンテキストに依存するXMLスキーマ駆動型の支援機能を使用して、バインディング・メタデータを編集できます。構造ウィンドウにページ定義メタデータが一覧表示されます。これにより、適切なエディタまたはプロパティ・インスペクタを使用して宣言的なバインディング・プロパティを構成できます。
JSFの参照実装では、基本のHTML入力フィールド・タイプと単純な表の表示機能が組み込まれたUIコンポーネントの最小限のセットが提供されますが、これらは実際のアプリケーションを構築するには不十分です。ADF Modelレイヤーには、Oracle ADF Facesライブラリの高性能なUIコンポーネントと連携して、エンド・ユーザーに必要とされるリッチな機能を迅速に導入できる次のようないくつかの機能が実装されています。
高機能な表モデル
表は、エンタープライズ・アプリケーションのUIにおける重要な要素です。JSFのデフォルトでは、表のページ移動やソート処理はサポートされません。ADF Facesの表とADF Modelの表バインディングを組み合せると、任意の列に基づいてソートできるページ移動可能な表、編集可能な表または読取り専用の表を表示できます。
キーに基づく現在の選択の追跡
Webユーザー・インタフェースにおける最も一般的なタスクの1つは、情報のリストを表示して、ユーザーがそのリストをスクロールできるように、またはリスト内の1つ以上のエントリを選択できるようにすることです。ADF Modelのイテレータ・バインディングにより、効果的な方法で簡単に選択行を追跡できます。この方法では、データがリフレッシュされて位置が変化すると変更される可能性のある位置インジケータのかわりに、行キーが使用されます。この行キーをADF Facesの表および複数選択コンポーネントと組み合せることで、単一または複数の選択を操作することや、マスター/ディテール情報をナビゲートする画面を作成することが容易になります。
宣言的な階層ツリー・コンポーネントおよびグリッド
エンタープライズ・アプリケーションの大部分の情報は階層的ですが、JSFのデフォルトでは階層的なデータの表示や操作がサポートされません。ADF Modelレイヤーでは、宣言的に構成してADF Facesツリーまたは階層的なグリッド・コンポーネントと組み合せて使用できる階層バインディングが提供されるため、最も直感的な形式でユーザーにデータを表示することが可能な対話型のユーザー・インタフェースを実装できます。
共通のUIコンポーネント用の柔軟性に富んだモデル
チェック・ボックスなどの単純なコンポーネントにも、改良の余地があります。JSFのデフォルトでは、チェック・ボックスのバインディングがブール型プロパティに制限されます。ADF Modelでは、データが提供可能なtrue値または有効値の任意の組合せに対してチェック・ボックスをマップできます。ADF Modelが威力を発揮するもう1つの領域に、リスト・コンポーネントがあります。リストの有効な値は、データ・コントロール内の任意のデータ・コレクションから取得できます。また、必要に応じて、リストを更新することや行ナビゲーションに使用することが可能です。ADF Modelのリスト・バインディングでは、変換可能な「<選択なし>」をオプションでリストに追加することにより、NULL値も簡単に処理できます。
ADF Modelでは、複数のアプリケーション機能の再利用性を向上するために、レイヤー化されたメタデータを、情報を表示するページで再利用可能なデータ・コントロールの構造定義に関連付けることができます。ADF Modelにより再利用可能となる機能の例は、次のとおりです。
翻訳可能なプロンプト、ツールチップおよびフォーマット・マスク
JSFでは、リソース・バンドルで翻訳可能な文字列を参照する単純なメカニズムがサポートされますが、文字列の用途は考慮されず、特定のビジネス・ドメイン・オブジェクトに文字列を関連付ける方法も提供されていません。ADF Modelでは、翻訳可能なプロンプト、ツールチップおよびフォーマット・マスクを、データ・コントロールのサービス・インタフェースで使用される任意のデータ型の属性に関連付けることができるため、属性のデータを含むすべてのページで、ロケールに依存した一貫性のある方法に従ってそれらのデータを表示できます。
宣言的な検証
JSFでは、UIコンポーネントに関連付けることのできるバリデータがサポートされますが、同じビジネス・ドメイン・データが使用されるすべての画面で、一貫性のある方法によりそれらのデータを簡単に検証するメカニズムは提供されていません。ADF Modelでは、バリデータ・オブジェクトの拡張可能セットをデータ・コントロールの構造定義メタデータに関連付けることができるため、オブジェクト・データの入力または変更に使用されるページとは無関係に、一貫性のある方法で検証を実行できます。
宣言的なセキュリティ
JSFには、認可情報をUIコンポーネントと統合するためのメカニズムはありません。ADF Modelでは、ユーザーまたはロール認可情報をデータ・コントロールの構造定義メタデータに含まれる各属性に関連付けることができるため、参照する権限のあるユーザーにのみ一貫性のある方法でページの情報を表示できます。
JSFでは、ページ処理のライフサイクルが厳密に定義されていますが、一部のごく一般的なタスクに対しても独自のフェーズ・リスナーにコードを記述し、それを実装する必要があります。さらに、JSF仕様の将来のバージョンでは、フェーズ・リスナーが事実上グローバル対応となるため、特定のページに対してのみ機能を適用する場合は、現在のページの名前に基づいた条件コードを記述する必要があります。ADF ModelレイヤーとADF Controllerレイヤーを組み合せると、通常であればカスタム・フェーズ・リスナーにコードを記述する必要のあるごく一般的な機能に関して、次のようなページ単位の制御を簡単に実行できます。
宣言的なメソッド起動
EL式に基づいてパラメータを渡すことでビジネス・サービスのメソッド起動を構成し、メソッド結果をバインドすることができます。このとき、データの不要な再問合せを避けるため、メソッド・パラメータが変更されるまで結果をキャッシュするオプションを使用できます。リンクやボタンなどのコマンド・コンポーネントが押されたときにメソッドを起動するか、JSFライフサイクルの適切なフェーズにメソッドが自動的に起動されるようページ定義を構成することが可能です。
宣言的なページ・ライフサイクル制御
特定のJSFライフサイクル・フェーズ中にデータをリフレッシュするようイテレータ・バインディングを宣言的に構成し、そのリフレッシュの発生するタイミングをより詳細に制御するための条件EL式を(オプションで)指定できます。自動メソッド起動によるメソッドの実行タイミングの指定にも同じ制御方法を使用できます。
エラー・レポートの一元管理
ページごとにではなく、単一の場所でアプリケーションのエラー・レポート方法をカスタマイズできます。
この項では、読者がJavaServer Facesを使用したOracle ADFアプリケーション構築の典型的な開発プロセスに慣れるように、簡単な例を取り上げて説明します。この項の情報は、Oracle ADFを使用したJ2EEアプリケーション構築の基本ワークフローの概要を示す目的で記述されています。
ここで取り上げる例は、高度に簡略化されたバージョンのサービス・リクエスト追跡システム(SRDemoサンプル)に基づきます。これは、このガイドの残りの部分で使用されている実用的なサンプル・アプリケーションです。サービス・リクエスト追跡システムでは、外部ユーザーが、購入した製品の技術的なサポートを求めるリクエストを記録します。内部ユーザーは、自分が専門とする領域で顧客をサポートします。この概要では、基礎的な内容に重点を置いて説明し、ユーザーとその専門技術領域に関連するシステム機能の一部について検討します。
ここでは、図1-5のような単純なJSFページを作成する場合の手順について説明します。このページで、エンド・ユーザーは、ユーザーを名前別に参照して結果をスクロールし、表示されたユーザーごとにその専門技術領域を確認できます。
新規アプリケーションを作成する最初の手順は、アプリケーションに名前を割り当て、そのソース・ファイルを保存するディレクトリを指定することです。JDeveloperの「新規ギャラリ」で「アプリケーション」を選択すると、図1-6に示された「アプリケーションの作成」ダイアログが表示されます。このダイアログで、アプリケーション名の指定、作業ディレクトリの設定、およびアプリケーションで作成するクラスのパッケージ接頭辞の指定を行います。この例では、パッケージ接頭辞としてoracle.srdemo
と入力するため、デフォルトですべてのクラスがoracle.srdemo.*
で始まる名前を持つパッケージ内に作成されます。JSF、EJBおよびTopLinkを使用してWebアプリケーションを作成するため、図1-6には、対応するアプリケーション・テンプレートがリストから選択されて表示されています。このアプリケーション・テンプレートは、アプリケーションの各レイヤーを構築するための適切なテクノロジを選択して、ModelおよびViewControllerという名前の個別プロジェクトを作成するよう構成されています。
一般的には、最初にビジネス・サービス・インタフェースを作成します(デフォルトでは、Modelというプロジェクト内で作成します)。Modelプロジェクトは、サービス・ファサードとして機能するEJB 3.0セッションBeanと、操作する必要のあるビジネス・ドメイン・オブジェクトを表すJavaクラスで構成されます。モデル部分は、後続のUI開発の手順に進むうえで機能的に完成している必要はありませんが、サービス・インタフェースを定義することにより、ビュー・レイヤーが必要とするデータと、作業を完了するためにサービス・メソッドにパラメータとして渡す必要のある情報について必然的に検討することになります。ユーザーと専門技術領域を操作するため、User
およびExpertiseArea
という名前のJavaクラスを作成します。各クラスには、ユーザーと専門技術領域を表現するのに必要なデータに対応するプロパティが含まれます。
要件によれば、ビジネス・サービスでは、名前によるユーザー検索をサポートする必要があります。このため、EJBセッションBeanウィザードにより、コンテナ管理のトランザクションを使用するEJB 3.0ステートレス・セッションBeanを作成します。次に、name
というパラメータとして一致パターンを取得するfindUsersByName()
というメソッドをローカル・インタフェースに追加します。結果の型と明確にやり取りし、コンパイル時の型チェックで可能なかぎり最良の結果を得るためには、メソッドの戻り型をList<User>
(User Beanの強く型付けされたリスト)として宣言するのがベスト・プラクティスです。最後に、サービス・インタフェースを実装するSRServiceBean
クラスにメソッドを記述します。図1-7は、JDeveloperのJavaクラス図に示されるサービスとそのクラスを示しています。クラスには、必要に応じてすべてのユーザーを戻す便利なfindAllUsers()
メソッドも含まれます。
ADF Modelでは、サービスとユーザー・インタフェースが明確に分離されるため、ページ作成の残りの手順は、その実装ではなくサービス・インタフェースにのみ依存します。最初は静的なテスト・データを戻すサービスから開始し、最終的にはUser
およびExpertiseArea
クラスをデータベースの適切な表にマップします。これは、Oracle TopLinkが威力を発揮する分野であり、JDeveloperによってTopLinkのセッションとマッピングの構成が一元的にサポートされるため、この作業は迅速に完了できます。すでに現在のクラスと同様の構造を持つデータベース表が存在する場合は、Oracle TopLinkを使用してその表にクラスを自動マップし、後から必要に応じて結果を調整できます。データベース表がまだ存在しない場合は、JDeveloperのデータベース・ダイアグラマを使用して、適切な表を設計してからマッピング操作を実行できます。findUsersByName()
メソッドを実装するには、User
マッピング・ディスクリプタの一部として名前付き問合せを作成し、パラメータとして渡された名前と一致するユーザーを取得するのに必要な条件を指定します。実行時に、Oracle TopLinkランタイムにより、XML駆動型のO/Rマッピング情報に基づいてデータベースからパラメータ付き問合せの結果が取得されます。
ビジネス・サービスを準備したら、ユーザー・インタフェースの作成を開始します。ビジネス・サービスでドラッグ・アンド・ドロップによるデータ・バインディングを可能にするための最初の手順は、ビジネス・サービスのデータ・コントロールを作成することです。データ・コントロールを作成することで、JSR-227サービスと構造記述を使用するOracle ADF Modelの設計時の残りの手順用に、サービス・インタフェースを公開します。データ・コントロールを作成するには、SRServiceBean
クラスをJDeveloperのデータ・コントロール・パレットにドラッグします。図1-8は、この操作後のデータ・コントロール・パレットを示しています。すべてのサービス・メソッド、適切なパラメータ、およびメソッドの戻り型が反映されていることがわかります。findUsersByName()
メソッドの場合、適切なパラメータはname
であることと、戻り型にUser
型のBeanが含まれていることを確認できます。ユーザーのネストされたプロパティとして、email
、lastName
およびexpertiseAreas
も表示されています。expertiseAreas
は、コレクション型のプロパティ(List<ExpertiseArea>
型)であるため、その下にさらにネストされたプロパティがあります。図で閉じられている「操作」フォルダには、ADF Modelレイヤーでサポートされるコレクションに対する組込みの操作(「前へ」、「次へ」、「先頭へ」、「最後へ」など)が含まれます。
アプリケーションの作成時に、サービス・インタフェースに別のメソッドを追加した場合や既存のメソッドを変更した場合は、データ・コントロール・パレットにSRServiceBean
クラスを再度ドラッグ・アンド・ドロップするだけで済みます。これにより、パレット(およびその基礎となるデータ・バインディング・メタデータ)は、最新の変更を反映するように更新されます。データ・コントロールの構成情報は、DataControls.dcx
というXMLファイルに格納されます。このファイルは、最初のデータ・コントロールを作成したときに、JDeveloperによってModel
プロジェクトに追加されます。複数のデータ・コントロールを作成する場合、データ・コントロールの種類(EJB、JavaBean、XML、Webサービスなど)や実行時のデータ・コントロールの構成方法に関する情報は、このファイルに保存されます。また、JDeveloperでは、サービス・インタフェースに関連するデータ型ごとに、そのデータ型の名前と同じ名前のXML構造定義ファイルが作成されます。EJBサービス・インタフェースの場合、サービス・クラスそれ自体に対して1つと、サービス・インタフェースのメソッド戻り値またはメソッド引数として出現するJavaBeanごとに1つの構造定義ファイルが作成されます。
これらの構造定義ファイルにより、データ・コントロール・パレットの表示が制御され、宣言的なモデル・レイヤーの機能(バリデータ、プロンプト、ツールチップ、フォーマット・マスク、宣言的なセキュリティなど)を使用する際の動作が決定されます。モデル・レイヤーのこれらの機能を構造定義ファイルに定義することで、これらのタイプに関連する情報が含まれるすべてのページの表示と情報検証を一貫した方法で実行できます。図1-9は、SRServiceBean
のデータ・コントロールの作成後にアプリケーション・ナビゲータのModel
プロジェクトに表示されるすべてのファイルを示しています。
データ・コントロールを作成したら、ドラッグ・アンド・ドロップによるデータ・バインディングを実行して、ページを作成します。このページではADF Facesコンポーネントを使用するため、最初にそれらのコンポーネントを使用するようプロジェクトのタグ・ライブラリが構成されていることを確認します。アプリケーション・ナビゲータのViewControllerプロジェクトをダブルクリックすると、「プロジェクト・プロパティ」ダイアログが表示されます。このダイアログの「JSPタグ・ライブラリ」ページで、構成されているライブラリを確認できます。「ADF Faces Components」ライブラリと「ADF Faces HTML」ライブラリが含まれていない場合は、このページで追加します。図1-10は、ViewControllerプロジェクトの補足ライブラリを含む「プロジェクト・プロパティ」ダイアログを示しています。
次に、JSF JSPの作成ウィザードを使用して、browseusers.jspx
というページを作成します。*.jsp
拡張子を持つJSPページの操作に慣れている読者が多いと思われますが、そのかわりに標準のXMLベースのJSPドキュメントを使用することは、次の理由からJSF開発のベスト・プラクティスとなります。
UIコンポーネント・タグの整形式のツリーとしてページを簡単に処理できます。
Javaコードとコンポーネント・タグの混同を回避できます。
ドキュメントや監査レポートの作成のためにページを簡単に解析できます。
JSF JSPの作成ウィザードが完了すると、JDeveloperのビジュアル・エディタに新規ページが開かれます。このページでは、図1-11のように、ドラッグ・アンド・ドロップするだけでデータがバインドされたページを作成できます。データ・コントロール・パレットからページに各要素をドロップすると、その要素に対して作成できるUI要素の適切なオプションを示すポップアップ・メニューが表示されます。
このページを作成する基本手順は、次のとおりです。
コンポーネント・パレットの「ADF Faces Core」ページからpanelFormコンポーネントをページにドロップし、プロパティ・インスペクタでそのテキスト属性を「Browse Users and Expertise Areas」に設定します。
データ・コントロール・パレットからfindUsersByName()メソッドをドロップし、ADFパラメータ・フォームを作成します。この操作により、name
パラメータの値を収集するためのラベル、フィールドおよびボタンを格納するpanelForm
コンポーネントが作成されます(ボタンがクリックされると、メソッドにパラメータの値が渡されます)。
データ・コントロール・パレットからfindUsersByName()ノードのUser戻り値をドロップし、ADF読取り専用フォームを作成します。この操作により、User Beanのプロパティのラベルとフィールドを格納するpanelForm
コンポーネントが作成されます。
データ・コントロール・パレットにあるUser戻り値の「操作」フォルダを開き、組込みの「前へ」操作を共通ボタンとしてページにドロップします。続けて、このボタンの右に「次へ」ボタンをドロップします。
データ・コントロール・パレットのUser戻り値内部にネストされたexpertiseAreasプロパティをADF読取り専用表としてドロップします。表示される「表の列の編集」ダイアログで「ソートの有効化」を選択し、列ヘッダーをクリックすることでデータをソートできるよう設定します。
ページは、いつでも実行またはデバッグして、作成したユーザー・インタフェースをテストできます。
データ・コントロール・パレットからデータ・バインドされたコンポーネントが最初にページにドロップされたときに、JDeveloperによりそのコンポーネントのページ定義ファイルが作成されます。図1-12は、構造ウィンドウのbrowseusersPageDef.xml
ファイルの内容を示しています。同じ名前のサービス・メソッドを起動するために、findUsersByName
というアクション・バインディングが作成されます。サービス・メソッドから戻されるUser
BeanのコレクションとExpertiseArea
Beanのネストされたコレクションを処理するために、findUsersByNameIter
およびexpertiseAreasIterator
というイテレータ・バインディングが作成されます。また、ドロップされたボタンをサポートするために、Next
およびPrevious
というアクション・バインディングが作成されます。最後に、読取り専用のoutputText
フィールドおよび表をサポートするために、適切な名前の属性バインディングが作成されます。
Oracle ADF Modelのデータ・バインディングをプロジェクトで最初に実行したときに、JDeveloperによりDataBindings.cpx
という追加のXMLファイルが1つ作成されます。このファイルには、ページ名とページ定義名のマッピングに関する情報が格納され、プロジェクトで使用中のデータ・コントロールがリストされます。図1-13は、構造ウィンドウに表示されたDataBindings.cpx
ファイルを示しています。このファイルは、実行時にOracle ADF Modelのバインディング・コンテキスト全体を作成するために使用されます。また、このファイルのページ・マップ情報とページ定義情報は、ユーザーがアクセスしたアプリケーション・ページで必要とされたときに、そのページのバインディング・コンテナをインスタンス化するために使用されます。
注意: DataControls.dcx 、DataBindings.cpx およびPageDef.xml メタデータ・ファイルの構造および内容の詳細は、付録A「ADF XMLファイルのリファレンス」を参照してください。 |
ドラッグ・アンド・ドロップによるデータ・バインディング操作を実行すると、JDeveloperにより、必要なADF Modelのバインディング・メタデータがページ定義に作成され、目的のJSFコンポーネントが生成されます。重要なのは、コンポーネントの様々なプロパティが構成されてバインディングを参照するEL式の値が割り当てられ、コンポーネントとバインディング定義が結び付けられることです。図1-14は、ページのコンポーネントが、実行時にそのページのバインディング・コンテナからバインディングを参照する仕組みを示しています。
簡単な例として、「前へ」ボタンを検討します。この組込み操作をボタンとしてドロップすると、Previous
というアクション・バインディングがページ定義ファイルに作成され、commandButton
コンポーネントの2つのプロパティが次のように設定されます。
actionListener="#{bindings.Previous.execute}"
disabled="#{!bindings.Previous.enabled}"
これら2つのEL式により、組込みのPrevious
操作を起動する動作と、Previous
操作が無意味なとき(ユーザーがコレクションの最初の行に移動しているときなど)にボタンを自動的に無効化する動作が、ボタンと結び付けられます。
ページ内の別の例として、ユーザーの電子メールを表示する読取り専用のoutputText
フィールドなどを検討すると、そのバインディングを参照するためにコンポーネントに次のプロパティが設定されていることがわかります。
value="#{bindings.email.inputValue}"
label="#{bindings.email.label}"
これら2つのバインディング属性設定の組合せに基づいて、コンポーネントでは、その値をemail
バインディングから取得し、表示ラベルとしてemail
バインディングのlabel
プロパティを使用します。Model
プロジェクトのUser
およびExpertiseArea
Beanにカスタム・プロンプトを構成済であれば、バインディングを使用して実行時にその情報を公開することで、ページのコンポーネントからそのプロンプトを汎用的な方法で参照できます。
前述のドラッグ・アンド・ドロップによるデータ・バインディングの手順では、ページ上に現在のレコードを表示する方法(「N of M」など)について説明していませんでした。表示行の現在のレンジ、レンジ内の開始行、およびコレクションの合計行数に関する情報は、イテレータ・バインディングで参照できる有益なプロパティです。この表示を作成するには、コンポーネント・パレットから3つのoutputText
コンポーネントをドロップし、それぞれのvalue
属性に適切な式を設定するだけで済みます。最初のコンポーネントでは、findUsersByName
メソッドから戻される結果のレンジ内における現在の行番号を表示するため、そのvalue
属性には、findUsersByNameIter
バインディングの(ゼロ・ベースの)rangeStart
プロパティを参照するEL式を設定する必要があります。
#{bindings.findUsersByNameIter.rangeStart + 1}
2番目のoutputText
コンポーネントでは、ofという語のみを表示するため、そのvalue
プロパティに文字列定数のof
を設定するだけで十分です。3番目のoutputText
コンポーネントでは、コレクションの合計行数を表示する必要があります。この場合、estimatedRowCount
というイテレータ・バインディングの属性に対する参照を使用します。
ページ定義でバインディングのプロパティを参照または設定する場合、ページのポップアップ・メニューで「ページ定義に移動」を選択します。たとえば、各イテレータ・バインディングでページごとに表示される行数を変更するには、このメニューを使用してRangeSize
プロパティを設定します。図1-14の例では、ページ定義の参照後に、プロパティ・インスペクタを使用してfindUsersByNameIter
イテレータ・バインディングのRangeSize
を1
に、expertiseAreasIterator
の同じプロパティを2
に設定してあります。各イテレータのRangeSize
プロパティを設定すると、ページ上に1人のユーザーと2つの専門技術領域が同時に表示されます。
Oracle ADF Modelの基礎を理解するうえで最後の課題となるのは、データ・コントロールと宣言的なバインディングが、作成済のXML構成ファイルに基づいて実行時にどのように作成されるかを把握することです。Oracle ADFのデータ・バインディングを操作するためのプロジェクト構成の一環として、JDeveloperでは、ViewController
プロジェクトのweb.xml
ファイルにADFBindingFilter
というサーブレット・フィルタが登録されます。このフィルタは、デフォルトで*.jsp
および*.jspx
というパターンに一致するURLにマップされます。
このADFBindingFilter
サーブレット・フィルタは、web.xml
ファイルの情報に基づいてDataBindings.cpx
ファイルを検出し、ADFバインディング・コンテキストを作成します。このバインディング・コンテキストは、すべてのバインディング・コンテナ、データ・コントロール、およびページ名とページ定義ファイルのマッピングが格納されたマップです。これらのデータは、アプリケーションで#{data}
というEL式を使用することでいつでも参照できます。また、このバインディング・コンテキストは、エラー・ハンドラの一元的な登録場所であり、カスタム・エラー・ハンドラを必要に応じて設定するためのAPI(および他の多くの有益なAPI)の提供場所でもあります。
ページ・リクエストが受信されると、アプリケーションによってJSFライフサイクルとADFライフサイクルの両方が起動されます。具体的には、ADFライフサイクルの実行中、ページ・リクエストを処理するためにバインディングが初めて必要になったときに、ADFPhaseListener
という別のオブジェクトによってバインディング・コンテナのバインディングとデータ・コントロールが遅延インスタンス化されます。ADFPhaseListener
は、バインディング・コンテキストのページ・マップ情報を参照して、それぞれのページで使用するバインディング・コンテナを決定します。また、DataControls.dcx
ファイルの情報を参照して、使用するデータ・コントロール・ファクトリを決定します。各リクエストにおいて、リクエスト対象となっている現在のページのバインディング・コンテナは、#{bindings}
というEL式を使用することで参照できます。図1-15は、これらのメタデータ・ファイル間の関係を示しています。
特定のページにバインディング・コンテナが設定されると、ADFPhaseListener
により、JSFページ処理ライフサイクルとバインディングが結合されます。このとき、適切なページ定義ファイルの情報に基づいて、イテレータおよびサービス・メソッドのページ単位での実行が調整されます。このため、イテレータとメソッド起動のバインディングは、実行可能バインディングと呼ばれます。
基本的なページ作業に慣れたら、ページのいくつかの部分に手を加えて機能性を向上することも可能です。たとえば、ADFバインディングのプロパティを使用して、コンポーネント・グループの表示と非表示を切り替えることや、コンポーネントの代替セットを交互に入れ替えることができます。
アプリケーション・ユーザーが1人のユーザーと一致する名前をbrowseusers.jspx
ページに入力したときに、無効化された「次へ」および「前へ」ナビゲーション・ボタンや「1 of 1」というレコード・カウンタが表示されると、見た目があまりよくありません。かわりに、図1-16のように、単一行のみが戻された場合はこれらのコンポーネントを非表示にできます。
実際、このような動作とすることは簡単です。まず、ナビゲーション・ボタンとレコード・カウンタ表示をpanelHorizontal
などの格納型のパネル・コンポーネントに配置します。これらを格納するパネルを作成したら、ビジュアル・エディタまたは構造ウィンドウでドラッグ・アンド・ドロップを実行し、もう1つのコンテナの内部に既存のコントロールを配置します。次に、パネル内のすべてのコンポーネントの表示と非表示を切り替えるため、パネルのrendered
属性の値にデータ駆動型のEL式を設定します。
前述したとおり、イテレータ・バインディングのコレクションの行数は、そのestimatedRowCount
プロパティを使用して取得できます。図1-17は、EL選択ダイアログを示しています。このダイアログを表示するには、panelHorizontal
コンポーネントを選択してからプロパティ・インスペクタでrendered
属性をクリックし、「...」ボタンをクリックします。現在のページのバインディングを開いて、findUsersByNameIter
イテレータ・バインディングを表示します。さらにこのバインディングを開いて、開発者がELで参照できる最も一般的なプロパティを表示します。estimatedRowCount
を選択して「>」ボタンをクリックし、行数が1より大きいかどうかを比較する比較演算子を挿入することで、この式をブール式に変更します。この式を設定すると、結果の行数が2以上の場合にのみ、実行時にパネルがレンダリングされます。
サンプル・ページの別の使用例を検討してみます。行が戻されなかった場合、読取り専用フォームのデフォルトでは、通常はデータ値が表示される空白領域の横にプロンプトが表示されます。また、専門技術領域の表には、列ヘッダーと「No rows yet」という語を含む空白行が表示されます。アプリケーションの機能性を多少向上する目的で、イテレータ・バインディングの結果コレクションで行が戻されなかった場合に、このデフォルトとは異なる文字を表示できます。たとえば、図1-18のように「No matches. Try again」という簡単なメッセージを表示できます。
JSFには、実行時に一定の方法でレンダリングされるコンポーネントの1つ以上の名前付き論理グループを、他のUIコンポーネントに格納できるようにするファセットという基本機能があります。ADF Facesには、実行時にレンダリングするファセットを決定するために独自のFacetName
属性でEL式を評価できる便利なswitcher
コンポーネントが付属しています。このコンポーネントを効果的に使用すると、動的かつ宣言的な方法でコンポーネントの任意のグループを交互に切り替えることができます。ユーザー情報と専門技術領域の表を表示するコンポーネントを1つのパネルにグループ化している場合、switcher
コンポーネントを使用して、戻された行数に応じてパネルと簡単なメッセージの表示を切り替えることができます。
図1-19は、switcher
コンポーネント挿入後のJSFコンポーネントの階層状態を反映したbrowseusers.jsp
ページの構造ウィンドウを示しています。まず、2つのJSFファセットを設定し、それぞれにfound
およびnotfound
などのわかりやすい名前を付けます。次に、構造ウィンドウでドラッグ・アンド・ドロップを使用し、適切なファセットに既存のコンポーネントを組み入れます。found
ファセットには、ユーザーと専門技術領域の情報を表示するすべてのコンポーネントを格納したパネルを組み入れます。notfound
ファセットには、「No matches. Try again」というメッセージを表示するoutputText
コンポーネントのみを組み入れます。
switcher
のfacetName
属性に次のEL式を設定することで、行数が0より大きい場合にはfound
ファセットが使用され、0と等しい場合にはnotfound
ファセットが使用されます。
#{bindings.findUsersByNameIter.estimatedRowCount > 0 ?'found':'notfound'}
Oracle ADFの宣言的なバインディング、ADF FacesコンポーネントおよびEL式の組合せにより、以前であれば面倒で反復の多いコードを記述していた処理にも簡単に対応できます。
これで、Oracle ADFを使用したJ2EEアプリケーション構築の概要説明を終了します。このガイドの残りの部分では、Oracle ADF、EJBおよびJSFを使用して実用的なサンプル・アプリケーションを作成する方法を詳細に説明します。