Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド 11gリリース1 (11.1.1.7.0) B52028-05 |
|
前 |
次 |
この章では、JDBCデータソースから導出されたOracle ADFアプリケーションのデータ・モデルをカプセル化するADFアプリケーション・モジュールの作成方法について説明します。この章では、ビジネス・サービス・メソッドをそのデータ・モデルと結合して完全なビジネス・サービスを実装する方法についても説明します。
この章の内容は次のとおりです。
アプリケーション・モジュールは、エンド・ユーザー・タスクに関連する論理作業ユニットのビジネス・サービス・メソッドおよびUIアウェアなデータ・モデルをカプセル化するADFビジネス・コンポーネントのコンポーネントです。
アプリケーション開発の早期段階では、アーキテクトと設計者は通常、UMLユースケース手法およびADFタスク・フローを使用して、アプリケーションの計画済エンド・ユーザー機能の高レベルな概要を作成します。この設計段階中に識別されるエンド・ユーザーの高レベルな各ユースケースは、一般に次のものに応じて異なります。
対象となるドメイン・ビジネス・オブジェクト。ユースケースに関連するコア・ビジネス・データについての問題に解答します。
必要なビジネス・データのユーザー指向ビュー。ユースケースをサポートするために必要な列サブセット、フィルタ処理された行セット、ソート方法、グループ化方法などについての問題に解答します。
各ユースケースに関連するドメイン・オブジェクトを識別すると、ビジネス・ドメイン・レイヤー内の必要なエンティティ・オブジェクトを識別する際に便利です。必要なビジネス・データのユーザー指向ビューは、ビュー・オブジェクトとして取得された適切なSQL問合せを定義して、データをエンド・ユーザーの期待どおりに取得する際に便利です。これには、パフォーマンスを最大化するために、ユースケースのサポートに必要な最低限の詳細の取得が含まれます。これまでの説明で、ビュー・オブジェクト問合せおよびビュー基準を利用してデータを形成する方法のみならず、ビュー・リンクを使用してデータ・モデルに自然なマスター/ディテール階層を設定し、期待どおりのエンド・ユーザー体験をユーザーに提供してユースケースを実現する方法も、すでに学習しました。
アプリケーション・モジュールは、当該のユースケースに必要な再使用可能なビュー・オブジェクトのインスタンスを含む作業ユニット・コンテナです。これらのビュー・オブジェクト・インスタンスは、エンド・ユーザー・ユースケースにより表示または変更する情報が決定される再使用可能なビジネス・ドメイン・レイヤー内の基礎となるエンティティ・オブジェクトに、メタデータを通じて関連付けられています。
この章では、図9-1に示す次の概念について説明します。
ビュー・オブジェクトのインスタンスをアプリケーション・モジュールで公開して、そのデータ・モデルを定義します。
サービス・メソッドを記述して、タスク・レベルのビジネス・ロジックをカプセル化します。
UIクライアントがコールするメソッドを選択し、クライアント・インタフェースで公開します。
アプリケーション統合シナリオでプログラム的に使用するメソッドを選択し、サービス・インタフェースで公開します。
リリース11.1.1.7.0以降、他のアプリケーションで使用できるようにサービス・メソッドを公開するためのベスト・プラクティスは、第11章「サービス対応アプリケーション・モジュールの統合」で説明しているように、Webサービスを作成することです。以前のリリースでは、アプリケーション・モジュールに対する概要エディタでEJBセッションBeanを使用してサービス・メソッドを公開することがサポートされていました。ADFビジネス・コンポーネント・アプリケーション・モジュールからのEJBセッションBeanの作成に対するこの設計時サポートは、後方互換性のためにのみ維持されています。これは構成可能なオプションで、「プリファレンス」ダイアログの「ADFビジネス・コンポーネント」→「アプリケーション・モジュール」ページで有効にする必要があります。
複数のWebページまたはビューにまたがる論理トランザクションでは、プールからのアプリケーション・モジュール・インスタンスを使用します。
アプリケーション・モジュールでは、データベース接続の取得と、エンティティ・オブジェクトに行われた変更の保存またはロールバックの調整を行うTransaction
オブジェクトを操作します。
関連するSession
オブジェクトにより、現在のアプリケーション・ユーザーに関するランタイム情報が提供されます。
大規模なアプリケーションでは、通常、粒度の粗い各エンド・ユーザー・タスクをサポートするアプリケーション・モジュールを1つずつ作成します。小規模なアプリケーションでは、アプリケーション・モジュールを1つ作成すれば、アプリケーションの全機能のニーズを十分に処理できると判断する場合もあります。9.4項「ネストされたアプリケーション・モジュールの定義」には、これに関する追加の説明があります。
作成するビュー・オブジェクトは、1つ以上のアプリケーション・モジュールで使用できる再利用可能コンポーネントです。各ビュー・オブジェクトは、そのアプリケーション・モジュールのトランザクションのコンテキストで、カプセル化した問合せを実行します。アプリケーション・モジュールで使用される一連のビュー・オブジェクト・インスタンスは、それ自体のデータ・モデル、つまり、クライアントがユーザー・インタフェースを介して表示および操作できる一連のデータを定義します。
既存のADFビジネス・コンポーネント・プロジェクトにアプリケーション・モジュールを追加するには、「新規ギャラリ」から使用できるアプリケーション・モジュールの作成ウィザードを使用します。
作業を始める前に、次のようにします。
5.2.1項「エンティティ・ベースのビュー・オブジェクトの作成方法」および5.2.3項「エキスパート・モードの読取り専用ビュー・オブジェクトの作成方法」に従って、該当するビュー・オブジェクトを作成します。
アプリケーション・モジュールを手動で作成するには:
アプリケーション・ナビゲータで、アプリケーション・モジュールを作成するプロジェクトを右クリックし、「新規」を選択します。
「新規ギャラリ」で、「ビジネス層」を展開し、「ADFビジネス・コンポーネント」、「アプリケーション・モジュール」の順に選択して、「OK」をクリックします。
アプリケーション・モジュールの作成ウィザードの「名前」ページで、パッケージ名およびアプリケーション・モジュール名を指定します。「次へ」をクリックします。
注意: Fusion Webアプリケーションでは、アプリケーション・モジュールの名前に予約語の |
「データ・モデル」ページで、以前に定義したビュー・オブジェクトのインスタンスを指定し、これらのビュー・オブジェクト・インスタンスの名前を、「データ・コントロール」パネルでクライアントに対して表示される名前とまったく同じ名前に編集します。次に、「次へ」をクリックします。
「Java」ページではオプションでJavaファイルを作成し、アプリケーション・モジュールの動作をプログラミングによってカスタマイズすることができます。あるいは、アプリケーション・モジュールのクライアント・インタフェースにメソッドをエクスポートして、クライアントが呼び出せるようにすることができます。XML専用のアプリケーション・モジュール・コンポーネントを生成するには、このフィールドを選択しないまま、「終了」をクリックします。
最初に、アプリケーション・モジュールのXML定義コンポーネントのみを生成することもできます。ウィザードを完了した後に、プログラムによるアクセスが必要になる場合は、概要エディタを使用してアプリケーション・モジュール・クラス・ファイルを生成できます。アプリケーション・モジュールのプログラム的な使用の詳細は、9.7項「サービス・メソッドによるアプリケーション・モジュールのカスタマイズ」を参照してください。
手順ごとの詳細は、9.2.3.2項「アプリケーション・モジュールへのマスター/ディテール・ビュー・オブジェクト・インスタンスの追加」を参照してください。
アプリケーション・モジュールを作成すると、JDeveloperでは、その宣言的設定を表すXMLコンポーネント定義ファイルが作成され、そのパッケージの名前に対応するディレクトリに保存されます。たとえば、storefront.model
パッケージのStoreServiceAM
という名前のアプリケーション・モジュールに対しては、プロジェクトのソース・パスに./storefront/model/StoreServiceAM.xml
というXMLファイルが作成されます。このXMLファイルには、ビュー・オブジェクト・インスタンスをアプリケーション・モジュールのデータ・モデルで再作成するために実行時に必要な情報が含まれています。
この内容を確認するには、アプリケーション・ナビゲータでアプリケーション・モジュールのノードをダブルクリックして概要エディタを開き、アプリケーション・モジュールのXMLファイルを確認します。エディタ・ウィンドウで「ソース」タブをクリックすると、XMLファイルが表示され、その内容を確認できます。構造ウィンドウには、XMLファイルの構造が表示されます。
ビジネス・コンポーネントを作成すると、JDeveloperがアプリケーション・モジュールのすべての機能を含むデータ・コントロールを自動的に作成します。データ・コントロールはADFモデル抽象レイヤーで、属性、メソッド、関連する型の情報を含む補足メタデータを提供して、アプリケーション・モジュールの操作とデータ・コレクション(ビュー・オブジェクト・インスタンスの行セット)を記述します。開発者は、JDeveloperの「データ・コントロール」パネルに表示されたデータ・コントロールの表現を使用して、アプリケーション・モジュールに自動的にバインドされるUIコンポーネントを作成できます。実行時にADFモデル・レイヤーによって、適切なXMLファイルからデータ・コントロールおよびバインディングを記述したメタデータが読み取られ、ユーザー・インタフェースとビジネス・サービスの双方向の結合が実装されます。
たとえば、StoreServiceAMDataControl
アプリケーション・モジュールによりStoreFrontモジュール・アプリケーションのビジネス・サービス・レイヤーが実装されます。このデータ・モデルには、複数のマスター/ディテール階層など、多数のビュー・オブジェクト・インスタンスが含まれています。Fusion Order Demoアプリケーションのビュー・レイヤーはJSFページで構成され、このページのUIコンポーネントは、StoreServiceAMDataControl
のデータ・モデル内のビュー・オブジェクト・インスタンスのデータと、そのクライアント・インタフェース上の組込み操作およびサービス・メソッドにバインドされています。「データ・コントロール」パネルでのUI開発者向けのアプリケーション・モジュール表示方法の詳細は、12.2項「ADFデータ・コントロールでのアプリケーション・モジュールの表示」を参照してください。
アプリケーション・モジュールの作成ウィザードでアプリケーション・モジュールを作成しながらビュー・オブジェクト・インスタンスをアプリケーション・モジュールに追加することも、作成済のアプリケーション・モジュールに後で追加することもできます。
アプリケーション・モジュールの作成ウィザードの使用方法の詳細は、9.2.1項「アプリケーション・モジュールの作成方法」を参照してください。
作成済のアプリケーション・モジュールにビュー・オブジェクト・インスタンスを追加できます。ビュー・オブジェクト・インスタンスを既存のアプリケーション・モジュールへ追加したり、オプションでビュー・オブジェクト・インスタンスをカスタマイズするには、アプリケーション・モジュールの概要エディタにある「データ・モデル」ページを使用します。
作業を始める前に、次のようにします。
5.2.1項「エンティティ・ベースのビュー・オブジェクトの作成方法」および5.2.3項「エキスパート・モードの読取り専用ビュー・オブジェクトの作成方法」に従って、該当するビュー・オブジェクトを作成します。
既存のアプリケーション・モジュールにビュー・オブジェクト・インスタンスを追加するには:
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
概要エディタで、「データ・モデル」ナビゲーション・タブをクリックします。
データ・モデル・コンポーネント」ページの「ビュー・オブジェクト・インスタンス」セクションを展開し、「選択可能なビュー・オブジェクト」リストで、追加するビュー・インスタンスを選択します。
リストの下の「新規ビュー・インスタンス」フィールドに、データ・モデルに追加するビュー・オブジェクトの次のインスタンスを識別する際に使用される名前が示されます。
ビュー・オブジェクトを追加する前に名前を変更するには、「新規ビュー・インスタンス」フィールドに別の名前を入力します。
目的のビュー・オブジェクトを選択し、「データ・モデル」リストに移動します。
図9-2では、ビュー・オブジェクトAddressVO
の名前をAddress
に変更してから、「データ・モデル」リストに移動しています。
アプリケーション・モジュールの概要エディタに表示されるデータ・モデルを使用すると、プロジェクトで定義されている既存のビュー・リンクに基づいて、ビュー・インスタンスの階層を作成できます。複数のマスター/ディテールの階層レベルで構成されるビュー・リンクを定義している場合は、アプリケーションでサポートされているレベル数までマスター/ディテールのビュー・インスタンスを作成できます。
作業を始める前に、次のようにします。
5.6項「マスター/ディテール階層における複数表の使用」の説明に従って、ビュー・オブジェクト間の階層関係を作成します。
マスター/ディテールのビュー・オブジェクト・インスタンスをデータ・モデルに追加するには:
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
概要エディタで、「データ・モデル」ナビゲーション・タブをクリックします。
データ・モデル・コンポーネント」ページの「ビュー・オブジェクト・インスタンス」セクションを展開し、「データ・モデル」リストで、積極的に調整を行うマスターにするビュー・オブジェクトのインスタンスを選択します。
リスト内のマスター・ビュー・オブジェクトには、このビュー・オブジェクトにビュー・リンクがあることを示すプラス記号が表示されます。ビュー・リンクは、マスター/ディテール階層の定義に必要です。
図9-3は、選択したPersonsVO
と、「新規ビュー・インスタンス」フィールドで名前を変更したAuthenticatedUser
を示しています。
選択したマスター・ビュー・オブジェクトを「データ・モデル」リストに移動します。
図9-4は、「データ・モデル」リストに新規作成したマスター・ビュー・インスタンスAuthenticatedUser
を示しています。
「データ・モデル」リストで、新規作成したマスター・ビュー・インスタンスを選択して強調表示しておきます。これは、追加するディテール・ビュー・インスタンスのターゲットになります。次に、「選択可能なビュー・オブジェクト」リストで、マスター・ビュー・オブジェクトの下のディテール・ビュー・オブジェクトを特定して選択します。
図9-5は、マスター・ビュー・オブジェクトPersonsVO
の下にある、OrdersVO via PersonsToOrders
という名前のディテール・ビュー・オブジェクトOrdersVO
を示しています。この名前はビュー・リンクPersonsToOrders
を表し、PersonsVO
とOrdersVO
間のマスター/ディテール階層を定義します。データ・モデルに追加すると、OrdersVO
にはビュー・インスタンス名のMyOrders
が追加されることにも注意してください。
追加したマスター・インスタンスにディテール・インスタンスを追加するには、「データ・モデル」リストで選択したマスター・ビュー・インスタンスの下に、ディテール・ビュー・オブジェクトを移動します。
図9-6は、データ・モデルにAuthenticatedUser
のディテールとして新規作成したディテール・ビュー・インスタンスMyOrders
を示しています。
別の階層レベルを追加するには、手順3から6を繰り返しますが、この場合は、新しく追加したディテール・インスタンスを「データ・モデル」リストで選択してから、新しいディテール・インスタンスを移動します。このディテール・インスタンスは、前に追加したディテール・インスタンスとマスター/ディテール関係を持ちます。
図9-7では、MyOrders
(旧のOrdersVO via PersonsToOrders
)のマスターとする(その結果、MyOrderItems
(旧名はOrderItemsVO via OrdersToOrderItems
)のマスターになる)AuthenticatedUser
(旧名はPersonsVO
)インスタンスを含む、「データ・モデル」リストを示しています。
アプリケーション・モジュールの概要エディタにある、「データ・モデル・コンポーネント」ページでビュー・オブジェクト・インスタンスのカスタマイズを任意に行えます。たとえば、次のようにマスター/ディテール・ビュー・オブジェクトの関係をコントロールする属性を設定できます。
既存のアプリケーション・モジュールへ追加するビュー・オブジェクト・インスタンスをカスタマイズするには:
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
概要エディタで、「データ・モデル」ナビゲーション・タブをクリックします。
データ・モデル・コンポーネント」ページの「ビュー・オブジェクト・インスタンス」セクションを展開し、「データ・モデル」リストで、カスタマイズするビュー・オブジェクト・インスタンスを選択し、編集ボタンをクリックします。
「ビュー・インスタンスの編集」ダイアログで、次のいずれかの手順を実行し、「OK」をクリックします。
「ビュー基準」グループ・ボックスで、ビュー・オブジェクト・インスタンスに適用する1つ以上のビュー基準を選択します。選択されたビュー基準は、WHERE
句としてインスタンス問合せに追加されます。ビュー基準の定義の詳細は、5.11項「名前付きビュー基準の処理」を参照してください。
「バインド・パラメータ値」グループ・ボックスで、定義済のビュー基準を適用する際にインスタンスで使用する値を入力します。バインド変数の定義の詳細は、5.10項「バインド変数の使用」を参照してください。
図9-8は、「ビュー・インスタンスの編集」ダイアログでAuthenticatedUserByPrincipalCriteria
を選択し、AuthenticatedUser
ビューを開いた状態を示しています。実行時に、Groovy式の評価によってADFセキュリティ・コンテキストから現在のユーザーを取得することで値が提供されるので、バインド変数userPrincipal
のデフォルト値は提供されていません。プロジェクトのデータ・モデルは、PrincipalName
属性をAuthenticatedUser
ビュー使用の制御属性として使用することにより、マスター/ディテール関係を定義します。ビュー基準フィルタによって設定した制御属性により、現在のユーザーのビュー行だけを取得できます。
ビュー・オブジェクト・コンポーネントのインスタンスを追加して、アプリケーション・モジュールのデータ・モデルを定義します。図9-9は、PersonService
アプリケーション・モジュールのJDeveloperビジネス・コンポーネント・ダイアグラムを示しています。
例に示したアプリケーション・モジュールにはPersons
ビュー・オブジェクト・コンポーネントの2つのインスタンスが含まれています。 メンバー名のPersonList
と、それを区別するAnotherPersonList
です。実行時には両方のインスタンスが同一のPersonsVO
ビュー・オブジェクト・コンポーネント定義を共有します。これにより、同じ属性構造とビュー・オブジェクト動作を持つようになります。ただし、それぞれを個別に使用して異なるユーザーのデータを取得できます。たとえばWHERE
句やバインド変数の追加フィルタなど、一部の実行プロパティは2つのインスタンスで異なっている場合があります。
例9-1は、PersonService
アプリケーション・モジュールにより、アプリケーション・モジュールのメンバー・ビュー・オブジェクト・インスタンスがそのXMLコンポーネント定義ファイルで定義される様子を示しています。
新しいアプリケーション・モジュールを作成した後、「アプリケーション・モジュールの編集」ダイアログを使用してその設定を編集できます。エディタを起動するには、アプリケーション・ナビゲータのポップアップ・メニューで「開く」を選択するか、アプリケーション・モジュールをダブルクリックします。エディタの様々なページを開き、データ・モデル、ネストされたアプリケーション・モジュールの参照、Java生成の設定、クライアント・インタフェース・メソッド、実行時インスタンス化動作、およびカスタム・プロパティを調整できます。
アプリケーション・モジュール名を編集する場合、Oracle Application Development Framework (Oracle ADF)が定義している予約語以外の名前を選択してください。特に、アプリケーション・モジュールの名前に基づいてJDeveloperによって自動的に割り当てられるデータ・コントロールの使用名では、予約語は無効になります。Fusion Webアプリケーションでは、予約語はdata
、bindings
、security
およびadfContext
で構成されます。たとえば、アプリケーション・モジュールの名前にはdata
を使用しないでください。予約語と競合するIDのデータ・コントロールの使用名が作成されると、実行時にアプリケーションからデータ・コントロール・オブジェクトにアクセスできなくなる場合があり、ランタイムClassCastException
のエラーが発生することがあります。
予約語はアンダースコア(_
)文字で始まる場合が多いため、名前が競合しないように、アプリケーション・モジュール名の先頭にはアンダースコアを使用しないでください。
アプリケーション・モジュール名に予約語が含まれる場合や、予約語の大文字と小文字を変更した名前が使用されている場合は、競合は発生しません。たとえば、Product_Data
、Product_data
またはData
は、全体の名前が予約語のdata
とは一致しないため、すべて有効なアプリケーション・モジュール名です。
アプリケーション・モジュールは、「データ・コントロール」パネルにデフォルトでAppModuleName
DataControl
という名前のデータ・コントロールとして表示されます。ユーザー・インタフェース・デザイナでは、「データ・コントロール」パネルを使用して、アプリケーション・モジュールからアプリケーションのWebページにデータをバインドします。たとえば、アプリケーション・モジュールの名前がStoreServiceAM
の場合、「データ・コントロール」パネルには、StoreServiceAMDataControl
という名前のデータ・コントロールが表示されます。デフォルトのデータ・コントロール名を変更して、名前を短くしたり適切な名前を指定することもできます。
ユーザー・インタフェース・デザイナでデータ・コントロールを操作すると、アプリケーション・モジュールのデータ・コントロール名は、ユーザー・インタフェース・プロジェクトのDataBindings.cpx
ファイルおよび各データ・バインディング・ページ定義のXMLファイルに表示されます。また、アプリケーション・モジュールのサービス・インタフェースをプログラム的に操作する必要がある場合は、データ・コントロール名をコード内で参照できます。このため、アプリケーション・モジュールの名前を変更する場合は、ビュー・レイヤーを作成する前に変更する必要があります。
アプリケーション・モジュールのデータ・コントロールの詳細は、第12章「Fusion WebアプリケーションでのADFモデルの使用」を参照してください。
注意: 1つ以上のページですでに参照した後にアプリケーション・モジュールのデータ・コントロール名を変更する場合は、データ・コントロール名が参照されているページ定義ファイルと |
アプリケーション・モジュールのデータ・コントロール名を変更するには:
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
プロパティ・インスペクタを開き、「その他」セクションを展開します。
「データ・コントロール名」フィールドに、適切なデータ・コントロール名を入力します。
アプリケーション・モジュールに関する一般的な疑問は、「アプリケーション・モジュールがどの位の大きさになるのか」というものです。つまり、「エンタープライズ・アプリケーションの全データ・モデルを含む1つの大きなアプリケーション・モジュールを構築するべきなのか、小さいアプリケーション・モジュールを多数構築するべきなのか」という疑問です。答えは状況によって異なります。
一般に、アプリケーション・モジュールのサイズは、そのモジュールでの対応が想定される特定のユースケースを十分にサポートできる大きさにする必要があります。9.4項「ネストされたアプリケーション・モジュールの定義」に記載されたネスト機能を使用して、微調整したアプリケーション・モジュール・コンポーネントを集めて構築することができます。複雑なビジネス・アプリケーションのユースケースは実際には1つではないので、Oracle ADFを使用して実装された複雑なビジネス・アプリケーションは複数のアプリケーション・モジュールから構成されるのが一般的です。
実際には、希望の粒度を選択できます。たとえば、主要なユースケースが1つ、バックエンドでサポートしているユースケースが1つの小規模アプリケーションの場合、アプリケーション・モジュールを2つ作成できます。ただし、簡潔にするため、数個のビュー・オブジェクトのみを含んだ2つ目のアプリケーション・モジュールを作成するのではなく、両方のユースケースを組み合せることもできます。
アプリケーション・モジュールの設計時に、ビュー・オブジェクト・コンポーネントのインスタンスを使用してそのデータ・モデルを定義します。ユーザー・インタフェースに含まれるButton
コンポーネントの2つのインスタンスに、区別するためのmyButton
およびanotherButton
というメンバー名が付けられているように、アプリケーション・モジュールにも、Persons
ビュー・オブジェクト・コンポーネントの2つのインスタンスに、区別するためのPersonList
およびAnotherPersonList
というメンバー名が付けられています。
Java Database Connectivity (JDBC) URLまたはJDBCデータソース名を「ビジネス・コンポーネント構成の編集」ダイアログの「接続タイプ」セクションで指定して、データベース接続を使用するようにアプリケーション・モジュールを構成します。データソースは、データベース・サーバー接続をベンダーに依存しない形式でカプセル化したものです。
JDBC URLまたはJDBCデータ・ソース接続タイプを使用して、Javaが実行可能な任意のコンテキストであればどこでも、アプリケーション・モジュールを実行できます。つまり、Java Enterprise Edition (Java EE)アプリケーション・サーバー内での実行に限定されません。たとえば、ビジネス・コンポーネント・ブラウザはスタンドアロンのJavaツールで、Java EEアプリケーション・サーバー内では稼働しませんが、いずれかの接続タイプを使用してビジネス・コンポーネント・ブラウザ内でビジネス・コンポーネントのテストが行えます。
JDBCデータ・ソースは、JDBC URL接続タイプでは得られない利点を提供します。データ・ソースに基づき接続タイプを定義すると、デプロイされたアプリケーションを変更することなく、データ・ソースの再構成が行えます。データ・ソースはアプリケーション・サーバー・レベルで一元定義できますが、JDBC URL接続ではそれが行えません。アプリケーション・モジュールのデフォルト接続タイプはJDBC URLですが、「ビジネス・コンポーネント構成の編集」ダイアログで、「データベース・ナビゲータ」に表示される既存のアプリケーション・リソース接続から選択できます。
デフォルトのYourAppModuleName
Local
構成では、JDBC URL接続を使用します。これは、アプリケーション・モジュールを含むプロジェクトの「プロジェクト・プロパティ」ダイアログの「ビジネス・コンポーネント」ページに設定されている名前付きの接続の定義に基づいています。図9-10は、JDBC URL接続を使用する構成で、このセクションの表示内容を示しています。
注意: Oracle以外のJDBCドライバを使用している場合は、「ビジネス・コンポーネント構成の編集」ダイアログの「プロパティ」ページで、ドライバに適したプロパティの設定を確認し、実行時の例外を回避します。 たとえばSybase JDBCドライバを使用している場合、 |
注意: データベース接続プールの使用方法およびチューニング方法の詳細は、41.1.1.2項「データベース接続プール」および41.2.9,項「データベース接続プールのパラメータについて」を参照してください。 |
もう1つの接続タイプとして、JDBCデータ・ソースを使用できます。JDBCデータ・ソースをアプリケーション・サーバー構成情報の一部として定義すると、アプリケーション・モジュールが実行時に論理名を使用してリソースを検索します。図9-11は、JDBCデータ・ソース接続を使用した構成でのこのセクションの表示内容を示します。
例9-2は、Fusion Webアプリケーションのweb.xml
ファイルの<resource-ref>
タグを示しています。このタグでは、jdbc/FODemoDS
およびjdbc/FODemoCoreDS
という名前の2つの論理データソースを定義しています。「ビジネス・コンポーネント構成の編集」ダイアログは、「JDBCデータソース名」フィールドの接頭辞java:comp/env
の後ろにある論理接続名を参照します。たとえば同じFusion WebアプリケーションのJDBCデータ・ソース接続名として、選択可能なjava:comp/env/jdbc/FODemoDS
という値を表示します。したがって、「JDBCデータソース名」フィールドには、使用可能なすべてのアプリケーション・リソース接続名に対するJNDI名が事前に取り込まれます。
例9-2 web.xmlに定義されている論理データソース・リソース名
<!-- In web.xml --> <resource-ref> <res-ref-name>jdbc/FODemoDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> <resource-ref> <res-ref-name>jdbc/FODemoCoreDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
ターゲット・スタンドアロン・アプリケーション・サーバー上でアプリケーションを実行するために必要なグローバル・データ・ソースの接続名を指定する場合は、「JDBCデータソース名」フィールドを直接編集できます。Oracle WebLogic Serverのデプロイ時、デフォルトでは、アプリケーション固有のデータ・ソースにアプリケーションはパッケージされておらず、Oracle WebLogic Serverはjava:comp/env/jdbc/
applicationConnectName
DS
の検索によって、jdbc/
applicationConnectName
DS
という名前のグローバル・データ・ソースの検索を行うように設定されています。したがって、この規則に従うことで、アプリケーション固有のデータ・ソースを使用してアプリケーションをJDeveloperで実行する場合や、グローバル・データ・ソースを使用してデプロイ済のスタンドアロン・サーバー上で実行する場合に、単一のデータ・ソース接続名を正しく機能させることができます。
注意: 冗長なデータベースやバックエンドとしてのOracle Real Application Clusters (Oracle RAC)など、可用性の高いデータベース・システムにアクセスするようにADFアプリケーション・モジュールを構成するときは、データ・ソースのコンテナが定義されている必要があります。このシナリオでは、アプリケーションはマルチ・データ・ソースを使用します。ただし、アプリケーション・モジュールの構成の観点からは、マルチ・データ・ソースと非マルチ・データ・ソースでネーミング規則は同じになります。これによって、正しいデータ・ソースが実行時に使用されるようになります。高可用性アプリケーションに対するマルチ・データ・ソースの構成の詳細は、『Oracle Fusion Middleware高可用性ガイド』を参照してください。 |
「ビジネス・コンポーネント構成の編集」ダイアログでデータベース接続を選択すると、JDeveloperがアプリケーション・モジュールXMLコンポーネント定義に関連する./common
サブディレクトリ内の、アプリケーション・モジュールの構成ファイル、bc4j.xcfg
を更新します。このファイルは、1つのJavaパッケージ内の全アプリケーション・モジュールの構成を定義しています。たとえば、Fusion Order DemoアプリケーションのStoreFront
プロジェクトの./classes/oracle/fodemo/storefront/store/service/common
ディレクトリにあるbc4j.xcfg
ファイルを見ると、そのStoreServiceAM
アプリケーション・モジュール用に名前の付いた構成が3つあることがわかります。
bc4j.xcfg
ファイルで定義された構成により、Fusion Webアプリケーションはデプロイ済の特定のアプリケーション・モジュールとの対話が可能になります。アプリケーション・モジュールのデータベース接続の詳細に加え、bc4j.xcf
ファイルにはモジュール名に関するメタデータ情報と、アプリケーション・モジュールに対して構成された実行時パラメータが含まれています。
例9-3に、Fusion Order Demoアプリケーションのbc4j.xcfg
ファイル例を示します。StoreServiceAMLocal
およびStoreServiceAMLocalWeb
の両方の構成は、JDBCName
属性内のJDBC接続(名前はFOD
)を参照します。JDBC接続用のJDBC接続文字列はアプリケーション・ナビゲータのConnectionsフォルダで定義され、アプリケーションのconnections.xml
ファイルに格納されています。構成StoreFrontService
は、最終的にターゲット・アプリケーション・サーバー上で定義されるデータ・ソースを参照します。StoreFrontService
構成内のJDBCDataSource
属性は、アプリケーション・リソース接続名のJNDI名を、java:comp/env/jdbc/
applicationConnectName
DS
の形式で指定します。ここで、applicationConnectName
はJDeveloper(この場合はFOD
)で定義されたアプリケーション・リソース・データベース接続名です。このJNDIネーミング規則(アプリケーション固有ネームスペースjava:comp/env/jdbc/
およびDS
をアプリケーション・リソース・データベース名に付加したもの)により、デプロイされたFusion Webアプリケーションは、変更を加えなくてもグローバル・データ・ソースを使用してOracle WebLogic Server上で実行できます。グローバル・データ・ソースは通常、アプリケーション・サーバー管理者がOracle WebLogic Server管理コンソールを使用して定義します。
例9-3 bc4j.xcfgファイルのアプリケーション・モジュール・データベース構成
<BC4JConfig version="11.1" xmlns="http://xmlns.oracle.com/bc4j/configuration"> <AppModuleConfigBag ApplicationName="oracle.fodemo.storefront.store.service.StoreServiceAM"> <AppModuleConfig DeployPlatform="LOCAL" JDBCName="FOD" jbo.project="StoreFrontService" name="StoreServiceAMLocal" ApplicationName="oracle.fodemo.storefront.store.service.StoreServiceAM"> ... </AppModuleConfig> <AppModuleConfig DeployPlatform="LOCAL" JDBCName="FOD" jbo.project="StoreFrontService" name="StoreServiceAMLocalWeb" ApplicationName="oracle.fodemo.storefront.store.service.StoreServiceAM"> ... </AppModuleConfig> <AppModuleConfig name="StoreFrontService" ApplicationName="oracle.fodemo.storefront.store.service.StoreServiceAM" jbo.project="StoreFrontService" ... <Custom JDBCDataSource="java:comp/env/jdbc/FODDS"/> </AppModuleConfig> </AppModuleConfigBag> </BC4JConfig>
アプリケーション・モジュールのXMLコンポーネント定義の作成に加え、JDeveloperでは、アプリケーション・モジュールのXMLコンポーネント定義ファイルを含むディレクトリを相対位置とするcommon
という名前のサブディレクトリにあるbc4j.xcfg
ファイルにappModuleName
Local
という名前のデフォルトの構成も追加します。bc4j.xcfg
ファイルは、アプリケーション・ナビゲータには表示されません。デフォルト設定を表示したり、アプリケーション・モジュールのランタイム構成の設定を変更するには、概要エディタで構成をダブルクリックして、図9-12に示す「構成の管理」ダイアログを開きます。
アプリケーション・モジュールの構成を管理するには:
「ビジネス・コンポーネント構成の編集」ダイアログを表示するには、次のいずれかを実行します。
アプリケーション・ナビゲータで、アプリケーション・モジュールを右クリックして、「構成」を選択します。「構成の管理」ダイアログで、appModuleName
Local
という名前のデフォルトの構成を選択し、「編集」をクリックします。
アプリケーション・モジュールの概要エディタで、「構成」ナビゲーション・タブをクリックし、表示されたリストでappModuleName
Local
という名前のデフォルト構成をダブルクリックします。
「ビジネス・コンポーネント構成の編集」ダイアログで、目的の実行時プロパティを編集し、「OK」をクリックして構成の変更を保存します。
アプリケーションの開発時、多数の異なるユーザーやスキーマを切り替える場合があります。これらを切り替えるには、ビジネス・コンポーネントを含むプロジェクトの接続プロパティを変更します。実行する選択により、ユーザーのプロジェクトのbc4j.xcfg
ファイルで定義される各構成の接続名が自動的に更新されます。
アプリケーション・モジュールの構成で使用する接続を変更するには:
アプリケーション・ナビゲータで、アプリケーション・モジュールが含まれているプロジェクトを右クリックして、「プロジェクト・プロパティ」を選択します。
「プロジェクト・プロパティ」ダイアログで、「ビジネス・コンポーネント」を選択して現在のデータベース接続の詳細を表示する「ビジネス・コンポーネント」ページを表示します。
「編集」をクリックし、「データベース接続の編集」ダイアログで、適切な変更を行います。
「OK」をクリックします。
アプリケーション・モジュールでは、高レベルな機能により複数のビジネス・ワークフローに共通なサブ機能が再使用される、ユースケースのモジュール性を模倣するソフトウェア・コンポーネントを作成する機能をサポートしています。このモジュール性は、他のアプリケーション・モジュールのインスタンスを使用してアセンブルする複合アプリケーション・モジュールを定義することで実装できます。このタスクはアプリケーション・モジュールのネストと呼ばれています。つまり、アプリケーション・モジュールにはビュー・オブジェクト・インスタンスだけでなく、1つ以上の他のアプリケーション・モジュール・インスタンスを(論理的に)含めることができます。最も外側に含まれているアプリケーション・モジュールは、ルート・アプリケーション・モジュールと呼ばれています。
ネストされたアプリケーション・モジュール定義の宣言的サポートは、図9-14に示すように、アプリケーション・モジュールの概要エディタから使用できます。アプリケーション・モジュールのAPIでも、実行時のアプリケーション・モジュールのネストがサポートされています。
アプリケーション・モジュールのインスタンスを別のアプリケーションにネストするときは、ビュー・オブジェクト・インスタンスをそのデータ・モデルに集約するのみならず、そこで定義されているカスタム・サービス・メソッドも集約します。アプリケーション・モジュールのインスタンスを別のアプリケーション・モジュール内でネストまたは再利用するこの機能は、大規模で実用的なアプリケーション・システムを実装するための、ADFビジネス・コンポーネントの重要な設計要素です。
アプリケーション・モジュールがエンド・ユーザーのユースケースまたはワークフローを表していることを考えると、一部の共有のモジュール化ユースケースで必要なデータを提供するアプリケーション・モジュールを作成でき、より複雑なユースケースをサポートするように設計されている、より複雑な別のアプリケーション・モジュール内でそれらのアプリケーション・モジュールを再使用できます。たとえば、アプリケーション・モジュールStoreServiceAM
およびProductService
を作成した後に、この両方のサービスを新しいCompositeService
アプリケーション・モジュールの不可欠な部分として使用するアプリケーションの作成が必要になったとします。図9-13は、このCompositeService
がJDeveloperのビジネス・コンポーネント・ダイアグラムでどのように表示されるかを示しています。この図に示すように、CompositeService
などのアプリケーション・モジュールには、ビュー・オブジェクト・インスタンスとアプリケーション・モジュール・インスタンスの両方を含めることができます。
既存のアプリケーション・モジュールのインスタンスをネストする複合ルート・アプリケーション・モジュールを指定するには、アプリケーション・モジュールの概要エディタを使用します。(アプリケーション・モジュール・インスタンスに含まれる)ネストされたすべてのコンポーネント・インスタンスでは、それらのインスタンスを再使用するルート・アプリケーション・モジュールと同じトランザクションとエンティティ・オブジェクト・キャッシュが共有されます。
ヒント: ネストされたアプリケーション・モジュールをアプリケーションで利用する場合は、12.2.1.4項「データ・コントロール」パネルでのネストされたアプリケーション・モジュールの表示」を必ず参照してください。また、これらのモジュールを含むデータ・バインディングの実行時によく発生する問題を回避してください。 |
作業を始める前に、次のようにします。
9.2.1項「アプリケーション・モジュールの作成方法」に記載されている方法に従って、該当するアプリケーション・モジュールを作成します。
ネストされたアプリケーション・モジュールを定義するには:
アプリケーション・ナビゲータで、ルート・アプリケーション・モジュールをダブルクリックします。
概要エディタで、「データ・モデル」ナビゲーション・タブをクリックします。
データ・モデル・コンポーネント」ページの「アプリケーション・モジュール・インスタンス」セクションを展開し、「使用可能」リストで、データ・モデルに追加するアプリケーション・モジュールを選択します。
リストの下の「新規アプリケーション・モジュール・インスタンス」フィールドに、データ・モデルに追加するネストされたアプリケーション・モジュールを識別する際に使用される名前が示されます。
アプリケーション・モジュールを追加する前に名前を変更するには、「新規アプリケーション・モジュール・インスタンス」フィールドに別の名前を入力します。
目的のアプリケーション・モジュールを選択し、「選択済」リストに移動します。
図9-14では、アプリケーション・モジュールLookupServiceAM
の名前をNestedLookupServiceAM
に変更してから、「選択済」リストに移動しています。
実行時に、アプリケーションはメインの、またはルートと呼ばれている、アプリケーション・モジュールを使用します。どのアプリケーション・モジュールもルート・アプリケーション・モジュールとして使用できますが、実際には、単純なCRUDアプリケーションを作成している場合を除き、より複雑なエンド・ユーザーのユースケースに対応するアプリケーション・モジュールがルートとして使用されます。ルート・アプリケーション・モジュールに別のアプリケーション・モジュールがネストされている場合、そのモジュールはすべてルート・アプリケーション・モジュールのトランザクションに関与し、同じデータベース接続および単一のエンティティ・キャッシュ・セットを共有します。この共有は、ルート・アプリケーション・モジュールおよびそのTransaction
オブジェクトによって自動的に処理されます。
また、トランザクション境界を宣言的に管理するためADFバインド・タスク・フローを使用してアプリケーションを作成する場合、Oracle ADFフレームワークにより実行時にタスク・フローで使用されるアプリケーション・モジュールが自動的にネストされます。バインド・タスク・フローとトランザクションの詳細は、18.4項「トランザクションの管理」を参照してください。
ビジネス・サービスのデータ・モデルを開発する際、多くの場合、UMLモデルを使用して視覚化すると便利です。JDeveloperでは、他の開発者が参照できるアプリケーション・モジュール用のダイアグラムを簡単に作成できます。
また、アプリケーション・モジュールの編集、表示オプションの制御、メソッド名のフィルタ処理、関連するオブジェクトやファイルの表示、アプリケーションの公開、ビジネス・コンポーネント・ブラウザの起動など、多数のタスクをダイアグラム上で直接実行できます。
アプリケーション・モジュールのダイアグラムを作成するには、「新規ギャラリ」から使用できる「ビジネス・コンポーネント・ダイアグラムの作成」ダイアログを使用します。
アプリケーション・モジュールのダイアグラムを作成するには:
アプリケーション・ナビゲータで、ダイアグラムを作成するプロジェクトを右クリックし、「新規」をクリックします。
「新規ギャラリ」で、「ビジネス層」を展開し、「ADFビジネス・コンポーネント」を選択したら、「ビジネス・コンポーネント・ダイアグラム」を選択し、「OK」をクリックします。
「ビジネス・コンポーネントの作成」ダイアログで、ダイアグラム名と、ダイアグラムの作成先のパッケージ名を入力します。
「OK」をクリックすると、空のダイアグラムが作成され、ダイアグラマを開きます。
既存のアプリケーション・モジュールを開いているダイアグラムに追加するには、追加するモジュールをアプリケーション・ナビゲータで選択してダイアグラム画面にドロップします。
プロパティ・インスペクタを次の目的で使用します。
パッケージ名の非表示化
フォントの変更
グリッドおよび改ページの非表示化
ビュー・リンク・コネクタ上の終了名("Master
"/"Detail
")の非表示化
これらの手順の完了後、ダイアグラムは図9-15のようになります。
ビジネス・コンポーネント・ダイアグラムを作成すると、ダイアグラムが格納されているパッケージ名と一致するプロジェクトのモデル・パスのサブディレクトリに、ダイアグラムを示す.adfbc_diagram
ファイルが作成されます。
デフォルトでは、アプリケーション・ナビゲータによってプロジェクト・コンテンツ・パスの表示が統一され、ソース・パスのADFコンポーネントおよびJavaファイルがプロジェクト・モデル・パスのUMLモデル・アーティファクトと同じパッケージ・ツリーに表示されます。アプリケーション・ナビゲータの「ナビゲータの表示オプション」→「ディレクトリの表示」ツールバー・オプションを使用して、統一されたディレクトリ・ビューと、個々のプロジェクト・コンテンツのディレクトリ・パス・ビューを切り替えることができます。
ビジネス・コンポーネントのUMLダイアグラムは、アプリケーション・モジュールをダイアグラムにドロップした時点の状態を示す単なる静的な図ではありません。むしろ、UMLダイアグラムは、現在のコンポーネント定義をUMLベースでレンダリングした図であるため、常に現在の状況を示しています。UMLダイアグラムは、視覚化を可能にするのみならず、視覚的なナビゲーションおよび編集ツールでもあります。
ポップアップ・メニューから「プロパティ」を選択(またはアプリケーション・モジュールをダブルクリック)すると、任意のアプリケーション・モジュールの概要エディタを起動できます。
また、ビュー・オブジェクト・インスタンス名の変更、ビュー・オブジェクト定義をアプリケーション・ナビゲータからデータ・モデルにドロップすることによる新しいビュー・オブジェクト・インスタンスの作成、[Del]キーを押すことによるビュー・オブジェクト・インスタンスの削除など、いくつかのアプリケーション・モジュール編集タスクもダイアグラム上で直接実行できます。
注意: コンポーネントをダイアグラムから削除すると、その表示のダイアグラム画面からの削除のみが行われます。コンポーネントおよびクラスは、ファイル・システムおよびアプリケーション・ナビゲータに残ります。 |
ダイアグラムでアプリケーション・モジュールを表示後、プロパティ・インスペクタを使用してオプションを表示します。
「Display Options」カテゴリで、プロパティを次のように切り替えます。
メソッドの表示 - サービス・メソッドを表示
パッケージを表示 - パッケージ名を表示
ステレオタイプの表示 - オブジェクトの型を表示(「<<application module>>
」など)
注意: operationは、メソッドに対する汎用性の高いUML名です。 |
「Operations」カテゴリでは、ダイアグラムに求められる詳細のレベルに応じて次のプロパティを変更します。
パラメータ・スタイル
戻りタイプの表示
可視性の表示(「public」、「private」など)
図9-16のプロパティ・インスペクタの設定に示すように、デフォルトでは、アプリケーション・モジュールのすべての操作が表示されます。
ダイアグラムのコンテキスト・メニューでは、「表示モード」に対して次を選択することもできます。
圧縮 - アイコンおよび名前のみを表示
シンボル - サービス操作を表示
展開済 - 操作およびデータ・モデルを表示(デフォルト)
デフォルトでは、アプリケーション・モジュールの操作を表示すると、ダイアグラムにすべてのメソッドが表示されます。上書きされたフレームワーク・メソッドとして認識されるメソッドは、すべて<<Framework>>操作カテゴリに表示されます。他のメソッドは、<<Business>>メソッド・カテゴリに表示されます。
プロパティ・インスペクタの「操作」カテゴリにある「名前フィルタ」プロパティは、ダイアグラムでの表示が不要なメソッドのフィルタ処理に使用できる正規表現です。たとえば、「名前フィルタ」プロパティを次のように設定します。
findLoggedInUser.*|retrieveOrder.*|get.*
この場合、次のアプリケーション・モジュール・メソッドをすべてフィルタ処理できます。
findLoggedInUserByEmail
retrieveOrderById
生成されたビュー・オブジェクトのgetterメソッド全般
ダイアグラム上でアプリケーション・モジュール(またはそのデータ・モデル内の任意の個別ビュー・オブジェクト・インスタンス・セット)の選択後、「表示」→「関連する要素」をコンテキスト・メニューから選択し、ダイアグラムに関連するコンポーネントを表示できます。同様に、「表示」→「実装ファイル」を選択することで、アプリケーション・モジュールを実装するファイルをダイアグラムに含むことができます。求められる詳細のレベルがダイアグラムに追加されるまで、表示されている追加ダイアグラム要素に対して前述のオプションを繰り返し使用できます。
図9-17は、アプリケーション・モジュールの実装ファイルを表示した図を示しています。この図には、アプリケーション・モジュールの実装クラスの関連要素(StoreServiceAMImpl
)が表示されています。また、アプリケーション・モジュールと実装クラス間の依存性を示す追加の線も表示されています。特定のカスタム・インタフェースにアプリケーション・モジュール・インスタンスをキャストした場合でも、図のように表示されます。
ダイアグラムをPNG
、JPG
、SVG
または圧縮されたSVG
書式で公開するには、ダイアグラム上でポップアップ・メニューから「ダイアグラムの公開」を選択します。
Fusion Webアプリケーションとの対話中に、エンド・ユーザーには次のような状況が発生する場合があります。
同じページを複数回表示する場合に、迅速なレスポンスを期待
完了までに多数のページを表示する必要がある論理作業ユニットを実行
未保存の保留中の変更内容の部分的なロールバックの実行を要求
サーバー・ファームのアプリケーション・サーバー障害による、保存前の保留中の変更への不可抗力的な被害
アプリケーション・モジュール・プーリング機能および状態管理機能では、これらの要件に対処するスケーラブルで高パフォーマンスの実装を簡略化します。
注意: ADFバインド・タスク・フローは、トランザクションの作業ユニットを表します。タスク・フローのオプションを指定して、トランザクションの処理方法を決定できます。ADFバインド・タスク・フローの宣言的な機能の詳細は、18.4項「トランザクションの管理」を参照してください。 |
状態管理機能をシミュレートするには、アプリケーション・モジュール上の2つのビジネス・コンポーネント・ブラウザのインスタンスを起動します。
ビジネス・コンポーネント・ブラウザを使用したトランザクション状態による受動化をシミュレートするには:
ビジネス・コンポーネント・ブラウザを実行し、ビュー・オブジェクト・インスタンスをダブルクリックしてそのデータを問い合せます。
数行の属性の現在の値をメモします。
これらの属性が別々の値を持つようにこれらの行に更新します。ただし、変更はコミットしないでください。
ビジネス・コンポーネント・ブラウザのメイン・メニューから「ファイル」→「トランザクション状態の保存」を選択します。
「受動化されたトランザクション状態」ダイアログが開き、トランザクションID番号が表示されます。この番号をメモします。
ビジネス・コンポーネント・ブラウザを完全に終了します。
ビジネス・コンポーネント・ブラウザを再起動し、同じビュー・オブジェクト・インスタンスをダブルクリックしてそのデータを問い合せます。
データは変更されない点に注意してください。データから問い合せたデータは、データベースの現在の状態を示し、前述の変更は反映されていません。
ビジネス・コンポーネント・ブラウザのメイン・メニューから「ファイル」→「トランザクション状態のリストア」を選択し、ステップ4でトランザクションIDを入力します。
この時点で、保留中の変更が、変更した行に再反映されます。ここでトランザクションをコミットすると、変更内容はデータベースに永続的に保存されます。
アプリケーション・モジュールをそのビジネス・サービスとして利用するアプリケーションを作成すると、そのアプリケーションでは自動アプリケーション・モジュール・プーリング機能を使用できます。この機能では、アプリケーションに対するエンド・ユーザーの負荷(ロード)の日中の変化に応じて増減するアプリケーション・モジュール・インスタンスの構成可能なセットを管理します。アプリケーション・ユーザー・インタフェースとのエンド・ユーザーの対話に特有の思考時間の性質により、プール内のアプリケーション・モジュール・インスタンスの数は、システムを使用しているアクティブ・ユーザーの合計数より少なくなる場合があります。
図9-18に示すように、あるエンド・ユーザーがアプリケーションの複数ページを表示して論理タスクを実行する場合、各ページ・リクエストに対し、プール内のアプリケーション・モジュール・インスタンスがその1リクエストの存続時間中にプールから自動的に取得されます。リクエストの最後に、インスタンスはプールに自動的に戻され、別のユーザー・セッションで使用可能になります。エンド・ユーザーの作業をアプリケーション・サーバーの障害から保護するために、アプリケーション・モジュールでは、そのエンティティ・キャッシュ内の保留中の変更セットを示すXMLスナップショットを保存することで、その変更セットを永続ストアに格納する機能をサポートしています。スケーラビリティ上の理由から、この状態スナップショットは通常、アプリケーション・データを含むデータベース・スキーマとは別の状態管理スキーマに保存されます。
プーリング・アルゴリズムではチューニング可能な最適化が行え、特定数のアプリケーション・モジュール・インスタンスが、プールに戻された最後のユーザー・セッションとの「スティッキー」な状態を維持しようとします。最適化は保証されていませんが、ユーザーが最適化による利益を得ることができれば、システム・ローダーが許容する限り、プール内の同じアプリケーション・モジュール・インスタンスを継続的に使用します。負荷が重すぎる場合、プーリング・アルゴリズムはプール内で使用可能な任意のインスタンスを使用してユーザーのリクエストに応え、その論理作業単位の凍結スナップショットを永続ストアから再構築して、アプリケーション・モジュールの新しいインスタンスが前回途中になったところから継続できるようにします。エンド・ユーザーは変更をコミットまたはロールバックするまで、この方法で作業を継続します。
アプリケーション・モジュールはこれらの機能を使用し、完全にステートレスなアプリケーションに近い実行時パフォーマンスを実現するアーキテクチャにおいて、複数ページのワークフローを簡単に処理できる、生産性の高いステートフルなパラダイムを実現します。これらのアプリケーション・モジュール機能の詳細は第40章「アプリケーション状態管理」を、チューニング方法の詳細は第41章「アプリケーション・モジュール・プールと接続プールのチューニング」を参照してください。
アプリケーション・モジュールでは、カスタムJavaコードを必要とせずに、そのビュー・オブジェクト・インスタンスのデータ・モデルをクライアントに公開できます。このため、クライアント・コードではoracle.jbo
パッケージのApplicationModule
、ViewObject
、RowSet
およびRow
というインタフェースを使用して、データ・モデル内のビュー・オブジェクトを直接操作できます。ただし、クライアント・コードで自由にビュー・オブジェクトをプログラミングで操作できても、それが必ずしもベスト・プラクティスではありません。
ビュー・オブジェクトを操作するプログラム的なコードが完全なビジネス・サービス機能を実装するための論理的な特徴を備えている場合、アプリケーション・モジュールのJavaクラスでカスタム・メソッドを記述して、詳細をカプセル化する必要があります。これには次のコードが含まれます。
表示するデータを正しく問い合せるためのビュー・オブジェクト・プロパティの構成
集計結果を取得するための、ビュー・オブジェクト行の反復処理
1つ以上のビュー・オブジェクトに対する、複数ステップのプロシージャによるロジックの実行
これらの実装の詳細をアプリケーション・モジュール内で一元管理することで、次の利点が得られます。
コードの目的が、クライアントにより明確に伝わります。
必要に応じて、複数のクライアント・ページから同じコードを簡単にコールできます。
ビジネス・サービス機能全体の回帰テストを簡略化できます。
クライアントに影響を与えることなく、実装を改善するオプションを使用可能にできます。
ページ内での論理的ビジネス機能の宣言的起動が可能になります。
カスタム・サービス・メソッドをアプリケーション・モジュールに追加するには、まずそのカスタムJavaクラスを有効化する必要があります。IDEレベルの「ビジネス・コンポーネント」のJava生成設定で、アプリケーション・モジュール・クラスが自動的に生成されるように構成されている場合は、カスタム・クラスが発生します。アプリケーション・モジュールにカスタムJavaクラスがあるかどうかが不明な場合は、アプリケーション・ナビゲータでそのアプリケーション・モジュール・ノードの概要エディタを開きます。エディタの「Javaクラス」ページに、プロジェクトのアプリケーション・モジュール用に生成されたクラスの完全リストが表示されます。他のユーザーによりすでにファイルが作成されているため存在する場合、「Javaクラス」ページには「アプリケーション・モジュール・クラス」として特定された、リンクされたファイル名が表示されます。ソース・エディタで既存ファイルを開くには、対応するファイル名のリンクをクリックします。
図9-19に示すように、「アプリケーション・モジュール・クラスに移動」オプションのアプリケーション・モジュール・ノードのポップアップ・メニューを選択することもできます。このオプションがメニューに存在する場合、このオプションでアプリケーション・モジュールのカスタム・クラスに簡単に移動できます。メニューにオプションが表示されていない場合は、アプリケーション・モジュールは現在XML専用コンポーネントであることを意味します。
プロジェクトにJavaクラスが存在しない場合、アプリケーション・モジュールの概要エディタの「Javaクラス」ページで生成できます。
作業を始める前に、次のようにします。
9.2.1項「アプリケーション・モジュールの作成方法」に記載されている方法に従って、該当するアプリケーション・モジュールを作成します。
アプリケーション・モジュール・クラスのJavaファイルを生成するには:
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
概要エディタで、「Java」ナビゲーション・タブをクリックし、「Javaオプションの編集」ボタンをクリックします。
「Javaオプションの選択」ダイアログで、「アプリケーション・モジュール・クラスの生成」を選択します。
「OK」をクリックします。
「Javaクラス」ページに新しい.java
ファイルが表示されます。
アプリケーション・モジュールのカスタム・クラスを生成すると、JDeveloperではコンポーネントのXMLコンポーネント定義ファイルと同じディレクトリにファイルが作成されます。そのカスタムJavaファイルのデフォルト名はAppModuleName
Impl.java
になります。
アプリケーション・モジュールに対して選択したJava生成オプションは、アプリケーション・モジュールの概要エディタの「Javaクラス」ページに後でアクセスしてもそのまま反映されています。XML定義ファイルの場合と同様、このエディタでどのような変更を行っても、カスタムJavaクラスで生成されたコードは最新の状態に保たれます。後でカスタムJavaファイルが不要になった場合は、「Javaクラス」ページから「Javaオプションの選択」ダイアログを開き、「アプリケーション・モジュール・クラスの生成」の選択を解除すると、プロジェクトからカスタムJavaファイルが削除されます。
デフォルトでは、アプリケーション・モジュールのJavaクラスは、最初に有効化した際、例9-4のようになります。この内容は次のとおりです。
データ・モデル内の各ビュー・オブジェクト・インスタンス用のgetterメソッド
ビジネス・コンポーネント・ブラウザを使用してアプリケーション・モジュールのデバッグを可能にするmain()
メソッド
例9-4 デフォルトで生成されるアプリケーション・モジュールのコード
package devguide.model; import devguide.model.common.StoreServiceAM; import oracle.jbo.server.ApplicationModuleImpl; import oracle.jbo.server.ViewLinkImpl; import oracle.jbo.server.ViewObjectImpl; // --------------------------------------------------------------------- // --- File generated by Oracle ADF Business Components Design Time. // --- Custom code may be added to this class. // --- Warning: Do not modify method signatures of generated methods. // --------------------------------------------------------------------- public class StoreServiceAMImpl extends ApplicationModuleImpl { /** This is the default constructor (do not remove) */ public StoreServiceImpl() { } /** Container's getter for YourViewObjectInstance1 */ public ViewObjectImpl getYourViewObjectInstance1() { return (ViewObjectImpl)findViewObject("YourViewObjectInstance1"); } // ... Additional ViewObjectImpl getters for each view object instance // ... ViewLink getters for view link instances here }
図9-20に示すように、アプリケーション・モジュール・クラスでは、カスタム・コードを追加する前にすべてのデフォルト動作を継承するようにベースADFのApplicationModuleImpl
クラスを拡張します。
カスタム・サービス・メソッドをアプリケーション・モジュールに追加するには、アプリケーション・モジュールのカスタム・クラスに移動して、新しいメソッドのJavaコードをアプリケーション・モジュールのJava実装クラスに入力します。次のガイドラインを使用して、メソッドに適切な可視性を判断してください。
メソッドをこのコンポーネントの実装内でヘルパー・メソッドとしてのみ使用する場合は、メソッドをprivate
にします。
アプリケーション・モジュールの最終的なサブクラスでこのメソッドを起動または上書きできるようにする場合は、メソッドをprotected
にします。
クライアントによる起動を可能にする場合は、public
にする必要があります。
注意: この章の |
例9-5は、StoreServiceAM
アプリケーション・モジュールのStoreServiceAMImpl.java
クラスでのprivate retrieveOrderById()
ヘルパー・メソッドを示しています。ここでは、関連するエンティティ定義にアクセスするためにOrdersEOImpl
エンティティ・オブジェクト・クラスのstatic
getDefinition()
メソッドが使用され、注文の検索に適したKeyオブジェクトを作成するためにエンティティ・オブジェクト・クラスでcreatePrimaryKey()
メソッドが使用され、エンティティ行をエンティティ・キャッシュで検索するためにエンティティ定義でfindByPrimaryKey()
メソッドが使用されています。このメソッドからは、強く型付けされたOrdersEOImpl
クラス(OrderEO
エンティティ・オブジェクトのカスタムJavaクラス)のインスタンスが戻されます。
例9-5 カスタム・アプリケーション・モジュール・クラスのprivateヘルパー・メソッド
// In devguide.model.StoreServiceAMImpl class /* * Helper method to return a Order by Id */ private OrdersEOImpl retrieveOrderById(long orderId) { EntityDefImpl orderDef = OrdersEOImpl.getDefinitionObject(); Key orderKey = OrdersEOImpl.createPrimaryKey(new DBSequence(orderId)); return (OrdersEOImpl)orderDef.findByPrimaryKey(getDBTransaction(), orderKey); }
例9-6は、作成する製品の名前および説明をコール元が渡すことを可能にするpublic createProduct()
メソッドを示しています。ここでは、関連するエンティティ定義にアクセスするためにProductImpl
エンティティ・オブジェクト・クラスのgetDefinition()
メソッドが使用され、トランザクションをコミットする前に渡されるパラメータ値が移入されるName
およびDescription
属性を持つProductImpl
エンティティ行を新規作成するためにcreateInstance2()
メソッドが使用されています。
例9-6 カスタム・アプリケーション・モジュール・クラスのpublicメソッド
/* * Create a new Product and Return its new id */ public long createProduct(String name, String description) { EntityDefImpl productDef = ProductImpl.getDefinitionObject(); ProductImpl newProduct = (ProductImpl)productDef.createInstance2(getDBTransaction(),null); newProduct.setName(name); newProduct.setDescription(description); try { getDBTransaction().commit(); } catch (JboException ex) { getDBTransaction().rollback(); throw ex; } DBSequence newIdAssigned = newProduct.getProdId(); return newIdAssigned.getSequenceNumber().longValue(); }
カスタム・アプリケーション・モジュールのメソッドをテストする準備ができたら、JDeveloperを使用してJUnitテスト・ケースを生成できます。JUnitでは、oracle.jbo package
で使用可能な任意のプログラムのAPIを使用して、アプリケーション・モジュールの操作およびカスタム・メソッドを起動が可能です。ADFビジネス・コンポーネントでのJUnit使用の詳細は、31.10項「JUnitを使用した回帰テスト」を参照してください。
JUnitテスト・ケースの代替方法として、カスタム・アプリケーション・モジュール・メソッドをテストする一般的な方法は、簡単なテスト・ケースを作成することです。たとえば、テスト用のコードをオブジェクトに作成し、そのコードをstatic main()
メソッドに含めます。例9-7は、これから記述するサンプル・メソッドをテストするために、カスタム・アプリケーション・モジュール・クラスに追加できるサンプルのmain()
メソッドを示しています。Configuration
オブジェクトを使用して(6.4.2項「コマンドラインJavaテスト・クライアントの作成方法」を参照)、テスト用のアプリケーション・モジュールをインスタンス化および操作します。
注意:
|
例9-7のコードを見ると、これまでの例で作成した4つのメソッドを使用して次が実行されていることがわかります。
注文1011の合計を取得します。
注文1011の顧客名を取得します。
1011の注文ステータスを「CANCEL」の値に設定します。
製品名がnullの新しい製品を作成します。
製品名を付けて新しい製品を作成し、新しく割り当てた製品IDを表示します。
例9-7 カスタム・アプリケーション・モジュールを内部からテストするmainメソッドのサンプル
// Main method in StoreServiceAMImpl.java public static void main(String[] args) { String amDef = "devguide.model.StoreFrontService"; String config = "StoreServiceLocal"; /* * This is the correct way to use application custom methods * from the client, by using the application module's automatically- * maintained custom service interface. */ // 1. Acquire instance of application module, cast to client interface ApplicationModule am = Configuration.createRootApplicationModule(amDef,config); /* * NOTE: This cast to use the StoreFrontServiceImpl class is OK since this * code is inside a business tier *Impl.java file and not in a * client class that is accessing the business tier from "outside". */ StoreFrontServiceImpl service = (StoreFrontServiceImpl)am; String total = service.findOrderTotal(1011); System.out.println("Total for Order # 1011 = " + total); String customerName = service.findOrderCustomer(1011); System.out.println("Customer for Order # 1011 = " + customerName); try { service.updateOrderStatus(1011,"CANCEL"); } catch (JboException ex) { System.out.println("ERROR: "+ex.getMessage()); } long id = 0; try { id = service.createProduct(null, "NEW", "CLASS1"); } catch (JboException ex) { System.out.println("ERROR: "+ex.getMessage()); } id = service.createProduct("Canon PowerShot G9", "NEW", "CLASS1"); System.out.println("New product created successfully with id = "+id); Configuration.releaseRootApplicationModule(am,true); }
カスタム・アプリケーション・モジュール・クラスを実行すると、例9-7のmain()
メソッドがコールされ、次の出力が表示されます。
Total for Order # 1011 = 99.99 Customer for Order # 1011 = John Chen ERROR: JBO-27014: Attribute ProductName in ProductsBaseEO is required. New product created successfully with id = 133
製品名をnullとしてcreateProduct()
をコールしようとした初回の試みでは、Product
エンティティ・オブジェクトのName
属性に対する組込み必須検証が原因で例外が発生しています。
注意: カスタム・アプリケーション・モジュールに作成したカスタム・サービスをクライアント・アプリケーションを使用して起動する方法の詳細は、9.9項「UIクライアントへのカスタム・サービス・メソッドの公開」を参照してください。 |
アプリケーション・ロジックが行セットにアクセスし、プログラムによる反復を実行する場合は必ず、ユーザー・インタフェース・コンポーネントにバインドされている可能性があるので、アプリケーション・モジュールのデータ・モデル内のビュー・オブジェクト・インスタンス、またはこれらのビュー・オブジェクト・インスタンスのビュー・リンク・アクセッサ行セットを扱う際に、セカンダリ行イテレータを使用する必要があります。セカンダリ・イテレータを作成するには、作業対象の行セットに対してcreateRowSetIterator()
メソッドを使用します。使用を修了したら、行セットに対してcloseRowSetIterator()
メソッドを呼び出し、メモリーからセカンダリ・イテレータを削除する必要があります。例9-8には、プログラムによる反復のためにセカンダリ行セット・イテレータを正しく使用する典型的なアプリケーション・モジュールを示します。これは、データ・モデル内のEmpView1
ビュー・オブジェクト・インスタンスが、ユーザー・インタフェースにバインドされている(現在または後で)ために使用されます。
例9-8 アプリケーション・モジュールのカスタム・メソッドにおけるセカンダリ行セット・イテレータの使用
// Custom method in an application module implementation class public void doSomeCustomProcessing() { ViewObject vo = getEmpView1(); // create secondary row set iterator with system-assigned name RowSetIterator iter = vo.createRowSetIterator(null); while (iter.hasNext()) { Row r = iter.next(); // Do something with the current row. } // close secondary row set iterator iter.closeRowSetIterator(); }
注意: 行セットのデフォルト行セット・イテレータを使用して独自の行セットの反復を行う、ビュー・オブジェクトの実装クラス内のカスタム・コードについても同じことが推奨されます。 |
このような推奨は次の2つの重要な理由のために行っています。これを行わなかった場合、現在の行が予期せず変更された場合にエンド・ユーザーを混乱させてしまいます。また、最初または最後の行、あるいは両方の行がスキップされてしまうため、検出が難しいビジネス・ロジック・エラーが発生してしまうことがあります。
現在の行が突然変更されることでエンド・ユーザーが混乱
イテレータ・バインディングは、エンド・ユーザーが行セット内でどの行を現在行として見ているのかを判断します。プログラムによるロジックがイテレータ・バインディングと同じデフォルト行セットイテレータを使用して行セットを反復している場合、ユーザーが現在選択している行を知らない間に変更してしまい、ユーザーを混乱させてしまうことがあります。
最初または最後の行を知らない間にスキップして、検出しにくいビジネス・ロジック・エラーを誘発
イテレータ・バインディングでは、行セット・イテレータを有効な行に強制的に配置して、行セットが空の場合に、UIコンポーネントがデータを表示できるようにします。これによってカスタム・ロジックが、最初の行の前のスロット、または最後の行の後ろのスロットに移動するのを防止する効果があります(イテレータ・バインディングと同じ行セット・イテレータを使用している場合)。具体的には、典型的なwhile (rowset.hasNext())
反復ループは、例9-9に示したように、最初の行ではなく2番目の行を処理することでスキップまたは開始されます。
例9-9 デフォルト行セット・イテレータの使用結果
// Reset the default row set iterator to the slot before the first row rowset.reset(); // If an iterator binding is bound to the same default row set iterator, // then it has already forced it to navigate to the first row here instead // of being on the slot before the first row. // // If the row set has only one row, the following will then return false while (rowset.hasNext()) { // If the row set has more than one row, the first time through the loop // this call to next() will return the second row rather than the first // row as expected. Row curRow = rowset.next(); // Do something with current row }
ADFアプリケーション・モジュールには独自のリソース・バンドルはなく、JDeveloperにはアプリケーション・モジュールとの連携を行う設計時はありません。ただし、カスタム・メッセージ文字列を含む.properties
ファイルを登録する場合は、アプリケーション・モジュール用に生成する定義クラス・ファイルにリソース・バンドル定義を設定できます。
アプリケーション・モジュールのカスタム定義クラス・ファイルを生成するには、アプリケーション・モジュールの概要エディタの「Javaクラス」ページで、アプリケーション・モジュール用に開く「Javaオプションの選択」ダイアログを使用します。このファイルを使用して、組込みメソッドであるfinishedLoading()
をオーバーライドできます。
作業を始める前に、次のようにします。
9.2.1項「アプリケーション・モジュールの作成方法」に記載されている方法に従って、該当するアプリケーション・モジュールを作成します。
.properties
ファイルを作成し、4.7項「リソース・バンドルの使用」に記載の内容に従って、メッセージ・キーとメッセージを追加します。
作成する.properties
ファイルは、完全修飾パッケージ名とカスタム・メソッド例外メッセージによって、属性プロパティを参照できます。たとえば、メッセージ・キーと文字列を次のように定義します。
test.Order.Orderno_LABEL=Order Number INVALID=You have called the method foo in an invalid way.
リソース・バンドルでメソッドの例外メッセージ用メッセージを定義する場合、カスタム・メソッドは9.9.1項「アプリケーション・モジュールのクライアント・インタフェース上でのカスタム・メソッドの公開方法」に記載したように、アプリケーション・モジュール・クライアント・インタフェースに表示する必要があります。
たとえば例外メッセージINVALID
のかわりに、メソッドfoo()
のメッセージを定義すると、インタフェースはリソース・バンドルからメッセージを呼び出すように、このメソッドを定義する場合があります。
public void foo() { ResourceBundleDef r = getResourceBundleDef(); throw new JboException(r,"INVALID",null); }
定義クラスを生成し、finishedLoading methodメソッドをオーバーライドするには、次の手順に従います。
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
概要エディタで、「Java」ナビゲーション・タブをクリックします。
「Javaクラス」ページで、「Javaオプションの編集」ボタンをクリックします。
「Javaオプションの選択」ダイアログで、「アプリケーション・モジュール定義クラスの生成」を選択し、「OK」をクリックします。
概要エディタの「Javaクラス」ページで、カスタマイズするアプリケーション・モジュール定義クラスにリンクされたファイル名をクリックします。ソース・エディタでクラス・ファイルが自動的に開きます。
JDeveloperツールバーから、「ソース」→「メソッドのオーバーライド」を選択します。
JDeveloperツールバーに「ソース」メニューが表示されていない場合は、定義クラス・ファイルが開いており、ソース・エディタが表示されていることを確認します。
「メソッドのオーバーライド」ダイアログで、リストをスクロールしてfinishedLoading()メソッドを検索し、選択して、「OK」をクリックします。
定義クラス・ファイルのソース・エディタで、メッセージ・バンドル.propertiesファイルを呼び出すコードを追加します。
たとえば、ファイルがtest
パッケージ内のMyAMBundle
の場合は、次のようなコードになります。
@Override protected void finishedLoading() { super.finishedLoading(); PropertiesBundleDef pbd = new PropertiesBundleDef(this); pbd.setPropertiesFile("test.MyAMBundle"); setResourceBundleDef(pbd); }
たとえば、finishedLoading()
メソッドはメッセージ・バンドル定義を作成し、定義にカスタム・メッセージ・バンドルを設定します。
ファイルを保存します。
アプリケーション・モジュールのカスタム定義クラスを生成すると、JDeveloperではコンポーネントのXMLコンポーネント定義ファイルと同じディレクトリにファイルが作成されます。そのカスタムJavaファイルのデフォルト名はAppModuleName
DefImpl.java
になります。
定義クラス・ファイル内の組込みfinishedLoading()
メソッドをオーバーライドするので、実行時にアプリケーションをロードした後で、フレームワークはメソッドを呼び出し、指定された.properties
ファイルを自動的にロードします。
アプリケーション・モジュール・クラスにpublic
カスタム・メソッドを追加する際に、アプリケーションのUIによるそのメソッドの起動を可能にする場合、そのメソッドをアプリケーション・モジュールのUIクライアント・インタフェースに追加する必要があります。
アプリケーション・モジュールのカスタムJavaクラスのpublicメソッドをクライアント・インタフェースに追加するには、アプリケーション・モジュールの概要エディタの「Javaクラス」ページを使用し、「クライアント・インタフェース」セクションの「編集」アイコンをクリックして、「クライアント・インタフェースの編集」ダイアログを表示します。「使用可能」リストから目的のメソッドを1つ以上選択し、「追加」ボタンをクリックして「選択済」リストに移動します。次に、「OK」をクリックしてエディタを閉じます。図9-21は、クライアント・インタフェースに追加した複数のpublicメソッドを示しています。
カスタム・サービス・メソッドをクライアント・インタフェースに公開すると、図9-22に示すように、アプリケーション・モジュールと同じ名前のJavaインタフェースが、アプリケーション・モジュールが存在するパッケージのcommon
サブパッケージに作成されます。fodemo.model
パッケージのStoreServiceAM
という名前のアプリケーション・モジュールでは、このインタフェースはStoreServiceAM
という名前になり、fodemo.model.common
パッケージに作成されます。このインタフェースにより、oracle.jbo
パッケージのベースApplicationModule
インタフェースが拡張され、アプリケーション・モジュールがApplicationModuleImpl
クラスから継承するすべてのベース機能へのクライアント・アクセスが可能になります。
例9-10に示すように、StoreServiceAM
インタフェースには、アプリケーション・モジュールのクライアント・インタフェースに配置するように選択したすべてのメソッドのメソッド・シグネチャが含まれています。
例9-10 「クライアント・インタフェース」パネルで選択されているメソッドに基づくカスタム・クライアント・インタフェース
package fodemo.model.common; import oracle.jbo.ApplicationModule; // --------------------------------------------------------------------- // --- File generated by Oracle ADF Business Components Design Time. // --------------------------------------------------------------------- public interface StoreServiceAM extends ApplicationModule { void deleteCurrentMyOrderItem(); void executeMyOrdersForCustomerVO(); void userRegistrationCreate(String userType); void updateUserInterests(List pCategoryIds); void userRegistrationCreateAddress(); }
注意: 新しいカスタム・メソッドをクライアント・インタフェースに追加した後で、JDeveloperのコード・インサイトによる状況依存の文補完を使用したときにこのカスタム・メソッドを使用できない場合は、生成されたクライアント・インタフェースの再コンパイルを試行してください。このためには、アプリケーション・モジュールをアプリケーション・ナビゲータで選択し、同じ名前のインタフェースのソース・ファイルを構造ウィンドウで選択し、「再ビルド」をポップアップ・メニューから選択します。このヒントは、ビュー・オブジェクトにかぎらず、ビュー行に追加された新しいカスタム・メソッドでも参考にしてください。 |
アプリケーション・モジュールのクライアント・インタフェースを生成することに加えて、カスタマイズ可能な他のキー・クライアント・オブジェクトを操作するための強く型付けされたクライアント・インタフェースも生成できます。たとえば、ビュー・オブジェクトの概要エディタで「Java」ページを開き、「クライアント・インタフェース」セクションと「カスタム行インタフェース」セクションを展開し、カスタム・メソッドをビュー・オブジェクト・クライアント・インタフェースおよびビュー行クライアント・インタフェースにそれぞれ追加できます。
devguide.model.queries
パッケージのProducts
ビュー・オブジェクトに対してカスタム・ビュー・オブジェクトのJavaクラスの生成を可能にして1つ以上のカスタム・メソッドをビュー・オブジェクト・クライアント・インタフェースに追加すると、図9-23に示すように、ProductsImpl
クラスおよびProducts
インタフェースが生成されます。アプリケーション・モジュール・カスタム・インタフェースと同様に、common
サブパッケージに生成されます。
同様に、同じビュー・オブジェクトに対してカスタム・ビュー行のJavaクラスの生成を有効にして、1つ以上のカスタム・メソッドをビュー行クライアント・インタフェースに追加すると、図9-24に示すように、ProductsRowImpl
クラスおよびProductsRow
インタフェースが生成されます。
カスタム・アプリケーション・モジュールのメソッドは、9.9項「UIクライアントへのカスタム・サービス・メソッドの公開」で説明しているように、クライアント・インタフェースに公開した後にビジネス・コンポーネント・ブラウザでテストできます。
公開したサービス・メソッドのテスト方法:
アプリケーション・ナビゲータで、目的のアプリケーション・モジュールおよびビュー・オブジェクトを含むプロジェクトを展開します。
アプリケーション・モジュールを右クリックし、「実行」を選択します。
または、デバッグを有効にしたビジネス・コンポーネント・ブラウザでアプリケーションを実行する場合は「デバッグ」を選択します。JDeveloperにより、ログ・ウィンドウのデバッガ・プロセス・パネルおよび各種デバッガ・ウィンドウが開きます。ビジネス・コンポーネント・ブラウザを使用してデバッグする場合、これらのウィンドウを使用してステータス・メッセージと例外を表示し、ソース・コードをステップ・インおよびステップ・アウトし、ブレークポイントを管理できます。
ADFビジネス・コンポーネントのデバッグに特有の診断メッセージを受信する方法の詳細は、6.3.8項「ADFビジネス・コンポーネント・デバッグ診断を有効化する方法」を参照してください。
クライアント・インタフェースによって定義されたメソッドのメソッド・テスト用パネルを開くには、次のいずれかを行います。
アプリケーション・モジュール・クライアント・インタフェース用に公開したメソッドを実行する場合、データ・モデル・ツリーでアプリケーション・モジュール・ノードを選択し、メイン・メニューから「表示」 - 「操作」を選択します。アプリケーション・モジュール・ノードをダブルクリックして、メソッド・テスト・パネルを開くこともできます。
ビュー・オブジェクト用のクライアント・インタフェースで公開したメソッドを実行する場合、データ・モデル・ツリーで該当するビュー・オブジェクト・ノードを選択し、メイン・メニューから「表示」 - 「操作」を選択します。ビュー・オブジェクト・ノードを右クリックして、「操作」を選択することもできます。
ビュー・オブジェクト行のクライアント行インタフェースで定義したメソッドのメソッド・テスト・パネルを開くには、データ・モデル・ツリーを展開し、該当するビュー・オブジェクト・ノードを右クリックして、「表の表示」を選択します。次にビュー・インスタンスの概要パネルで該当する行を選択し、メイン・メニューから「表示」 - 「操作」を選択します。
マスター・ビュー・オブジェクトではビュー行の操作は禁止されているので、データ・モデル・ツリーでマスター・ビュー・インスタンスを選択しないでください。図9-25のように、マスター/ディテール階層が指定されていないディテール・ビュー・インスタンスまたはビュー・インスタンスを必ず選択してください。
ヒント: ディテール・ビュー・インスタンスの場合、マスター・ビュー・インスタンスを開いて該当する行のディテールに移動できます。ビジネス・コンポーネント・ブラウザは開いた概要パネル内に表示されたデータを、移動先のマスター・ビュー・インスタンスと自動的に同期化します。 |
メソッド・パネル内で、ドロップダウン・リストから該当するサービスを選択し、メソッド・パラメータとして渡す値を入力し、「実行」をクリックします。
メソッド・テスト・パネルにはパラメータ名が表示され、渡す値をどこに入力すればよいのかがわかるようになっている点に注意してください。これはメソッド・シグネチャが同じデータ型の複数のパラメータを定義している場合には特に便利です。
戻り値(ある場合)とテスト結果を表示できます。ビジネス・コンポーネント・ブラウザに表示される結果は、メソッドが正常に実行されたかどうかを示します。
クライアント・インタフェースには、次の実装ルールに従うカスタム・メソッドを追加できます。
メソッドの戻り型がvoid
以外の場合、型はシリアライズ可能である必要があります。
メソッドが任意のパラメータを受け入れる場合、その型はすべてシリアライズ可能である必要があります。
メソッド・シグネチャにthrows句が含まれる場合、例外はoracle.jbo
パッケージのJboException
のインスタンスである必要があります。
つまり、そのメソッド・シグネチャ内のすべての型はjava.io.Serializable
インタフェースを実装する必要があり、チェック済の例外はJboException
またはそのサブクラスである必要があります。メソッドでは、アプリケーション・モジュールのクライアント・インタフェースで非表示になることなく、未チェックの例外(java.lang.RuntimeException
またはそのサブクラス)をスローできます。
java.util.List
の型のメソッド・シグネチャは、インタフェースの実装クラスがシリアライズ可能な限り使用できる点に注意してください。たとえば、java.util.ArrayList
およびjava.util.LinkedList
は両方ともシリアライズ可能なクラスです。同じ要件がコレクション内の要素型に適用されます。インタフェースを実装しているクラスをインスタンス化したにもかかわらず、java.io.Serializable
インタフェースを実行しなかった場合、ADFビジネス・コンポーネント・ランタイムはエラーを生成します。
注意: アプリケーション・モジュール・クラスに追加したメソッドが「使用可能」リストに表示されない場合は、メソッド実装ルールのいずれか違反していないかをまず確認してください。適切なメソッドと判断できる場合は、アプリケーション・モジュールの概要エディタに再移動する前に、アプリケーション・モジュール・クラスの再コンパイルを試行してください。 |
アプリケーション・モジュールのカスタム・メソッドのプライベート実装では、生成されたアクセッサ・メソッドを使用してデータ・モデル内のビュー・オブジェクト・インスタンスを簡単に参照できます。ビュー・オブジェクトでgetCurrentRow()
メソッドをコールすると、クライアント・ユーザー・インタフェースでビュー・オブジェクトの現在行として認識されている行にアクセスできます。その結果、アプリケーション・モジュールのビジネス・サービス・メソッドの記述中には、クライアントからのパラメータの引渡しが不要な場合があります。これは、同じアプリケーション・モジュールのデータ・モデルにある他のビュー・オブジェクト・インスタンスの現在行から値を渡すのみの場合に該当します。
たとえば、例9-11にあるカスタム・アプリケーション・モジュール・メソッドではパラメータを受け入れません。createOrderItem()
メソッドはgetGlobals().getCurrentRow()
を内部でコールし、Globals
ビュー・オブジェクト・インスタンスの現在行にアクセスします。次に、強く型付けされたアクセッサ・メソッドを行で使用してDescription
およびLineItemId
属性の値にアクセスし、この値を、新規作成されたOrderItem
エンティティ・オブジェクト行の対応する属性の値として設定します。
メソッドをアプリケーション・モジュールのクライアント・インタフェースに公開したら、それらのメソッドをクライアントから起動できます。
アプリケーション・モジュールのクライアント・インタフェースをプログラム的に操作するには:
ApplicationModule
を、特定のクライアント・インタフェースにキャストします。
インタフェース上のいずれかのメソッドをコールします。
注意: この項では、説明を簡潔にするために、カスタム・アプリケーション・モジュールのインタフェースの操作のみを重視しますが、これと同じダウンキャスト方法は、 |
例9-12は、この2つの手順を実行するTestClientCustomInterface
クラスを示しています。9.7.5項「静的メイン・メソッドを使用したカスタム・アプリケーション・モジュールのテスト方法」に記載のように、このクラスのmain()
メソッドを使用してアプリケーション・モジュール・メソッドのテストを行うこともできます。その場合は、StoreFrontService
クライアント・インタフェースを使用して、クライアントからすべての同一メソッドをコールします。
注意:
|
例9-12の基本ロジックは次の手順に従います。
注文1011の合計を取得します。
注文1011の顧客名を取得します。
1011の注文ステータスを「CANCEL」の値に設定します。
製品名がnullの新しい製品を作成します。
製品名を付けて新しい製品を作成し、新しく割り当てた製品IDを表示します。
例9-12 クライアントからのアプリケーション・モジュールのカスタム・インタフェースの使用
package devguide.examples.appmodules; import devguide.examples.appmodules.common.StoreFrontService; import devguide.examples.entities.PersonsEOImpl; import devguide.examples.entities.ProductsBaseEOImpl; import oracle.jbo.ApplicationModule; import oracle.jbo.JboException; import oracle.jbo.Key; import oracle.jbo.client.Configuration; import oracle.jbo.domain.DBSequence; import oracle.jbo.domain.Number; import oracle.jbo.server.ApplicationModuleImpl; import oracle.jbo.server.EntityDefImpl; public class TestClientCustomInterface { public static void main(String[] args) { String amDef = "devguide.model.StoreFrontService"; String config = "StoreFrontServiceLocal"; /* * This is the correct way to use application custom methods * from the client, by using the application module's automatically- * maintained custom service interface. */ // Acquire instance of application module, cast to client interface StoreFrontService service = (StoreFrontService)Configuration.createRootApplicationModule(amDef,config); String total = service.findOrderTotal(1011); System.out.println("Status of Order # 1011 = " + total); String customerName = service.findOrderCustomer(1011); System.out.println("Customer for Order # 1011 = " + customerName); try { service.updateOrderStatus(1011,"CANCEL"); } catch (JboException ex) { System.out.println("ERROR: "+ex.getMessage()); } long id = 0; try { id = service.createProduct(null, "NEW", "CLASS1"); } catch (JboException ex) { System.out.println("ERROR: "+ex.getMessage()); } id = service.createProduct("Canon PowerShot G9", "NEW", "CLASS1"); System.out.println("New product created successfully with id = "+id); Configuration.releaseRootApplicationModule(am,true); } }
例9-12のクライアントはクライアント・インタフェースのカスタム・メソッドをコールし、次の出力を表示します。
Total for Order # 1011 = 99.99 Customer for Order # 1011 = John Chen ERROR: JBO-27014: Attribute ProductName in ProductsBaseEO is required. New product created successfully with id = 133
製品名をnullとしてcreateProduct()
をコールしようとした初回の試みでは、Product
エンティティ・オブジェクトのName
属性に対する組込み必須検証が原因で例外が発生しています。
アプリケーション・モジュールにアクセス中のクライアント・レイヤーはJava EEアーキテクチャの同一層にあるため、アプリケーション・モジュールはローカル・モードと呼ばれるモードでデプロイされます。ローカル・モードでは、クライアント・インタフェースはカスタム・アプリケーション・モジュールのJavaクラスによって直接実装されます。JavaServer FacesアプリケーションのWeb層のアプリケーション・モジュールにアクセスするたびに、ローカル・モードでアプリケーション・モジュールにアクセスします。
oracle.jbo.client
パッケージのConfiguration
クラスでは、テスト用のアプリケーション・モジュール・インスタンスを非常に簡単に入手できます。これにより、JUnit回帰テスト・フィクスチャの一部となるテスト・クライアント・プログラム(31.10項「JUnitを使用した回帰テスト」を参照)のように、テスト・クライアント・プログラムの記述が簡単になります。
ベスト・プラクティス: Fusion Webアプリケーションに対しては、常にバインディング・レイヤーを使用してアプリケーション・モジュールにアクセスする必要があります。開発者はアプリケーション・モジュールにアクセスするあらゆる場合に、このクラスの |
データをバインドするためのADFモデル・レイヤーを使用してFusion Webアプリケーションを操作している場合、ユーザー・インタフェース・プロジェクトにADFBindingFilter
というサーブレット・フィルタが構成されます。このフィルタにより、宣言的なバインディング・メタデータに基づく適切なアプリケーション・モジュール・インスタンスの自動的な取得およびリリースが調整され、ユーザー・インタフェース・プロジェクトのページ定義ファイルで指定された既知のアクション・バインディングまたはイテレータ・バインディングを使用して、サービスをデータ・コントロールとして検索できるようになります。ADFバイディング・コンテナ、データ・コントロール、ページ定義ファイルおよびバインディングの詳細は、第12章「Fusion WebアプリケーションでのADFモデルの使用」を参照してください。ここでは、ADFアクション・バインディングまたはADFイテレータ・バインディングに名前を付けることで、このDCBindingContainer
からアプリケーション・モジュールのクライアント・インタフェースにアクセスできることがわかるだけで十分です。例9-13(アクション・バインディング)および例9-14(イテレータ・バインディング)に示すように、JSFマネージドBeanのカスタム・クライアント・インタフェースで、バインディング・コンテキストを参照してメソッドをコールできます。
アクション・バインディングを使用して、アプリケーション・モジュールのカスタム・インタフェースにアクセスするには、例9-13に示す基本手順に従います。
ADFバインディング・コンテナにアクセスします。
名前の付いたアクション・バインディングを検索します。(ユーザー・インタフェース・プロジェクトのページ定義ファイルに提供されている任意のアクション・バインディング名を使用します。)
データ・コントロールをアクション・バインディングから名前で取得します。
アプリケーション・モジュールのデータ・プロバイダにデータ・コントロールからアクセスします。
アプリケーション・モジュールをそのクライアント・インタフェースにキャストします。
クライアント・インタフェースにあるいずれかのメソッドをコールします。
例9-13 名前付きアクション・バインディングを使用したJSFバッキングBeanでのアプリケーション・モジュール・クライアント・インタフェースへのアクセス
package demo.view; import oracle.fodemo.storefront.store.service.common.StoreServiceAM; import oracle.adf.model.binding.DCBindingContainer; import oracle.adf.model.binding.DCDataControl; import oracle.jbo.ApplicationModule; import oracle.jbo.uicli.binding.JUCtrlActionBinding; public class YourBackingBean { public String commandButton_action() { // Example using an action binding to get the data control public String commandButton_action() { // 1. Access the binding container DCBindingContainer bc = (DCBindingContainer)getBindings(); // 2. Find a named action binding JUCtrlActionBinding action = (JUCtrlActionBinding)bc.findCtrlBinding("SomeActionBinding"); // 3. Get the data control from the iterator binding (or method binding) DCDataControl dc = action.getDataControl(); // 4. Access the data control's application module data provider ApplicationModule am = (ApplicationModule)dc.getDataProvider(); // 5. Cast the AM to call methods on the custom client interface StoreServiceAM service = (StoreServiceAM)am; // 6. Call a method on the client interface service.doSomethingInteresting(); return "SomeNavigationRule"; } }
イテレータ・バインディングを使用して、アプリケーション・モジュールのカスタム・インタフェースにアクセスするには、例9-14に示す基本手順に従います。
ADFバインディング・コンテナにアクセスします。
名前の付いたイテレータ・バインディングを検索します。(ユーザー・インタフェース・プロジェクトのページ定義ファイルないの任意のイテレータ・バインディング名を使用します。)
データ・コントロールをイテレータ・バインディングから名前で取得します。
アプリケーション・モジュールのデータ・プロバイダにデータ・コントロールからアクセスします。
アプリケーション・モジュールをそのクライアント・インタフェースにキャストします。
クライアント・インタフェースにあるいずれかのメソッドをコールします。
例9-14 名前付きイテレータ・バインディングを使用したJSFバッキングBeanでのアプリケーション・モジュール・クライアント・インタフェースへのアクセス
package demo.view; import oracle.fodemo.storefront.store.service.common.StoreServiceAM; import oracle.adf.model.binding.DCBindingContainer; import oracle.adf.model.binding.DCDataControl; import oracle.adf.model.binding.DCIteratorBinding; import oracle.jbo.ApplicationModule; public class YourBackingBean { public String commandButton_action() { // Example using an iterator binding to get the data control public String commandButton_action() { // 1. Access the binding container DCBindingContainer bc = (DCBindingContainer)getBindings(); // 2. Find a named iterator binding DCIteratorBinding iter = bc.findIteratorBinding("SomeIteratorBinding"); // 3. Get the data control from the iterator binding DCDataControl dc = iter.getDataControl(); // 4. Access the data control's application module data provider ApplicationModule am = (ApplicationModule)dc.getDataProvider(); // 5. Cast the AM to call methods on the custom client interface StoreServiceAM service = (StoreServiceAM)am; // 6. Call a method on the client interface service.doSomethingInteresting(); return "SomeNavigationRule"; } }
これらのバッキングBeanの例は、例9-15に示すヘルパー・メソッドによって異なります。
例9-15 バッキングBeanクラスのヘルパー・メソッド
public BindingContainer getBindings() { { return BindingContext.getCurrent().getCurrentBindingsEntry(); }
ADFアクションに宣言的にバインドされるボタンを上書きしてバッキングBeanクラスを作成すると、このメソッドがクラス内に自動的に生成されます。それ以外の場合は、ヘルパー・メソッドをクラスに手動で追加する必要があります。
ApplicationModuleImpl
ベース・クラスには、この機能を実装する組込みメソッドが多数含まれています。付録E「ADFビジネス・コンポーネントのよく使用されるメソッド」は、カスタム・アプリケーション・モジュール・クラスでよく記述、使用および上書きする最も一般的なコードのクイック・リファレンスとなっていますが、この項では、これらの組込みフレームワーク・メソッドの1つを上書きしてデフォルトの動作を拡張する基本手順の理解を深めることを重視しています。
アプリケーション・モジュールの組込みフレームワーク・メソッドを上書きするには、「メソッドのオーバーライド」ダイアログを使用して、メイン・メニューからアプリケーション・モジュールのJavaクラスを選択します。
作業を始める前に、次のようにします。
9.2.1項「アプリケーション・モジュールの作成方法」に記載されている方法に従って、該当するアプリケーション・モジュールを作成します。
アプリケーション・モジュールのフレームワーク・メソッドを上書きするには:
アプリケーション・ナビゲータで、アプリケーション・モジュールをダブルクリックします。
概要エディタで、「Java」ナビゲーション・タブをクリックします。
「Javaクラス」ページで、カスタマイズするアプリケーション・モジュールのJavaクラスにリンクされたファイル名をクリックします。
ソース・エディタでクラス・ファイルが自動的に開きます。
メイン・メニューから、「ソース」→「メソッドのオーバーライド」を選択します。
「ソース」メニューが表示されていない場合は、目的のJavaクラス・ファイルが開いており、ソース・エディタが表示されていることを確認します。
「メソッドのオーバーライド」ダイアログで、リストをスクロールして目的のメソッドを特定するか、あるいはメソッド名の最初の数文字を入力してインクリメンタル検索を実行します。
メソッドを1つ以上選択します。
「メソッドのオーバーライド」ダイアログでは、任意の数のメソッドを選択して同時に上書きできます。
たとえば、図9-26
に示すように、新規ユーザー・セッションでアプリケーション・モジュールのサービス・コンポーネントの操作を初めて開始したときに、アプリケーション・モジュールのprepareSession()
メソッドを上書きしてデフォルトの機能を拡張する場合、prepareSession(Session)メソッドの隣のチェック・ボックスを選択します。
「OK」をクリックします。
「メソッドのオーバーライド」ダイアログを閉じると、図9-27に示すように、上書きしたメソッドにカーソルが置かれた状態でソース・エディタに戻ります。メソッドには、super.prepareSession()
をコールする単一行が表示されています。これは、ベース・クラスがこのメソッドに対して通常であれば実行したはずのデフォルトの動作を起動するJava構文です。カスタム・アプリケーション・モジュール・クラスでこの行の前または後にコードを追加して、デフォルトの機能の前または後のデフォルトの動作を拡張できます。
「メソッドのオーバーライド」ダイアログを使用してメソッドを上書きする場合、ソース・エディタにより、上書きしたメソッドの直前にJDK @Override
注釈が挿入されます。この注釈により、アプリケーション・モジュール・クラスのメソッドがスーパークラスのメソッドのシグネチャと一致しない場合は、コンパイル時にエラーが生成されます。
クラスにメソッド名を追加してスーパークラス内のメソッドをオーバーライドする場合は注意が必要です。オーバーライドするベース・クラス・メソッドと完全に同一のシグネチャが必要です。@Override
注釈は必ずメソッドの直前に追加してください。これにより、メソッドがスーパークラスのメソッドのいずれのシグネチャとも一致しない場合は、コンパイル時にエラーが生成されます。スーパークラスの実装をコールするかわりにメソッドのコードを記述する場合は、抑止または置換する組込みコードについて理解しておく必要があります。
prepareSession()
メソッドは、新しいユーザー・セッションで初めて使用されるときにアプリケーション・モジュールによって起動されるため、カスタム・アプリケーション・モジュール・クラスをオーバーライドし、アプリケーション・モジュールを使用する新しいユーザーごとに固有のセットアップ・タスクを実行する場合に便利なメソッドです。例9-16は、アプリケーションで使用する言語を初期化するsetCurrentUserLanguage()
ヘルパー・メソッドを起動するoracle.fodemo.storefront.adfextensions.FODApplicationModuleImpl
クラス内の、オーバーライドされたprepareSession()
メソッドを示しています。
例9-16 現在のユーザー・セッションで使用する言語の初期化
public class FODApplicationModuleImpl extends ApplicationModuleImpl { public static String preferredLanguage; public static boolean isWebUser=false; private String[] supportedLanguages = {"EN","JA","EL","FR","DE"}; /** * @param session */ @Override protected void prepareSession(Session session) { super.prepareSession(session); setCurrentUserLanguage(); } private void setCurrentUserLanguage() { DBTransactionImpl dbti = (DBTransactionImpl)getDBTransaction(); CallableStatement statement = dbti.createCallableStatement(("BEGIN " + "user_context_pkg.set_app_user_lang(?); " + "END;"), 0); try { statement.setString(1, getApplicationLanguage()); statement.execute(); } catch (SQLException sqlerr) { throw new JboException(sqlerr); } finally { try { if (statement != null) { statement.close(); } } catch (SQLException closeerr) { throw new JboException(closeerr); } } } /** * @return */ public String getApplicationLanguage(){ String appLanguage = "EN"; if (isWebUser){ for (int index=0; index<supportedLanguages.length; index++){ if (preferredLanguage.equals(supportedLanguages[index])){ appLanguage = preferredLanguage; break; } } } else{ appLanguage = getAMLanguage(); } return appLanguage; } /** * @return */ public String getAMLanguage(){ PropertyMetadata langProperty = PropertyMetadata.findProperty("jbo.default.language"); String amLanguage = langProperty.getProperty(); return amLanguage.toUpperCase(); } }