この章では、ユーザー・インタフェース・プロジェクトをデバッグするプロセスについて説明します。また、デバッグのブレークポイントを設定する際に使用できる、Oracle ADFモデルAPIのメソッドについても説明します。最後に、ADF Business Componentsベースのビジネス・サービスに対するリグレッション・テストを記述し、実行する方法について説明します。
この章の内容は次のとおりです。
WebアプリケーションとOracle ADFとの対話のデバッグは、他のデバッグ・タスクと同様に、特定の要因を切り分けするプロセスです。ただし、Webアプリケーションの場合は一般に、このプロセスでJavaソース・コードのコンパイルが行われません。このため、Webページにはコンパイル用のJavaソース・コードは含まれません。実際には、アプリケーションを実行して使用してみるまで、問題が存在しているかわからないことがあります。たとえば、次のような障害は実行時に初めて現れます。
ページが見つからないというサーブレット・エラー
ページは見つかるが、コンポーネントがデータなしで表示される
メソッド・コールまたは組込み操作(「Next」や「Previous」など)の実行後、ページにデータが表示されない
ページは表示されるが、メソッド・コールまたは組込み操作をまったく実行できない
ページは表示されるが、予期しない検証エラーが発生する
データを表示できない、またはメソッド・コールを実行できない場合、WebページのコンポーネントとOracle ADFモデル・レイヤーの間の対話に原因があります。ADFライフサイクル処理中にランタイム・エラーが観測されると、モデルの準備、値の更新、アクションの起動、データのレンダリングという一連の処理の完了が失敗します。
幸い、WebアプリケーションとOracle ADFの対話における失敗は、アプリケーションにより定義された宣言情報か、ページのOracle ADFバインディング・コンテナのランタイム・オブジェクトにアクセスするEL式の中にある、修正が容易な単純なエラーが原因であることがほとんどです。
このため、Oracle ADFのデータ・バインド済アプリケーションでランタイム障害が観測された場合は、その原因として考えられる宣言情報とEL式を調べる必要があります。次の各項では、宣言ファイルの編集について説明します。
アプリケーションの実行中に使用できる(デバッグ・セッション全部を起動する必要のない)最も便利な診断ツールは、ADF Loggerです。Oracle ADFモデル・レイヤーAPIからランタイム・トレース・メッセージを取得するには、JDeveloperでこのJ2EEロギング・メカニズムを使用します。ADFロギングが有効になっている場合、JDeveloperにより、メッセージ・ログ・ウィンドウ内にアプリケーション・トレースが表示されます。このトレースには、アプリケーション・エラーの原因をすぐに特定できるランタイム・メッセージが含まれます。詳細なトレース・メッセージが表示されるようにADF Loggerを構成するには、24.4項「一般的なOracle ADFモデルのデバッグ・セッションの概要」を参照してください。
2005年6月28日現在、サポート契約を締結しているOracle ADFのお客様については、Oracle Worldwide SupportにOracle ADFソース・コードをリクエストできます。これにより、Oracle ADF Business Componentsフレームワーク・コードを非常に簡単にデバッグできます。Oracle ADFソース・コードを使用するためのJDeveloperの構成方法については、24.5項「デバッグに対するOracle ADFソース・コードの設定」を参照してください。
エラーを容易に特定できない場合は、JDeveloperのデバッグ・ツールを使用して、アプリケーションの実行と、Oracle ADFページのライフサイクルの様々なフェーズをステップ実行できます。このプロセスによって、エラーが発生した正確な箇所を切り分けできます。デバッグ・ツールを使用すると、アプリケーションの実行をOracle ADF API内の特定のメソッドで一時停止し、Oracle ADFバインディング・コンテナが持つデータを調べ、それを本来の期待されるデータと比較することができます。Oracle ADFモデル・レイヤーのデバッグについては、24.6項「Oracle ADFモデル・レイヤーのデバッグ」を参照してください。
EL式をデバッグする際に、ヘルプが必要な場合があります。ELは多数の便利な例外に関して十分にサポートされているわけではありませんが、JSFトレース・メッセージを有効にして、変数解決を調べることができます。JSFトレース・メッセージの使用については、24.7項「EL式のトレース」を参照してください。
JDeveloperでは、リグレッション・テスト・ケースを生成するウィザードにより、ADF Business ComponentsアプリケーションのためのJUnitとの統合が提供されます。アプリケーションのテスト・スイートの記述方法については24.8項「JUnitによるアプリケーション・モジュールのリグレッション・テスト」を参照してください。
JDeveloperで、Webページを作成し、ADFデータ・コントロールを使用してADFバインディング定義を作成するとき、編集するOracle ADF宣言ファイルは、Oracle ADFにより定義されたXMLスキーマに準拠している必要があります。XML構文エラーが発生すると、JDeveloper XMLコンパイラによって即時に構造ウィンドウ内にエラーが表示されます。JDeveloperの「表示」メニューから「構造」を選択して、XMLエディタで編集するOracle ADFファイルに対して構造ウィンドウを開きます。
現在、JDeveloperコンパイラではEL式の解決機能に制約があります。Webページ内のEL式は、Web環境における様々なランタイム・オブジェクト(WebページのOracle ADFバインディング・コンテナなど)と直接対話します。現在、EL式内のエラーは実行時にしか観測できません。このため、オブジェクト・アクセス式に入力エラーが1つ存在していても、コンパイラによって検出されず、実行時にバインディング・コンテナと対話できないこと、またページにデータが表示されないことでエラーが明らかになります。ラインタイム・エラーのデバッグの詳細は、24.3項「単純なOracle ADFランタイム・エラーの修正」を参照してください。
|
ヒント: JDeveloperの式ビルダーは、オブジェクト、マネージドBeanおよびプロパティのリストを提供することでEL式の作成を支援するダイアログです。式ビルダーでは、ADFバインディング・オブジェクトとその有効なプロパティが階層リストで表示されます。式に使用するオブジェクトやプロパティをこのリストから選択できるため、ADFデータ・バインドされたEL式を作成または編集するときに特に便利です。入力エラーを未然に防ぐために、式ビルダーを使用することをお薦めします。詳細は、12.6.2項「式ビルダーの使用方法」を参照してください。 |
例24-1に、ページ定義ファイルに含まれた単純なコンパイル・エラーを示します。falseとなるところがfaseに、IsQueriable="false"/>となるところがIsQueriable="false"/(終了の山カッコがない)となっています。
例24-1 2つのエラーが含まれたサンプル・ページ定義ファイル
<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
version="10.1.3.35.62" id="browseusersPageDef"
Package="oracle.srdemo.view.pageDefs"
EnableTokenValidation="fase"
...>
<parameters/>
<executables>
<variableIterator id="variables">
<variable Type="java.lang.String" Name="findUsersByName_name"
IsQueriable="false"/
前述のエラーに対する構造ウィンドウは、図24-1のように表示されます。
アプリケーションのコンパイルを試行すると、コンパイラ・ウィンドウにも同様のエラーが表示されます(図24-2)。
スキーマ検証エラーを修正するには、構造ウィンドウまたはコンパイラ・ウィンドウのいずれかで、エラーをダブルクリックしてファイルを開きます。ファイルがXMLエディタ内に開かれ、修正の必要がある行が強調表示されます。
エラーを修正すると、構造ウィンドウから即時にエラーが削除されます。オプションで、変更済のファイルを再コンパイルするためのmake操作を使用してプロジェクトを再コンパイルし、空のコンパイラ・ウィンドウを確認することもできます。
Oracle ADFモデル・レイヤーの障害は、JDeveloperコンパイラによって検出されません。ページのデータ表示およびメソッド実行の動作がOracle ADFページ定義ファイルの宣言に依存していることが、この一因です。Oracle ADFモデル・レイヤーは、実行時にこれらの宣言ファイルを使用して、Oracle ADFバインディング・コンテナのオブジェクトを作成します。
スキーマ検証だけでなく、Webページを定期的に実行およびテストして、次の条件が存在していないことを確認すると効果的です。
データ・モデル・プロジェクトとユーザー・インタフェース・プロジェクトの間のプロジェクト依存関係が無効になっている。
デフォルトでは、データ・モデル・プロジェクト内のデータ・コントロールにアクセスするWebページを作成すると、プロジェクト間の依存関係が有効になります。しかし、アプリケーションを実行しようとしたときに依存関係が無効化されて再び有効化されないと、実行時に次の内部サーブレット・エラーが生成されます。
oracle.jbo.NoDefException: JBO-25002: 型nullの定義model.DataControls.dcxが見つかりません。
このエラーを修正するには、ユーザー・インタフェース・プロジェクトを右クリックして「プロジェクト・プロパティ」を選択し、ダイアログで「依存性」を選択します。パネル内に<ModelProjectName>.jprオプションが表示されていることを確認してください。
DataBindings.cpxファイルの場所が変更されたのに、web.xmlファイルが依然としてそのファイルの元のパスを参照している。
デフォルトでは、JDeveloperにより、ユーザー・インタフェース・プロジェクト用のパッケージにDataBindings.cpxファイルが追加されます。(たとえば、アプリケーションのリファクタなどによって)ファイルの場所が変更された場合、実行時に次の内部サーブレット・エラーが生成されます。
oracle.jbo.NoXMLFileException: JBO-26001: コンテナ/oracle/<path>/DataBinding.cpxに対するXMLファイルが見つかりません。
このエラーを修正するには、web.xmlファイルを開き、<context-param>要素CpxFileName内のパスを編集します。
ページ定義ファイルの名前が変更されたのに、DataBindings.cpxファイルが依然として元のページ定義ファイル名を参照している。
JDeveloperではIDE内でのこれらのファイルの名前変更は許可されていませんが、JDeveloperの外部でページ定義ファイルの名前が変更された場合、DataBindings.cpxファイル内の参照が更新されていないと、実行時に次の内部サーブレット・エラーが生成されます。
oracle.jbo.NoDefException: JBO-25002: 型フォーム・バインディング定義の定義oracle.<path>.pageDefs.<pagedefinitionName>が見つかりません。
このエラーを修正するには、DataBindings.cpxファイルを開き、<pageMap>要素と<pageDefinitionUsages>要素内のページ定義ファイル名を編集します。
Webページ・ファイル(.jspまたは.jspx)の名前が変更されたが、DataBindings.cpxファイルが依然として同じWebページの元のファイル名を参照している。
ページ・コントローラでは、ページのURLを使用して、Webページ用のADFバインディング・コンテナの作成に使用する適切なページ定義を決定します。URLからのページの名前がDataBindings.cpxファイルの<pageMap>要素と一致しない場合、実行時に次の内部サーブレット・エラーが生成されます。
javax.faces.el.PropertyNotFoundException: プロパティ<propertyname>のテスト中にエラーが発生しました。
このエラーを修正するには、DataBindings.cpxファイルを開き、<pageMap>要素内のWebページ・ファイル名を編集します。
WebページのEL式でバインディングの名前が変更されたが、ページ定義ファイルが依然として元のバインディング・オブジェクト名を参照している。
Webページに期待どおりの情報が表示されない可能性があります。このエラーを修正するには、ページ定義ファイル内のバインディング名と、表示されていないページ部分に対応するEL式とを比較します。不一致は値バインディングで発生する可能性が最も高く、その結果として、コンポーネントがデータなしで表示されます。イテレータ・バインディング名で不一致が発生した場合、エラーはもっと軽微になり、不一致の原因を特定するためにさらに詳細なデバッグが必要になることがあります。
ページ定義ファイル内のバインディングの名前変更または削除が行われたが、EL式が依然として元のバインディング・オブジェクト名を参照している。
デフォルトのエラー処理メカニズムによりADFバインディング・コンテナからのランタイム・エラーが捕捉されるため、このタイプのエラーは非常に簡単に検出できます。たとえば、ページ定義ファイル内の(findUsersByNameIterという名前の)イテレータ・バインディング名が変更されたが、ページが依然として元の名前を参照している場合、Webページに次のエラーが表示されます。
JBO-25005: 型イテレータ・バインディング定義のオブジェクト名findUsersByNameIterが無効です。
このエラーを修正するには、Webページで名前をクリックして「ページ定義に移動」を選択し、EL式内に使用する適切なバインディング名を見つけます。
式ピッカー・ダイアログを使用せずに手動でEL式を記述し、無効なオブジェクト名またはプロパティ名が入力されている。
このエラーは見つけにくいことがあります。エラーが含まれているEL式によって、サーブレットのエラー・メッセージが表示されることと、表示されないことがあります。たとえば、ランタイム結果を持たないバインディング・プロパティ(ラベル名の表示など)においてエラーが発生した場合、ページは正常に機能しますが、ラベルは表示されません。しかし、メソッドを実行するバインディングにおいてエラーが発生した場合は、内部サーブレット・エラーjavax.faces.el.MethodNotFoundException: <methodname>が表示されます。また、メソッド式にプロパティ名を間違って入力した場合は、サーブレット・エラーjavax.faces.el.PropertyNotFoundException: <propertyname>が表示されます。これらの例外のデバッグに役立つJSFトレース・メッセージの表示の詳細は、24.7項「EL式のトレース」を参照してください。
前述の一般的なエラーのリストを調べても、ランタイム・エラーの特定と解決ができない場合は、原因を特定するためにJDeveloper内部のデバッグを開始できます。このプロセスでは、Oracle ADFページ・ライフサイクルの各フェーズでアプリケーションの実行が一時停止され、そのライフサイクルで受け取られたデータが調査され、それが期待されるデータか否かが判断されます。アプリケーションのデータを検査するには、ソース・コードのブレークポイントとデータ・ウィンドウを使用します(24.4項「一般的なOracle ADFモデルのデバッグ・セッションの概要」を参照)。
Webページまたはその対応するページ定義ファイル内でエラーが簡単に見つからない場合、JDeveloperのデバッグ・ツールを使用して、アプリケーションの障害の発生箇所を調べることができます。具体的に言えば、WebページとOracle ADFモデル・レイヤーの対話をデバッグする目標は、Oracle ADFページ・ライフサイクルの実行にブレークポイントを設定してアプリケーションを一時停止し、実行時にロードされるデータを調べることにあります。Oracle ADFモデル・レイヤーのオブジェクトに期待されるデータが含まれていない場合、これを観測することで、考えられる原因の特定につながります。
一般に、デバッグのプロセスは次のとおりです。
アプリケーションを実行し、欠落しているデータや不完全なデータ、無視されるアクションとメソッド、正しく実行されていないアクションとメソッド、あるいはその他の予期しない結果があるか調べます。
ADFログを有効にしてOracle ADFモデル・メッセージをJDeveloperのログ・ウィンドウに送信するデバッグ構成を作成します。詳細は、24.4.2項「Oracle ADFデバッグ構成の作成」を参照してください。
「ナビゲート」メニューから(または[Ctrl]を押しながら[-]を押して)「Javaクラスに移動」を選択し、ダイアログを使用して、処理が失敗しているエントリ・ポイントを表すOracle ADFクラスを見つけます。
|
ヒント: JDeveloperにより、アプリケーション・ナビゲータ内で現在フォーカスのあるユーザー・インタフェース・プロジェクトからのクラスが特定されます。ワークスペースに複数のユーザー・インタフェース・プロジェクトが含まれている場合は、デバッグの対象となるプロジェクトに現在フォーカスがあることを確認してください。 |
Javaエディタでクラス・ファイルを開き、メソッドの文をトレース実行できるOracle ADFメソッド・コールを見つけます。
目的のメソッドにブレークポイントを設定し、デバッガを実行します。
アプリケーションがブレークポイントで停止したら、データ・ウィンドウを使用して、現在のコンテキストのローカル変数および引数を調べます。
アプリケーションを一時停止するブレークポイントをキー・ポイント上に設定した後は、JDeveloperのデータ・ウィンドウにデータを表示できます。WebページとOracle ADFモデル・レイヤーの対話を効率的にデバッグするには、次のことを理解する必要があります。
Oracle ADFページのライフサイクルと、起動されるメソッド・コール
アプリケーションの処理過程でOracle ADFモデル・レイヤーに含まれる必要のあるローカル変数および引数
Oracle ADFの処理(24.6項「Oracle ADFモデル・レイヤーのデバッグ」を参照)を理解しておくことは、ブレークポイントを選択的に設定し、アプリケーションによりロードされたデータを調べ、エラーの要因を特定するための手がかりとなります。
|
注意: JSF Webページでは、ページのコンポーネントとデータの間の対話を管理するためにバッキングBeanを使用している場合もあります。バッキングBeanをデバッグするには、他のJavaクラス・ファイルの場合と同様に、ブレークポイントを設定します。 |
実際のデバッガを使用する前でも、フレームワークの診断ロギングを有効化してアプリケーションを実行すると、問題の発生時に何が起きたかを確認するのに役立ちます。診断ロギングを有効化するには、Javaシステム・プロパティjbo.debugoutputをconsoleという値に設定します。また、ADFLoggerという値にすると、標準のJ2SE Logger実装を通じて診断をルーティングできます。この実装は、OC4J j2ee-logging.xmlファイルを使用する一般的な方法で制御できます。
JDeveloper内部でのアプリケーションの実行中、このシステム・プロパティを設定する最も簡単な方法は、プロジェクト・プロパティを編集し、「実行/デバッグ」パネルで実行構成を選択して、「編集」をクリックして編集することです。次に、文字列-Djbo.debugoutput=consoleを「Javaオプション」フィールドに追加します。
ADF Facesでは、デバッグ・セッションの実行時にロギング機能を提供するために、JavaロギングAPI(java.util.logging.Logger)を使用します。Javaロギングは、Javaプラットフォーム(JDK 1.4以上)で使用可能な標準的なAPIです。主要な要素は、http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/overview.htmlの『Java Logging Overview』を参照してください。
標準的なJavaロギングが使用されるため、j2ee-logging.xmlファイルを編集して、ログ・ウィンドウに表示される診断レベルを制御できます。
JDeveloper内部でデバッグ・セッションを実行する場合は、JDeveloperに組み込まれているOC4Jを使用します。変更の対象となるJDeveloperインストールのファイルは次の場所にあります。
<JDev_Install>/jdev/system/oracle.j2ee.10.1.3.xx.xx/embedded-oc4j/config
同様に、Oracle Application Serverでリモート・デバッグ・セッションを実行する場合、次の場所にあるファイルを変更できます。
<OAS_Home>/j2ee/<OC4J_INSTANCE>/config
また、スタンドアロンOC4J上でリモート・デバッグ・セッションを実行する場合は、次の場所にあるファイルを変更できます。
<OC4J_Home>/j2ee/home/config
j2ee-logging.xmlファイル内のADFパッケージ・レベル・ロギングを編集する手順:
Oracle ADFのロギング・レベルを変更する場合は、構成ファイルの<logger>要素を編集します。
|
注意: デフォルトでは、Oracle ADFのすべてのパッケージのレベルはINFOに設定されています。ただし、詳細なロギング診断を行う場合には、level="FINE"に設定することをお薦めします。 |
パッケージoracle.adf.view.facesおよびoracle.adfinternal.view.facesの場合は、次の要素を編集します。
<logger name="oracle.adf" level="INFO"/><logger name="oracle.adfinternal" level="INFO"/>
Oracle ADFモデル・レイヤー・パッケージの場合は、次の要素を編集します。
<logger name="oracle.adf" level="INFO"/><logger name="oracle.jbo" level="INFO"/>
あるいは、デバッグ・セッションを開始する際に選択できるデバッグ構成をJDeveloper内に作成することもできます。
Oracle ADFモデルのデバッグ構成を作成する手順:
アプリケーション・ナビゲータで、ユーザー・インタフェース・プロジェクトをダブルクリックします。
「プロジェクト・プロパティ」ダイアログで「実行/デバッグ」をクリックし、(たとえば、ADF debuggingという名前の)新しい実行構成を作成します。
新しい実行構成をダブルクリックして、プロパティを編集します。
「実行構成の編集」ダイアログの「起動設定」で、デフォルトのojvm仮想マシンに対して次のJavaオプションを入力します。
-Djbo.debugoutput=adflogger -Djbo.adflogger.level=FINE
詳細な診断メッセージを表示する場合は、level=FINEに設定することをお薦めします。
ADFアプリケーションのユーザー・インタフェースを実行せず、アプリケーションでADF Business Componentsをデバッグするほうが便利な場合が多くあります。アプリケーション・ナビゲータで任意のアプリケーション・モジュールを選択し、そのモジュールで右クリックして表示されるポップアップ・メニューから「テスト」を選択し、ビジネス・コンポーネント・テスター・ツールを起動できます。
さらに、デバッガでテスター・ツールを起動することもできます。これは、ADF Business Componentsアプリケーションのデバッグを、アプリケーションの完全なフロントエンドGUIを起動させるよりもはるかに簡単に行うことができる有益な方法です。
デバッグ・モードでテスターのADFアプリケーション・モジュールを起動するには、次の処理を行います。
アプリケーション・ナビゲータで、該当するアプリケーション・モジュールを選択します。
構造ウィンドウでソース・フォルダを開き、アプリケーション・モジュールのJava実装クラスを選択します。
アプリケーション・モジュールがMyModuleという名前の場合、その実装クラスの名前はMyModuleImpl.javaになります。
そのアプリケーション・モジュール実装クラスのポップアップ・メニューから「デバッグ」を選択して、デバッガを起動します。
アプリケーション・モジュールJavaクラスのmain()メソッドは、次のようになります。
public static void main(String[] args) {
launchTester("com.yourcompany.yourapp.model", /* package name */
"MyModuleLocal"); /* Configuration Name */
}
指定された構成(たとえば、上述のコード例のMyModuleLocal)とは異なる構成を使用して、デバッガでアプリケーション・モジュールを起動する必要がある場合は、かわりに使用する構成の名前になるよう、第2引数としてlaunchTester()に渡される文字列を変更します。
|
ヒント: アプリケーション・モジュール実装クラスを(システム・ナビゲータで.javaファイルを選択して)デバッグする場合、構成名はデバッガに渡される2つの文字列のうちの1つとしてmain()メソッドに書き込まれるため、変更する必要はありません。ただし、アプリケーション・ナビゲータのアプリケーション・モジュール・ノード上のポップアップ・メニューから「テスト」を選択してビジネス・コンポーネント・テスターを使用し、アプリケーション・モジュールをデバッグする場合は、構成にはJDBC DataSourceではなくJDBC URL接続を使用する必要があります。たとえば、SRDemoアプリケーションでは、構成SRServiceLocalTestingにより、テスターを実行します。デフォルトでは、選択された構成はSRServiceLocalになります。構成の選択を変更しない場合、テスターがJDBC DataSource接続を使用できないことが警告で示されます。 |
最初に、様々なブレークポイントとそれを作成する場所を理解する必要があります。
デバッガのブレークポイント・ウィンドウを表示するには、JDeveloperのメイン・メニューで「表示」→「デバッガ」→「ブレークポイント」の順にメニューを選択します。または、オプションで[Ctrl]+[Shift]+[R]というキー・アクセラレータを使用します。
ブレークポイント・ウィンドウ内の任意の場所で右クリックして、メニューから「新規ブレークポイント」メニュー選択項目を選択し、新規のブレークポイントを作成できます。「ブレークポイント型」ドロップダウン・リストでは、作成するブレークポイントの種類をコントロールします。有効な選択項目は、次のとおりです。
例外: 該当クラス(またはサブクラス)の例外がスローされると、ブレークが発生します。
これは、例外が発生する場所が不明であり、例外がどのような種類か判明している場合に役立ちます(たとえば、java.lang.NullPointerException、java.lang.ArrayIndexOutOfBoundsException、oracle.jbo.JboExceptionなど)。チェック・ボックス・オプションにより、このクラスの例外を捕捉する場合または捕捉しない場合にブレークするかどうかを制御できます。「(参照)」ボタンは、例外の完全修飾されたクラス名を検索するのに役立ちます。「例外クラス」コンボ・ボックスでは、最近使用した例外ブレークポイント・クラスが記憶されています。これはブレークポイント・ウィンドウでブレークポイントを作成する場合の、デフォルトのブレークポイント型であることに注意してください。
ソース: 特定のパッケージに含まれるクラスの特定のソース行が実行されると、ブレークが発生します。
新規ブレークポイント・ウィンドウでソース・ブレークポイントを作成することはほとんどありません。その理由は、メニューの「ナビゲート」→「クラスに移動」(アクセラレータの[Ctrl]+[Shift]+[-])を使用して、目的の行番号までスクロールし(または「ナビゲート」→「指定行に移動」(アクセラレータの[Ctrl]+[G])を使用)、ブレークを実行する行の左側のブレークポイント・マージンをクリックする方がはるかに簡単であるためです。これは、新規のソース・ブレークポイントの作成と同じですが、パッケージ、クラスおよび行番号を手入力する必要がありません。
メソッド: 特定のクラスの1つのメソッドが起動されると、ブレークが発生します。
これは、問題のデバッグ中にコール・スタックで表示される、特定のメソッドにブレークポイントを設定するのに便利です。必要に応じてソース・ブレークポイントを設定できるソースがそのクラスにある場合でも、この種のブレークポイントでは、クラスに対するソースがない場合もデバッガで停止します。
クラス: 特定のクラスのいずれかのメソッドが起動されると、ブレークが発生します。
このオプションは、問題に関連するクラスのみがわかっており、ブレーク対象のメソッドが正確にわからない場合に便利です。また、この種類のブレークポイントでもソースは必要ありません。「参照」ボタンを使用して、ブレークを実行するクラスの完全修飾名を簡単に検索できます。
監視ポイント: 特定のフィールドがアクセスまたは変更されると、ブレークが発生します。
このオプションは、(setterまたはgetterメソッドが毎回使用されるかわりに)クラス内部のコードにより、複数の異なる場所から直接メンバー・フィールドが変更される状況で問題を検出する場合に非常に便利です。フィールドが変更された場合に、即座にデバッガを停止できます。このタイプのブレークポイントを作成するには、クラスのソースのメンバー・フィールドにカーソルを置いて右クリックし、「監視ポイントの設定」メニュー項目を選択します。
ブレークポイントを作成した後、該当するブレークポイントでポップアップ・メニューの「編集」を選択すると、ブレークポイント・ウィンドウでブレークポイントを編集できます。
ブレークポイントの編集で使用可能な役立つ機能は次のとおりです。
ブレークポイントをグループ化する論理的なブレークポイント・グループ名を、同じブレークポイント・グループ名を持つ他のブレークポイントに関連付けることができます。ブレークポイント・グループにより、1回の操作でブレークポイントのセット全体を有効化または無効化することが簡単になります。
ブレークポイントに到達した場合に実行するデバッガ・アクションを関連付けることができます。デフォルト・アクションは、検査可能になるようデバッガを停止するだけですが、ビープ音の追加、ログ・ファイルへの書込み、ブレークポイントのグループの有効化または無効化も可能です。
条件に一致した場合にのみデバッガを停止するように、ブレークポイントに条件式を関連付けることができます。10.1.3では、次のように、ほとんどすべてのブール式が可能です。
expr ==value
expr.equals("value")
expr instanceoffully.qualified.ClassName
|
注意: デバッガ監視ウィンドウを使用して、最初に式を評価してその式が有効であるか確認します。 |
JDeveloperデバッガには、見落とされがちですが優れた機能として、任意のクラスのデバッガ・ウィンドウに表示されるメンバーをフィルタできる機能があります。デバッガのデータ・ウィンドウで任意の項目にカーソルを置いて右クリックし、ポップアップ・メニューの「オブジェクト設定」を選択すると、デバッガに表示するメンバーと(状況によってはより重要となる)表示しないメンバーをカスタマイズできるダイアログが表示されます。これらの設定は、クラス・タイプごとに指定します。これにより、デバッガのデータ・ウィンドウでスクロールを要する量が大幅に減少します。この機能は、クラスの一部のメンバーにのみ関心がある場合のデバッグ作業において特に便利です。
問題のデバッグを試行する際に、Oracle ADFソース・コードで設定できる、注目に値するブレークポイントは次のとおりです。
oracle.jbo.JboExceptionに対する例外ブレークポイント
開始場所がわからない場合、これはすべてのADF Business Components実行時例外のベース・クラスです。
oracle.jbo.DMLExceptionに対する例外ブレークポイント
これは、トリガまたは制約違反によって発生する例外が原因で失敗したDML操作など、データベースから生じる例外のベース・クラスです。
JUCtrlActionBindingクラスのdoIt()メソッド(oracle.jbo.uicli.bindingパッケージ)のソース・ブレークポイント
これは、任意のADFアクション・バインディングの起動時に実行されるメソッドです。関連する場合、ロジックに踏み込んでパラメータを確認できます。
oracle.jbo.server.ViewObjectImpl.executeQueryForCollectionメソッドのメソッド・ブレークポイント
これはビュー・オブジェクトがSQL問合せを実行する際にコールされるメソッドです。
oracle.jbo.server.ViewRowImpl.setAttributeInternalメソッドのメソッド・ブレークポイント
これは任意のビュー行属性が設定される際にコールされるメソッドです。
oracle.jbo.server.EntityImpl.setAttributeInternalメソッドのメソッド・ブレークポイント
これは任意のエンティティ・オブジェクト属性が設定される際にコールされるメソッドです。
これらのブレークポイントに到達した際にスタック・ウィンドウを参照してソースを確認することで、現状をよりよく把握することができます。
通常、問題を判断できず、自分で解決できない場合には、他の人に支援を求めます。OTNのJDeveloperフォーラムに問題を投稿するか、Metalinkでサービス・リクエストを提出するかにかかわらず、投稿にスタック・トレース情報を含めると、支援者が問題の発生場所を正確に特定する際に非常に役立ちます。
JDeveloperのスタック・ウィンドウでは、この情報を簡単にやり取りできます。デバッガが一時停止したときに、スタック・ウィンドウで、現在行に到達するまでのメソッド・コールのスタックとしてプログラム・フローを参照できます。スタック・ウィンドウの背景で右クリックし、「設定」メニューを使用して、デフォルトで表示されるクラスとメソッド名の他に行番号の情報を含むようにスタック・ウィンドウを設定できます。最後に、他の便利なポップアップ・メニュー・オプションとして、「エクスポート」によって現在のスタック情報を外部テキスト・ファイルに保存できます。このテキストの内容は、問題の診断を支援する他の人に投稿または送信できます。
Oracle Worldwide Supportでサービス・リクエストをオープンし、Oracle ADFの完全なソース・コードをリクエストして取得できます。この項では、Oracle JDeveloper環境内でデバッグのためにOracle ADFソース・コードを使用する方法について説明します。
|
注意: 次の指示では、adf_1013_3673_source.zipアーカイブをルートC:\ディレクトリに抽出してC:\adf_1013_3673_sourceディレクトリを作成している、またJDeveloperのホーム・ディレクトリがC:\jdev1013であると仮定しています。JDeveloperを他のディレクトリにインストールしてある場合は、かわりにそのディレクトリを使用する必要があります。 |
最初の手順では、adfsource.zipファイルを指し示すシステム・ライブラリを定義する必要があります。このタスクを実行するには、次の手順に従います。
「ツール」→「ライブラリの管理」を選択して、「ライブラリの管理」ダイアログを表示します。
「ライブラリ」タブを選択して、左側のツリーの「システム・ライブラリ」フォルダをクリックし、「新規」ボタンをクリックします。
ライブラリ名を入力します。たとえば、ADF Sourceと入力します。
ソース・パスC:\adf_1013_3673_source\adfsource.zipを入力します。
|
注意: 「クラス・パス」フィールドは空白です。「ソース・パス」フィールドの値のみ指定する必要があります。 |
「デフォルトでデプロイ済」チェック・ボックスの選択を解除します。
「OK」をクリックして、「ライブラリの管理」ダイアログを終了します。
JDeveloper内部でOracle ADFを使用して任意のアプリケーションをデバッグするには、前項で作成した新規のADF Sourceシステム・ライブラリを、デバッグ対象のプロジェクトのライブラリ・リストに追加するのみです。このタスクを実行するには、次の手順に従います。
アプリケーション・ナビゲータでデバッグ対象のプロジェクトを選択します。
右クリックして、メニューから「プロジェクト・プロパティ」を選択して、「プロジェクト・プロパティ」ダイアログを表示します。
左側のツリー(デフォルトでは、「開発」プロファイルの下)で「ライブラリ」カテゴリを選択します。
左側の「使用可能なライブラリ」リストでADF Sourceライブラリを選択します。
(>)ボタンをクリックして、このライブラリをプロジェクトの「選択済のライブラリ」リストに移動します。
「OK」をクリックして、「プロジェクト・プロパティ」ダイアログを終了します。
ADFソース・ライブラリをプロジェクトに追加すると、JDeveloperコード・エディタで使用可能になる有用なQuick JavaDoc機能([Ctrl]+[D])にアクセスできるようになります。図24-3に示すとおり、findSessionCookie()などのメソッド上でQuick JavaDocを起動します。
前述の2つの手順を実行した後、自身のJavaコードに対して処理したものと同じ方法で、現在のプロジェクトに対するOracle ADFコードをデバッグできます。つまり、[Ctrl]+[-]キーを押してOracle ADFで任意のクラス名を入力すると、JDeveloperによってそのソース・ファイルが自動的に開かれるため、必要に応じてブレークポイントを設定できます。
Oracle ADFソースをデバッグする際、図24-4に示すように、デフォルトでは現在実行中のメソッドのパラメータまたはメンバー変数の記号情報は表示されません。
これにより、デバッグはあまり有用ではなくなります。自身の開発環境でデバッグする場合は、ソースとともに提供されるADF JARファイルのデバッグ・バージョンを使用することにより、状況を改善できます。
|
注意: 通常、提供されたデバッグ・ライブラリは、JDeveloperに同梱されている最適化されたJARファイルに比べ、実行時パフォーマンスがわずかに劣るため、テスト環境または本番環境での使用はお薦めできません。 |
C:\adf_1013_3673_sourceのdebuglibサブディレクトリには、追加のデバッグ情報でコンパイルされたJDeveloper 10.1.3ビルド3673からのOracle ADF JARファイルのバージョンが含まれます。デフォルトの最適化されたJARファイルではなく、これらのデバッグJARファイルを使用する場合、図24-5に示すように、デバッガにすべての情報が表示されます。
これらのデバッグJARファイルを使用するには、次の手順に従います。
JDeveloper 10gが実行中でないことを確認します。JDeveloperが実行中の場合、この後の手順を続行する前にJDeveloperを終了します。
JDeveloperインストールの./BC4J/libディレクトリで、既存の最適化されたJARファイルすべてのbackupサブディレクトリを作成します。
C:\> cd jdev1013\BC4J\lib C:\jdev1013\BC4J\lib> mkdir backup C:\jdev1013\BC4J\lib> copy *.jar backup
C:\adf_1013_3673_sourceのdebuglibサブディレクトリに、バックアップを作成したものと同じADF JARファイルのデバッグ・バージョンがあることに注意してください。この違いは、各デバッグJARファイルの接尾辞が単なる.jarではなく、_g.jarであることのみです。
デバッグ時にデバッグ記号を持たせる必要のある各ADFライブラリに対して、C:\jdev1013\BC4J\libディレクトリで対応する既存のライブラリに、一致するライブラリの_g.jarバージョンをコピーします。これは、前述の手順2で最適化されたJARファイルのバックアップをbackupディレクトリに作成してあるため安全です。
たとえば、メインのADF Business Components実行時JARファイル(bc4jmt.jar)の場合、C:\adf_1013_3673_source\debuglib\bc4jmt_g.jarをC:\jdev1013\BC4J\lib\bc4jmt.jarにコピーします。
通常、デバッグ・ライブラリはデバッグ情報なしでコンパイルされたライブラリよりも実行速度が劣るため、この診断メッセージは実行タイミングでデバッグ・ライブラリを使用しないように注意を促すものです。
************************************************************************** *** WARNING: Oracle BC4J debug build executing - do not use for timing *** **************************************************************************
最適化されたライブラリに戻すには、該当するJARファイルを./BC4J/lib/backupディレクトリから./BC4J/libディレクトリにコピーして戻します。
Oracle ADFモデルと合せたJSFページの処理は、次の2つのクラスにより制御されます。
oracle.adf.controller.faces.lifecycle.FacesPageLifecycleクラス
oracle.adf.controller.v2.lifecycle.PageLifecycleImplクラス
FacesPageLifecycleは、PageLifecycleImplの特定のメソッドを実装して、ADF Facesアプリケーションのカスタマイズしたエラー処理動作を提供します。ただし、一般にはPageLifecycleImplにブレークポイントを設定します。これは、このクラスが、Oracle ADFバインディング・コンテキストのオブジェクトを作成するための開始ポイントを提供するためです。
|
ヒント: FacesPageLifecycleクラスは、ADFライフサイクルのフェーズのデフォルト実装を提供します。ブレークポイントを設定するのに適した箇所は、prepareModel()メソッドです。これは、このメソッドがADFライフサイクルの最初のフェーズを開始するためです。Oracle ADFライフサイクルの詳細は13.2.3項「実行時に行われる処理: JSFおよびADFのライフサイクル」を参照してください。 |
WebページとOracle ADFバインディング・コンテキストのこれらのオブジェクトとの対話が正常に行われると、ページのコンポーネントが適切で完全なデータとともに表示され、メソッドおよびアクションにより目的の結果が生成され、ページが該当する検証エラーとともに正しくレンダリングされます。
実行時、ADFライフサイクルがモデルを準備してWebページを表示できるようになるまでに、いくつかの処理が行われる必要があります。ADFデータ・バインドされたWebページに対する最初のリクエストが発生すると、サーブレットによりOracle ADFサーブレット・フィルタADFBindingFilter(web.xmlファイル内に指定されているフィルタ)が登録されます。メソッドADFBindingFilter.doFilter()はADF処理状態を設定し、メソッドADFBindingFilter.initializeBindingContext()はweb.xmlファイルからCpxFileName初期パラメータを読み取ることによってoracle.adf.model.BindingContextのインスタンスを作成します。
ADFBindingFilter.initializeBindingContext()がコールされた直後のBindingContextは、Oracle ADFモデル・レイヤー・オブジェクトの階層を定義する空のコンテナ・オブジェクトです。ただし、ページのバインディングを作成するためには、コンテナ・オブジェクトとしてBindingContextが存在している必要があります。存在していない場合、コンテナ/oracle/<path>/DataBinding.cpxの次の内部サーブレット・エラーがスローされます。
oracle.jbo.NoXMLFileException: JBO-26001: XMLファイルが見つかりません
Webアプリケーションのバインディング・コンテキストの作成をデバッグする手順:
oracle.adf.model.servlet.ADFBindingFilterクラス内で、chain.doFilter()にブレークを設定し、このメソッドをトレース実行します。

