19 ADFモデル・レイヤーでの検証の使用
この章の構成は、次のとおりです。
ADFモデル・レイヤー検証について
Modelレイヤーでは、ADFモデル検証規則を特定のページのバインディングの属性として設定できます。ユーザーがフィールド内のデータを編集または入力してフォームを送信したときに、設定した規則および条件に対してバインドされたデータが検証されます。検証が失敗すると、アプリケーションによりエラー・メッセージが表示されます。
エンティティ・オブジェクトのビジネス・ドメイン・レイヤーに検証規則をすでに設定している場合は、ADFモデル検証を追加する必要はありません。ADFビジネス・コンポーネント・ベースのFusion Webアプリケーションでは、アプリケーション・モジュールのデータ・コントロール以外のデータ・コントロールを使用しないかぎり、ADFモデル検証を使用する必要はありません。
ADFモデル・レイヤー検証のユースケースと例
アプリケーションでADFビジネス・コンポーネントに基づかないデータ・コントロールを使用している場合は、ADFモデル・レイヤー検証を使用してユーザーが入力したデータの品質を確保できます。
ベスト・プラクティス:
可能な場合はビジネス・レイヤー検証を使用します。ただし、次の例に示すような場合には、モデル・レイヤー検証の使用が必要になる場合があります。
-
ビジネス・レイヤーが宣言的検証をサポートしていない場合。
-
負荷の高いラウンドトリップ(Webサービスとのバインドなど)が開始される前に検証を実行する場合。
-
パラメータを使用して作成されたフォームを検証する必要がある場合(
executeWithParams
操作を使用する場合など)。
また、サーバーとのラウンドトリップの前に検証を実行する場合、クライアント側の検証を使用することもできます。詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の検証の追加に関する項を参照してください。
アプリケーションで、ビジネス・レイヤー検証に加えてモデル・レイヤー検証の使用も保証されている場合は、ADFビジネス・コンポーネント・オブジェクトで利用できる宣言的検証機能の多くをモデル・レイヤーでも利用できます。
ADFモデル・レイヤー検証の追加機能
モデル・レイヤー認証を使用する前に、他のADF検証機能を理解しておくと役立つ場合があります。次に、関連する他の機能へのリンクを示します。
-
ADFビジネス・コンポーネント・アプリケーション・モジュールのデータ・コントロールを使用する場合、モデル・レイヤー検証を使用する必要はありません。可能であれば、すべての検証規則を、ビジネス・レイヤー内の再使用と管理が容易で一元管理されたエンティティ・オブジェクトに定義することを検討してください。詳細は、「検証とビジネス・ルールの宣言的な定義」を参照してください。
-
ページ・レベルで利用できる宣言的検証機能の多くは、Beanレベルでも利用できます(その場合はデータ・コントロール構造ファイルで実装します)。データ・コントロール構造ファイルの検証規則は、データ・コントロールが使用されるすべての場合に適用されるため、非常に役立ちます。データ・コントロール構造ファイルでの検証ルールの実装の詳細は、『Oracle ADFデータ・コントロールによるアプリケーションの開発』の「データ・コントロールへのビジネス・ロジックの追加」を参照してください。
ADFモデル・レイヤーでの検証規則の定義
バインディングの属性に対するADFモデル検証は、ページ定義ファイルで構成できます。モデル・レイヤーの検証規則は、特定のページのバインディング属性に対して、その対象を含むフォームの送信時に実行されます。
オプションで、skipValidation
プロパティをtrue
に設定すると、ADFモデル検証をバイパスできます。skipValidation
をskipDataControls
に設定して、トランザクションを検証せずに、バインド・オブジェクトを検証できます。たとえば、データ入力を受け付けるポップアップ・ウィンドウを開く表アクションがあるときに、表でコミットする前にビュー・レイヤーでこれらの入力を検証できるようにする場合は、skipValidation
をskipDataControls
に設定します。skipValidation
プロパティは、「構造」ウィンドウでページ定義ファイルのルート・ノードを選択した後に、「プロパティ」ウィンドウに表示されます。
ADFモデル・レイヤー検証の追加方法
ADFモデル検証をページ定義ファイルに設定します。検証規則を定義し、規則に違反した場合に表示するエラー・メッセージを設定します。
表19-1に、バインディングの属性に対して構成できるADFモデル検証規則を示します。
表19-1 ADFモデル検証規則
バリデータ・ルール名 | 説明 |
---|---|
比較 |
属性の値とリテラル値を比較する。 |
リスト |
値が値リスト内にあるかどうかを検証する |
範囲 |
値が値範囲内にあるかどうかを検証する。 |
長さ |
値の文字またはバイト・サイズをサイズおよびオペランド(greater than or equal toなど)に対して検証する。 |
正規表現 |
Java正規表現構文を使用してデータを検証する。 |
必須 |
属性にその値が存在するかどうかを検証する。 |
始める前に:
モデル・レイヤーでの検証規則の使用に関する知識があると役立つ場合があります。詳細は、「ADFモデル・レイヤーでの検証規則の定義」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「ADFモデル・レイヤー検証の追加機能」を参照してください。
次のタスクを完了する必要があります。
-
ページにコンポーネントを作成します。このコンポーネントにはバインディング属性が必要です。
ADFモデル検証規則を作成するには:
- 「アプリケーション」ウィンドウで、ルールを作成するバインディングを含むページ定義をダブルクリックします。
- 「構造」ウィンドウで、属性、リストまたは表バインディングを選択します。
- 「プロパティ」ウィンドウで、「詳細」ドロップダウン・メニューをクリックし、「検証ルールの編集」を選択します。
- 「検証ルール・エディタ」ダイアログで、バインディング・ノードを開き、属性名を選択して、「新規」をクリックします。
- 「検証ルールの追加」ダイアログで、検証規則を選択し、必要に応じて規則を構成します。
- 「失敗処理」タブをクリックして、ルールに違反した場合に表示するメッセージを構成します。
実行時に行われる処理: Model検証規則
ユーザーがデータを送信すると、送信された値がNULL以外の値か、少なくとも1つの文字からなる文字列値であった場合、コンポーネントに設定されているすべてのバリデータが1つずつコールされます。コンポーネントのf:validator
タグはバインディングのvalidator
プロパティにバインドされるため、モデルに設定されている検証ルーチンがアクセスされて実行されます。
続いて、プロセスは次のコンポーネントに進みます。すべての検証が正常に完了すると、モデル値更新フェーズが開始され、ローカル値を使用してモデルが更新されます。いずれかの検証が失敗すると、現在のページがエラー・メッセージとともに再表示されます。
デフォルトのエラー処理に関する必知事項
例外が発生すると、デフォルトの動作ではADF Facesのエラー・ダイアログにリーフレベル・エラーのみ表示されます。ADFコントローラのデフォルトのエラー処理メカニズムは、ページ・バインディング・コンテナから例外のリストを取得し、各エラーの表示方法を決定します。例外がJboException
でない場合、Facesエラー・メッセージが例外メッセージとともに表示されます。
例外がJboException
の場合、エラー処理メカニズムはネストされた例外に再帰的にドリル・ダウンし、一意の例外ごとに単一のFacesエラー・メッセージを表示します。ただし、例外にJboWarning.HIDE_DETAIL_EXCEPTIONS_HINT
がある場合、エラー処理メカニズムはネストされた例外にドリル・ダウンしません。
また、エラー処理メカニズムは、各例外のバインディング・エラーのリストを取得し、エラーをレポートしたバインディングに関連付けられているコンポーネントに対するFacesエラー・メッセージを表示します。
エラー処理のカスタマイズ
デフォルトのDCErrorHandlerImpl
クラスを拡張するカスタム・エラー・ハンドラを使用して、エラーをレポートできます。カスタム例外ハンドラ・クラスを登録するためにコードを記述する必要はありません。かわりに、「構造」ウィンドウでDataBindings.cpx
ファイルのルート・ノードを選択した後、「プロパティ」ウィンドウを使用してErrorHandlerClass
プロパティを、使用するエラー・ハンドラの完全修飾名に設定します。
カスタム・エラー・ハンドラには、次のオーバーライド可能なメソッドを含めることができます。
-
reportException()
: 発生した例外をレポートするためにコールされます。レポートされた例外を分析するようにオーバーライドできます。 -
getDisplayMessage()
: 発生したエラーごとにJSFにレポートされるメッセージを戻します。カスタム・エラー・ハンドラで特定の例外をクライアントにレポートする必要がない場合は、null
を戻します。 -
getDetailedDisplayMessage()
: 発生したエラーごとにJSFにレポートされるメッセージの詳細部分を、String
オブジェクトまたはHTMLとして戻します。カスタム・エラー・ハンドラで特定の例外をクライアントにレポートする必要がない場合は、null
を戻します。 -
skipException()
: ユーザー向けに表示される最終的なエラー・リストに、ネストされた例外から各アイテムを表示するかどうかに応じたブール値を戻します。このメソッド・オーバーライドにより、特定の例外タイプをチェックし、ビジネス・シナリオに基づいて、このタイプをリストに表示するかどうかを判断するロジックを実装できます。
次の例は、DCErrorHandlerImpl
クラスを拡張するカスタム・エラー・ハンドラを示し、ユーザーに対して表示されるリストに出現すべきでない例外をスキップするために必要なskipException()
メソッドに対するオーバーライドを示しています。
package view.controller.fwkext; import java.sql.SQLIntegrityConstraintViolationException; import java.util.ArrayList; import java.util.List; import oracle.adf.model.binding.DCBindingContainer; import oracle.adf.model.binding.DCErrorHandlerImpl; import oracle.jbo.CSMessageBundle; import oracle.jbo.DMLConstraintException; import oracle.jbo.JboException; public class CustomErrorHandler extends DCErrorHandlerImpl { List<ExceptionMapper> exceptionMapperList = new ArrayList<ExceptionMapper>(); public CustomErrorHandler() { super(); exceptionMapperList.add(new DisableJboExceptionCodesMapper()); } public void reportException(DCBindingContainer bc, Exception ex) { for (ExceptionMapper mapper : exceptionMapperList) { if (mapper.canMapException(ex)) { ex = mapper.mapException(ex); } } super.reportException(bc, ex); } /** * If an exception is a RowValException or a TxnValException and they * have nested exceptions, then do not display it. This example shows * an implementation that skips the SQLIntegrityConstraintViolationException * from displaying in the error final list displayed to the user. */ @Override protected boolean skipException(Exception ex) { if (ex instanceof DMLConstraintException) { return false; } else if (ex instanceof SQLIntegrityConstraintViolationException) { return true; } return super.skipException(ex); } }
エラー・ハンドラ・クラスには、カスタム・クラスの名前と一致するデフォルトのコンストラクタが必要です。たとえば、カスタム・ハンドラ・クラスMyErrorHandler
を作成した場合、例外エラー・ハンドラは、次の例に示すようにデフォルトのコンストラクタを起動します。この規則に従うと、クラス名のみで動的な起動が可能になります。
ErrorHandlerClass="viewcontroller.MyErrorHandler" public MyErrorHandler() { super(); }
メッセージの詳細部分のカスタマイズ方法
メッセージの詳細部分をカスタマイズし、使用する予定のある場合は、このメッセージを取得し、処理するために、カスタム・エラー・ハンドラを作成し、getDetailedDisplayMessage
メソッドを実装することができます。最終的なメッセージは、ビュー・レイヤーに渡され、他のメッセージと統合されます。
メッセージの詳細部分をカスタマイズするには:
HTMLタグを使用してメッセージを書式化するには、例に示すように、メッセージを<html></html>
タグで囲む必要があります。エラー・メッセージでは次のHTMLタグのみを使用できます。
-
<span>
-
<b>
-
<a>
-
<i>
-
<em>
-
<br>
-
<hr>
-
<li>
-
<ol>
-
<ul>
-
<p>
-
<tt>
-
<big>
-
<small>
-
<pre>
カスタム・エラー・ハンドラから情報メッセージを表示する方法
エラー・ハンドラを使用すると、ADFモデル・レイヤーのカスタム検証を使用してアプリケーションの警告に対して情報メッセージを表示できます。モデル・レイヤー検証を使用するアプリケーションでは、すべてのエラーと警告について、アプリケーションCPXレベルでカスタム・エラー・ハンドラを使用する必要があります。
始める前に:
モデル・レイヤーでのカスタム検証の動作に関する知識があると役立つ場合があります。詳細は、「エラー処理のカスタマイズ」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「ADFモデル・レイヤー検証の追加機能」を参照してください。
JDeveloperを起動し、カスタム・エラー・ハンドラを追加するアプリケーションを開く必要もあります。
情報メッセージを表示する手順
複数スレッドを処理するエラー・ハンドラの記述方法
Oracle ADFでは、作成されるBindingContext
オブジェクトごとにカスタム・エラー・ハンドラのインスタンスを1つ作成します。Oracle ADFでは、同じ論理エンド・ユーザー・セッションからの同時Webリクエストをシリアライズするため、通常、複数スレッドは同じエラー・ハンドラを同時に使用しません。ただし、スレッドセーフのカスタム・エラー・ハンドラを保証するには、JboException
でsetProperty()
APIを使用します。このメソッドは、表示用に例外がJSF FacesMessage
オブジェクトに変換されるときに、後で必要になる可能性があるヒントをすべて例外オブジェクト自体に格納します。