ctx.get(BindingContext.IS_INITIALIZED)に別のブレークを設定し、このメソッドをトレース実行します。

oracle.jbo.uicli.mom.JUMetaObjectManagerクラス内で、chain.getClientProjectExtension()にブレークを設定し、このメソッドをトレース実行します。
一時停止の処理中、データ・ウィンドウで、予測されるパッケージ名を持つファイルに対するslot0を探します。

DataBindings.cpxファイルが見つからない場合は、サーブレット・コンテキスト・パラメータ要素が.cpxファイルの完全修飾名を正しく定義していることを確認し、修飾名パスにより指定された場所にあるプロジェクト内にそのファイルが存在していることを確認します。例24-2に、SRDemoアプリケーションのコンテキスト・パラメータを示します。
|
ヒント: コンテキスト・パラメータのparam-value要素内に指定された名前は、.cpxファイルの完全修飾名である必要があります。 |
ADFBindingFilterによってBindingContextが作成された後、メソッドPageLifeCycle.xXX()はリクエストのWebページURLをメソッドBindingContext.findBindingContainer()に渡して、DataBindings.cpxファイル内の<pageMap>要素からそのWebページに一致するページ定義を見つけます。これはBindingContainerになります。このBindingContainerオブジェクトはランタイム・インスタンス・オブジェクトであり、すべてのバインディングはこのオブジェクト上に作成されます。ページ定義ファイルが見つからない場合は、次の内部サーブレット・エラーがスローされます。
oracle.jbo.NoDefException: JBO-25002: 型フォーム・バインディング定義の定義oracle.<path>.pageDefs.<pagedefinitionName> が見つかりません。
Webページのバインディング・コンテナの作成をデバッグする手順:
oracle.adf.model.BindingContextクラス内で、findBindingContainerIdByPath()にブレークを設定し、このメソッドをトレース実行します。
データ・ウィンドウ内で、バインディング・コンテナに関連付けられたデータ・バインド済Webページの名前を探します。

スマート・データ・ウィンドウで、予測されるデータ・バインド済Webページ・ファイル名と一致するエントリを探します。

データ・ウィンドウ内に、データ・バインド済Webページに一致するページ定義エントリが表示されます。

<pagename>PageDef.xmlファイルが見つからない場合は、DataBindings.cpxファイル内の<pageMap>要素がプロジェクト内のWebページの正しい名前とパスを指定していることを確認します。例24-3に、SRDemoアプリケーションのDataBindings.cpxサンプル・ファイルを示します。<pageMap>要素によってJSFページがそのページ定義ファイルにマップされていることに注意してください。
|
注意: JSFページまたはページ定義ファイルの名前を変更した場合、.cpxファイルは自動的にリファクタされません。新しいページ名を反映させるには、手動で.cpx内のページ・マッピングを更新する必要があります。 |
例24-3 Databinding.cpxページ定義のサンプル
<?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://xmlns.oracle.com/adfm/application"
version="10.1.3.34.12" id="DataBindings" SeparateXMLFiles="false"
Package="oracle.srdemo.view" ClientType="Generic">
<pageMap>
<page path="/app/SRList.jspx" usageId="app_SRListPageDef"/>
...>
</pageMap>
<pageDefinitionUsages>
<page id="SRListPageDef" path="oracle.srdemo.view.pageDefs.
app_SRListPageDef"/>
...
</pageDefinitionUsages>
<dataControlUsages>
<dc id="SRDemoFAQ" path="oracle.srdemo.faq.SRDemoFAQ"/>
<BC4JDataControl id="SRService" Package="oracle.srdemo.model"
FactoryClass="oracle.adf.model.bc4j.DataControlFactoryImpl"
SupportsTransactions="true" SupportsFindMode="true"
SupportsRangesize="true" SupportsResetState="true"
SupportsSortCollection="true"
Configuration="SRServiceLocal" syncMode="Immediate"
xmlns="http://xmlns.oracle.com/adfm/datacontrol"/>
</dataControlUsages>
</Application>
BindingContextによりBindingContainerが作成された後、Webページにデータが表示される前に、ADFライフサイクルによりモデル準備フェーズとモデル・レンダリング・フェーズが開始される必要があります。バインディングが解決されて、Webページにデータが表示されるまでに、いくつかの処理が行われる必要があります。
ページ・パラメータを設定する必要があります。
名前付きのサービス・メソッドとADFイテレータ・バインディングを実行することにより、イテレータおよびメソッドの実行可能ファイルをリフレッシュする必要があります。
ADFライフサイクルは、BindingContainer.refresh(PREPARE_MODEL)をコールすることにより、モデル準備フェーズを開始します。モデル準備フェーズでは、BindingContainerページ・パラメータが準備されてから評価されます。次に、BindingContainer実行可能ファイルが、pagedef.xmlファイルの<executables>セクション内のエントリの順序と、それらのRefreshおよびRefreshConditionプロパティ(存在する場合)の評価に基づいてリフレッシュされます。実行可能ファイルがイテレータ・バインディング・リフレッシュに到達すると、対応するデータ・コントロールが実行され、それによってサービス・オブジェクト内の1つ以上のコレクションが実行されます。イテレータ・バインディングがリフレッシュに失敗すると、JBO例外がスローされ、データを表示できなくなります。
バインディング・コンテナのすべての実行可能ファイルをデバッグする手順:
oracle.adf.model.binding.DCBindingContainerクラス内で、実行可能ファイルをデバッグするエントリ・ポイントとしてinternalRefreshControl(int, boolean)にブレークを設定します。

ヒント: DCBindingContainer.internalRefreshControl()メソッド内では、条件if (/*execute ||*/ execDef == null || execDef.isRefreshable(this, iterObj, refreshFlag))の結果を確認することにより実行可能ファイルをリフレッシュするかどうかを指定できます。条件がTrueに評価された場合は、実行可能ファイルがリフレッシュされ、処理はinitSourceRSI()に進みます。
oracle.adf.model.binding.DCIteratorBindingクラス内で、callInitSourceRSI()にブレークを設定して処理を停止し、メソッドをトレース実行します。

一時停止の処理中、スタック・ウィンドウ内でcallInitSourceRSI()を探します。スマート・データ・ウィンドウには、予測された結果が表示されるはずです。

Webページにメソッド・イテレータ・バインディングからのデータが表示されない場合は、JUMethodIteratorDef.java内のエントリ・ポイントおよびそのネストされたクラスJUMethodIteratorBindingにドリルダウンしてその実行をデバッグできます。
バインディング・コンテナのメソッド・イテレータ実行可能ファイルをデバッグする手順:
oracle.jbo.uicli.binding.JUMethodIteratorDefクラス内で、メソッド・イテレータ・バインディング実行可能ファイルをデバッグするためのエントリ・ポイントとしてinitSourceRSI()にブレークを設定します。

invokeMethodAction()にブレークを設定して処理を停止し、メソッドをトレース実行します。

メソッドが有効なコレクションまたはBeanを返すと、そのオブジェクトはこのイテレータ・バインディングのバインド先の行セット・イテレータのデータソースになることに注意してください。Beanデータ・コントロールの場合、DCRowSetIteratorImplのインスタンスが作成されて、イテレータ・バインディングで使用できる行セット・イテレータ機能が提供されます。(ADF Business Componentsの場合、このメソッドは、ADF Business Componentsがコレクションの状態を管理できるようにADF Business Components行セット・イテレータを返すのが理想的です。)
initSourceRSI()により行セット・イテレータが返されたら、処理を一時停止し、スマート・データ・ウィンドウ内でmProviderを探します。mProvider変数は、この行セット・イテレータに対してフェッチされたデータソースです。メソッドが正常に返された場合、イテレータまたはBeanにバインドされたコレクションが表示されているはずです。

|
ヒント: デバッガが、バインディング・コンテナ内の実行可能ファイルに設定したブレークポイントに到達しない場合、エラーの原因として最も可能性が高いのは、実行可能ファイルのRefreshおよびRefreshCondition属性の定義内容です。属性定義を調べてください。属性値RefreshおよびRefreshConditionの詳細は、A.6.1項「PageDef.xmlの構文」を参照してください。 |
例外を生成した実行可能ファイルが特定されたら、pagedef.xmlファイル内の<executables>要素が適切な属性設定を指定していることを確認します。
モデル準備フェーズ中に実行可能ファイルがリフレッシュされるかどうかは、RefreshおよびRefreshConditionの値(存在する場合)によって決まります。RefreshがprepareModelに設定されているか、値が指定されていない(つまり、デフォルトのifneededが使用される)場合は、RefreshCondition属性値が評価されます。RefreshCondition値が存在しない場合は、実行可能セクションが起動します。RefreshConditionの値が存在する場合は、値が評価され、評価の戻り値がtrueの場合は、実行可能ファイルが起動します。値がfalseと評価された場合は、実行可能ファイルは起動しません。デフォルト値は常に、実行を強制します。
例24-4に、SRDemoアプリケーションのpagedef.xmlファイルのサンプルを示します。<executables>要素内に、実行可能ファイルが実行順に一覧表示され、そのマスター・バインディング・イテレータの後にディテール・イテレータが指定されていることに注意してください。
ADFライフサイクルのprepareRenderフェーズでは、バインディングによって表示されるデータが決まり、バインディングのプロパティによってデータが表示される条件が決まります。初めてWebページがレンダリングされるとき、バインディングを指し示す各EL式が、そのページのBindingContainerインスタンスにより解決されます。式の適切な値(format、isEnabled、isViewableなど)に基づいて、バインディングのデータ値がBindingContainerから返されます。バインディングがデータを返すことができない場合、JBO例外がスローされます。
バインディング・コンテナのバインディング解決をデバッグする手順:
oracle.jbo.uicli.binding.JUCtrlValueBindingクラス内で、getInputValue()にブレークを設定し、メソッドをトレース実行します。
getInputValue()によりエラーが戻された場合、処理を一時停止し、データ・ウィンドウ内でバインディング名を探します。

引き続きgetInputValue()をトレース実行し、データ・ウィンドウ内で、このバインディングが表す現在の行に対して予測される戻り値を探します。
例外を生成したバインディングが特定されたら、pagedef.xmlファイル内の<bindings>要素が適切な属性設定を指定していることを確認します。例24-5に、SRDemoアプリケーションのpagedef.xmlファイルのサンプルを示します。
例24-5 ページ定義の値バインディングのサンプル
<bindings>
<attributeValues IterBinding="GlobalsIterator" id="ProblemDescription">
<AttrNames>
<Item Value="ProblemDescription"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="GlobalsIterator" id="ProductId">
<AttrNames>
<Item Value="ProductId"/>
</AttrNames>
</attributeValues>
<attributeValues IterBinding="GlobalsIterator" id="ProductName">
<AttrNames>
<Item Value="ProductName"/>
</AttrNames>
</attributeValues>
<attributeValues id="FirstName"
IterBinding="LoggedInUserIterator">
<AttrNames>
<Item Value="FirstName"/>
</AttrNames>
</attributeValues>
<attributeValues id="LastName"
IterBinding="LoggedInUserIterator">
<AttrNames>
<Item Value="LastName"/>
</AttrNames>
</attributeValues>
...
</bindings>
送信の場合も、ライフサイクルでは最初にBindingContainerインスタンスが検索および準備されます。ライフサイクルで、このBindingContainerに対して持続されていた状態トークンが見つかると、この状態トークンを処理するようにBindingContainerに対して要求されます。状態トークンを処理すると、以前のレンダリングのときに保存された変数値がリストアされます。状態トークンの処理をデバッグする必要がある場合、DCIteratorBinding.processFormToken()およびDCIteratorBinding.buildFormToken()にブレークインします。
これ以降、すべてのポストは値バインディングのsetInputValue()を介してバインディングに適用されます。
実行可能ファイルがリフレッシュされると、ページ上のアクションおよびカスタム・メソッドが起動されることがあります。この段階で、対応するアクションまたはメソッドのバインディングがリフレッシュされます。実行可能ファイルもそのターゲット・バインディングも実行されない場合、アクションは無視されます。
アクションおよびメソッドの実行のエントリ・ポイントは、DCDataControl.invokeOperation()メソッドです。この他に、JUCtrlActionBinding.invoke()もエントリ・ポイントとして考えられますが、これは、メソッド・イテレータ・バインディングが暗黙的にメソッドを起動する場合にも使用されます。DCDataControl.invokeOperation()でデバッグを実行すれば、データ・コントロールがメソッドの起動に使用する同じメソッドを使用できます。一部のアダプタ・データ・コントロールでは、ADFにメソッドのコールを任せなくても独自の方法でメソッド名を解析できるため、この方法が推奨されます。
バインディング・コンテナのアクションまたはメソッド起動をデバッグする手順:
oracle.adf.model.binding.DCDataControlクラス内で、アクションまたはメソッド起動をデバッグするエントリ・ポイントとしてinvokeOperation()にブレークを設定します。
一時停止の処理中に、このメソッドをステップ実行して、データ・ウィンドウ内の「instanceName」で、起動されているメソッドが目的のオブジェクトの予測どおりのメソッドであることを確認します。

データ・ウィンドウ内の「args」で、メソッドに渡される各パラメータのパラメータ値が予測どおりの値であることを確認します。下図のパラメータ値では、nullが示されています。

バインディング・コンテナのカスタム・メソッド起動をデバッグする手順:
クラス内で、目的のカスタム・メソッドにブレークポイントを設定します。
oracle.adf.model.generic.DCGenericDataControlクラス内で、invokeMethod()にブレークを設定して、データ・ウィンドウ内を調べる前に処理を停止します。

一時停止の処理中に、このメソッドをステップ実行して、データ・ウィンドウ内の「instanceName」で、起動されているメソッドが目的のオブジェクトの予測どおりのメソッドであることを確認します。

データ・ウィンドウ内の「args」で、メソッドに渡される各パラメータのパラメータ値が予測どおりの値であることを確認します。下図のパラメータ値では、nullが示されています。

無視されているアクションまたはカスタム・メソッドが特定されたら、<executables>要素内の<invokeAction>定義と、pagedef.xmlファイルの<bindings>要素内の対応する<action>および<methodAction>定義が適切な属性設定を指定していることを確認します。
|
ヒント: デバッガが、バインディング・コンテナ内のアクションに設定したブレークポイントに到達しない場合、エラーの原因として最も可能性が高いのは、実行可能ファイルのRefreshおよびRefreshCondition属性の定義内容です。属性定義を調べてください。属性値RefreshおよびRefreshConditionの詳細は、A.6.1項「PageDef.xmlの構文」を参照してください。 |
モデル準備フェーズ中に<invokeAction>実行可能ファイルがリフレッシュされるかどうかは、RefreshおよびRefreshConditionの値(存在する場合)によって決まります。RefreshがprepareModelに設定されているか、値が指定されていない(つまり、デフォルトのifneededが使用される)場合は、RefreshCondition属性値が評価されます。RefreshCondition値が存在しない場合は、実行可能セクションが起動します。RefreshConditionの値が存在する場合は、値が評価され、評価の戻り値がtrueの場合は、実行可能ファイルが起動します。値がfalseと評価された場合は、実行可能ファイルは起動しません。デフォルト値は常に、実行を強制します。
例24-6に、SRDemoアプリケーションのpagedef.xmlファイル内のカスタム・メソッド・バインディング定義のサンプルを示します。
例24-6 ページ定義の実行可能ファイルおよびアクション・バインディングのサンプル
<executables>
<invokeAction id="AlwaysFind" Binds="Find" Refresh="ifNeeded"
RefreshCondition=
"${bindings.SearchServiceRequestsIterator.findMode == false}"/>
<invokeAction id="insertBlankViewCriteriaRowIfThereAreNone" Binds="Create"
Refresh="renderModel"
RefreshCondition=
"${bindings.SearchServiceRequestsIterator.findMode and
bindings.SearchServiceRequestsIterator.estimatedRowCount == 0}"/>
...
</executables>
ELは、特定の障害を通知することを除いて、十分にはサポートされていません。しかし、例24-7に、リゾルバにより完全に式を評価できないときに表示される可能性のある一般的な例外を1つ示します。
例24-7 式評価のPropertyNotFound例外
javax.faces.el.PropertyNotFoundException: Error setting property 'resultsTable' in bean of type null at com.sun.faces.el.PropertyResolverImpl.setValue (PropertyResolverImpl.java:153)
プロパティ名の入力ミスなど、式の中の問題を探すには、Webページのソース・コードを調べることができます。明らかなエラーが見つからない場合は、<JDeveloper_Install>/jre/libディレクトリ内のlogging.propertiesファイルを、ELリゾルバからのメッセージが表示されるように構成します。
EL式の変数をトレースする手順:
テキスト・エディタで<JDeveloper_Install>/jre/lib/logging.propertiesを開きます。
java.util.logging.ConsoleHandler.level=FINEを設定します。
次の行を追加します。
com.sun.faces.level=FINE
アプリケーションを実行し、JDeveloperのログ・ウィンドウ内に変数解決を表示します。
ビジネス・サービスのテストは、アプリケーション開発プロセスの中でも重要な部分です。アプリケーション・モジュールによって提供されている機能を実行する、一連のJunitリグレッション・テストを作成すると、新規機能、不具合の修正、またはリファクタによるアプリケーションの安定性への影響がないことを確認できます。JDeveloperのJUnitリグレッション・テストの作成の統合サポートにより、簡単にこのベスト・プラクティスを理解できます。JUnitテストの実行の統合サポートとは、チームの任意の開発者がマウスを1回クリックするだけでテスト・スイートを実行できることを意味します。このため、すべてのチーム・メンバーが、テストを実行して自身のシステムに対する変更を検証できる機会が大幅に増えます。さらに、Apache Antビルド・スクリプトの作成および実行にJDeveloperの統合サポートを使用して、テストの実行を夜間のビルド・プロセスにも簡単に組み込むことができます。この項では、アプリケーション・モジュールに対するJUnitテストの作成方法、その実行方法およびテストのAntビルド・スクリプトへの統合方法について説明します。
通常、リグレッション・テストを含む個別のプロジェクトを作成します。たとえば、SRDemoアプリケーションには、UnitTestsプロジェクトにJUnitリグレッション・テスト・スイートがありますが、一方で、SRServiceアプリケーション・モジュールを構成するビジネス・コンポーネントは、DataModelプロジェクトに属します。JUnitテスト・スイートを含む新規プロジェクトを作成した後、その新規プロジェクトのコンテキストで、ビジネス・コンポーネントのテスト・スイートの作成ウィザードを使用して、アプリケーション・モジュールに対するJUnitテスト・スイートを作成できます。このウィザードは、「新規ギャラリ」の「General」→「Unit Tests (JUnit)」カテゴリと選択すると表示されます。
|
ヒント: ビジネス・コンポーネントのテスト・スイートの作成ウィザードが表示されない場合は、続行する前にJDeveloperの「ヘルプ」→「更新の確認」機能を使用して、ビジネス・コンポーネントのためのJUnit統合拡張機能をインストールします。 |
テスト・スイート・ウィザードのダイアログが表示される場合、「アプリケーションの選択」ページで次の手順を実行します。
アプリケーション・モジュールが含まれるワークスペースでビジネス・コンポーネント・プロジェクトを選択します。
テスト・スイートを作成する必要のあるプロジェクトで、アプリケーション・モジュールを選択します。
テストの実行に使用する構成名を入力します。
「終了」をクリックして、テスト・スイートを作成します。
ウィザードを使用してアプリケーション・モジュールのJUnitテスト・スイートを作成する場合、JDeveloperでは、そのアプリケーション・モジュールを含むプロジェクトに依存するように現在のプロジェクトが更新されます。さらに、テスト・スイートを作成した対象のアプリケーション・モジュールがdevguide.example.ExampleModuleという名前であると仮定すると、devguide.example.testパッケージで次のスケルトン・クラスが生成されます。
ExampleModuleAllTestsという名前のテスト・スイート・クラス
ExampleModuleConnectFixtureという名前のテスト・フィクスチャ・クラス
アプリケーション・モジュールのデータ・モデルでの各ビュー・オブジェクト・インスタンスに対するViewInstanceNameTestという名前のテスト・クラス
この例では、ExampleModuleAllTestsクラスを実行することにより、いつでもテスト・スイートを実行できます。
仕様では、JUnitテスト・スイートは、junit.frameworkパッケージのTestインタフェースを実装するオブジェクトを戻す、suite()という名前のpublic staticメソッドを含むクラスです。通常、これは同じパッケージ内のTestSuiteクラスのインスタンスになります。生成されたExampleModuleAllTestsクラスはこの仕様に従い、このTestSuiteオブジェクトのインスタンスを作成し、戻します。例24-8に示すとおり、テスト・スイートを戻す前に、addTestSuite()メソッドがコールされ、1つ以上のテスト・ケース・クラスがスイートに追加されます。
例24-8 テスト・ケースをスイートに追加するテスト・スイート・クラス
package devguide.example.test;
import junit.framework.Test;
import junit.framework.TestSuite;
public class ExampleModuleAllTests {
public static Test suite() {
TestSuite suite;
suite = new TestSuite("ExampleModuleAllTests");
suite.addTestSuite(ProductsTest.class);
suite.addTestSuite(ServiceHistoriesTest.class);
suite.addTestSuite(ServiceRequestsTest.class);
// etc.
return suite;
}
}
生成されたExampleModuleConnectFixtureは、アプリケーションの取得および解放の詳細をカプセル化する、JUnitテスト・フィクスチャです。これには、アプリケーション・モジュールのインスタンスを作成するためにConfigurationクラスのcreateRootApplicationModule()メソッドを使用する、setUp()メソッドが含まれます。tearDown()メソッドは一致するreleaseRootApplicationModule()メソッドをコールして、アプリケーション・モジュールのインスタンスを解放します。
各テスト・ケース・クラスには、テスト・ケースによって必要とされるリソースの初期化を可能にし、その後それらをクリーン・アップするためにJUnitによって起動される、setUp()およびtearDown()メソッドが含まれます。これらのテスト・ケース・メソッドは、対応するsetUp()およびtearDown()メソッドを起動して、各テスト・ケース実行のテキスト・フィクスチャを準備およびクリーン・アップします。テスト・ケース内のテストの1つがアプリケーション・モジュールへのアクセスを必要とする場合は常に、テキスト・フィクスチャのgetApplicationModule()メソッドを使用してアプリケーション・モジュールにアクセスします。これは、テスト・ケースの最後で、setUp()への最初のコールからtearDown()への最後のコールまでの間に、テスト・フィクスチャ・クラスのメンバー・フィールドに保存された、同じアプリケーション・モジュールのインスタンスを戻します。
JUnitテスト・スイートに対して使用するアプリケーション・モジュール構成は、JDBCデータソースではなく、JDBC URL接続を使用する必要があります。これは、JDBCデータソースがJ2EEアプリケーション・サーバーによって定義され、サーバー内部で実行するアプリケーションのコンテクストでのみ参照可能なためです。JUnitテストは、サーバー環境の外部で実行します。たとえば、SRDemoアプリケーションには、そのSRServiceアプリケーション・モジュールに定義された2つの構成があります。SRServiceLocal構成はJDBCデータソースを使用します。これは、SRDemoアプリケーションでの使用についてUserInterfaceプロジェクトのDataBindings.cpxファイルで参照されます。これに対して、SRDemoのJUnitテストは、SRServiceLocalTesting構成を参照します。これはデータソースのかわりにJDBC URL接続を使用します。
生成されたテスト・ケースそれぞれに、そのテスト・ケース実行の一部としてJUnitフレームワークが実行する1つ以上のテスト・メソッドを含めることができます。接頭辞testで始まる名前を持つクラスでpublic voidメソッドを作成するのみで、テストをテスト・ケースに追加できます。たとえば、次のようになります。
// In ViewInstanceNameTest.java test case class public void testSomeMeaningfulName() { // test assertions here }
ウィザードにより、データ・モデルの各ビュー・オブジェクト・インスタンスに対してスケルトン・テスト・ケースが生成されます。各テスト・ケースには、testAccess()という名前の単一テスト・メソッドが含まれます。このメソッドには、ビュー・オブジェクト・インスタンスの存在をテストするためのassertNotNull()メソッドへのコールが含まれます。
自身のテスト・メソッドでは、oracle.jboパッケージで使用可能な任意のプログラムのAPIを使用して、アプリケーション・モジュールおよびそのデータ・モデル内のビュー・オブジェクト・インスタンスを扱うことができます。また、ApplicationModuleインタフェースをカスタム・インタフェースにキャストして、テストがそのジョブの一部としてカスタム・サービス・メソッドを起動するようにします。それぞれのテスト中に、JUnitフレームワークによって提供されている1つ以上のassertXxxx()メソッドをコールして、特定の式の予測結果がどのようになる必要があるかをアサートします。テスト・スイートを実行する際、任意のテスト・ケースの任意のテストに失敗したアサーションが含まれる場合、JDeveloperのJUnitテスト・ランナー・ウィンドウに失敗したテストが赤の失敗アイコンとともに表示されます。
Apache Antは、JDeveloperによる優れた設計時サポートが提供されている、一般的なクロス・プラットフォーム・ビルド・ユーティリティです。Antの組込みjunitおよびjunitreportタスクを使用することにより、JUnitテストの自動実行とテスト出力レポート生成を組み込むことができます。例24-9では、BuildAndDeployプロジェクトのSRDemoのAnt build.xmlファイルからのtestsと呼ばれるタスクを示します。これは、testsターゲットを実行する前にAntが確実に実行しているbuildおよびbuildTestsターゲットに依存します。
junitタグには、実行するテスト・スイート・クラスを識別するネストされたテスト・タグが含まれ、結果をレポートするディレクトリが指定されます。junitreportタグにより、JavaDocの形式に類似するHTMLページのコレクションにテスト結果を書式設定できるようになります。このAntタスクからSRDemoのJUnitテストを試行するには、アプリケーション・ナビゲータでbuild.xmlファイルを選択し、ポップアップ・メニューから「Antターゲットの実行」→「テスト」を選択します。
例24-9 JUnitテスト・スイートを実行してレポートを生成するAntビルド・ターゲット
<!-- In SRDemo's build.xml -->
<target name="tests" description="Run the model layer Unit tests"
depends="build, buildTests">
<mkdir dir="${tests.reporting.dir}"/>
<junit printsummary="true" fork="true">
<formatter usefile="true" type="xml"/>
<test name="oracle.srdemo.tests.model.SRServiceAllTests"
todir="${tests.reporting.dir}"/>
<sysproperty key="jbo.debugoutput" value="file"/>
<classpath path="${model.build.dir}"/>
<classpath path="${tests.build.dir}"/>
<classpath refid="tests.classpath"/>
</junit>
<junitreport todir="${tests.reporting.dir}">
<fileset dir="${tests.reporting.dir}">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${tests.reporting.dir}"/>
</junitreport>
</target>
SRDemoのUnitTestプロジェクトには、生成されたテスト・ケース・クラスに適用できる、いくつかのカスタマイズ例が含まれています。この項では、特定ユーザーを認証するためのテキスト・フィクスチャのカスタマイズ方法、および共通テスト・ケース・コードをベース・クラスにリファクタする方法について説明します。
SRServiceFixtureには、ユーザー名とパスワードを承認するカスタム・コンストラクタがあります。そのsetUp()メソッドでは、カスタムADF Business Components EnvInfoProvider実装を使用して、アプリケーション・モジュールに実行時構成パラメータを指定します。特に、指定されたパスワードのある指定ユーザー名として認証するには、JUnitFixureLoginInfoProviderクラスがEnvInfoProviderインタフェースのgetInfo()メソッドを実装し、次のものを戻します。
jbo.security.enforceプロパティに対する値Must
java.naming.security.principalプロパティに対するユーザー名の値(JboContext.SECURITY_PRINCIPAL定数を使用して参照される)
java.naming.security.credentialsプロパティに対するパスワードの値(JboContext.SECURITY_CREDENTIALS定数を使用して参照される)
oracle.srdemo.tests.model.unittestsパッケージの3つのテスト・ケースそれぞれが、ユーザー名とパスワードの値の様々な組合せで独自のSRServiceFixtureのインスタンスを作成します。たとえば、SRServiceTestAsManagerRoleテスト・ケースは、マネージャ・ロール(sking)を持つユーザーに対してSRServiceFixtureを作成します。他の2つのテストもそれぞれ同じことを別の2つのロールTechnicianとManagerのユーザーに対して行います。
|
ヒント: SRDemoのUnitTestsプロジェクトには、そのプロジェクトのコンテンツ・パスの1つとしてConfigurationDataディレクトリが含まれます。これにより、デモに対するすべてのユーザーとロールを定義するjazn-data.xmlファイル(META-INFサブディレクトリに含まれる)が、実行時にJUnitテストによって読取り可能であることが保証されます。*.xmlファイル拡張子は、デフォルトで「プロジェクト・プロパティ」ダイアログの「コンパイラ」ページの「ファイル・タイプの出力ディレクトリへのコピー」フィールドに含まれるため、プロジェクト・ソース・パスのXMLファイルは、コンパイル時にプロジェクトの出力ディレクトリにコピーされます。 |
3つのテスト・ケース・クラスすべてによりSRUnitTestBaseクラスが拡張されます。このクラスには、すべてのテスト・ケースに共通のコードが含まれます。たとえば、現在日付の取得、文字列化されたキーによるビュー・オブジェクトの現在行の設定、指定されたビュー・オブジェクトに対する適切なタイプのキーの作成のためのいくつかのヘルパー・メソッドが含まれます。また、認証のための適切なユーザー名とパスワードで構成されたSRServiceFixtureを戻すため、各サブクラスがオーバーライドするabstractメソッドcreateSRServiceFixtureForTest()を定義します。