サーバー・スクリプト
アプリケーション・コンポーザでは、アプリケーションの拡張に使用するスクリプト言語としてGroovyがサポートされています。 Groovyスクリプトを使用できる様々なコンテキストがあります。
このトピックでは、標準オブジェクトまたはカスタム・オブジェクトに対してサーバー・スクリプト・ノードを使用して定義できる検証ルール、トリガーおよびオブジェクト関数の使用について説明します。 アプリケーション・コンポーザを使用したGroovyスクリプトの詳細は、Groovyスクリプト・リファレンス・ガイドを参照してください。
標準オブジェクトまたはカスタム・オブジェクトに対して定義できるサーバー・スクリプトには、次のものがあります:
-
検証ルール
フィールドまたはオブジェクトのいずれかを検証するスクリプトを記述します。
-
トリガー
特定のトリガー・イベントが発生するたびにアクションを自動的に実行するトリガー・スクリプトを記述します。
-
オブジェクト関数
複数のコンテキストで再利用できる関数を記述します。 たとえば、トリガーまたは検証ルール内でオブジェクト関数を再利用できます。
検証ルール
検証ルールは、フィールドまたはオブジェクトで定義できる制約です。 フィールドまたはオブジェクトを保存する前に検証する式または長いスクリプトを記述します。 標準オブジェクトまたはカスタム・オブジェクトのサーバー・スクリプト・ノードを使用して、検証ルールを定義します。
-
要件に単一のフィールドが含まれる場合は、フィールドレベルの検証を使用します。
フィールド・レベルの検証ルールは、標準フィールドまたはカスタム・フィールドに対して定義できる制約です。 ルールは、対応するフィールドの値が設定され、ユーザーがフィールドからタブで移動するたびに実行時に評価されます。 ルールが実行されると、フィールドの値がまだ割り当てられず、ルールが成功した割当てまでゲート・キーパーとして機能します。 フィールド・レベルで検証ロジックをカバーすると、保存時のGroovy実行のオーバーヘッドが軽減されます。 可能な場合は常にこのオプションを使用します。
ノート: 動的選択リストはフィールド・レベルの検証ルールをサポートしていません。たとえば、優先度フィールドを含むカスタムTroubleTicketオブジェクトを考えてみます。 フィールド・レベルの検証ルールを設定して、入力した数値が1から5の間であることを検証できます。
記述する式(または長いスクリプト)は、値が有効かどうかを示すブール値を返す必要があります。
-
ルールがtrueを返す場合、同じフィールドの他のすべてのフィールド・レベル・ルールもtrueを返すかぎり、フィールド割当は成功します。
-
ルールでfalseが返された場合、フィールド割当は発生しません。 また、無効なフィールドがUIで視覚的に強調表示され、構成されたエラー・メッセージがエンド・ユーザーに表示されます。 この状況では割当てが失敗するため、フィールドには現在の値が保持されます(以前の値がnullだった場合はnullになる可能性があります)。 ただし、webページのUIコンポーネントを使用すると、ユーザーは無効なエントリを表示して修正し、再試行できます。
Groovyスクリプト・リファレンス・ガイドのフィールドレベル検証ルールの定義を参照してください。
-
-
オブジェクト内の複数の関連フィールドで検証が必要な場合は、オブジェクトレベルの検証ルールを使用します。 これは、標準オブジェクトまたはカスタム・オブジェクトに対して定義できる制約です。
オブジェクト・レベルのルールを使用して、オブジェクトの複数のフィールドに依存する条件を適用します。 これにより、ユーザーが値を割り当てる順序に関係なく、ルールが一貫して適用されます。 フレームワークがオブジェクトを検証しようとすると、ルールが評価されます。 この検証は、たとえば、Webフォームで変更を送信するとき、ある行から別の行にナビゲートするとき、およびオブジェクトに対する変更が保存されるときに発生します。 (ルールが評価されるのは、ユーザーがレコードを変更せずに保存した場合です。)
たとえば、優先度およびAssignedToフィールドを含むTroubleTicketオブジェクトについて考えてみます。後者は、タイプ・フィールドがスタッフ・メンバーである連絡先オブジェクトを参照する動的選択リスト・フィールドです。 オブジェクト・レベルの検証ルールを設定して、優先度1または2の問題チケットをスタッフに割り当てないと保存できないことを検証できます。
記述する式(または長いスクリプト)は、オブジェクトが有効かどうかを示すブール値を返す必要があります:
-
ルールがtrueを返す場合、同じオブジェクト上の他のすべてのオブジェクト・レベル・ルールがtrueを返すかぎり、オブジェクト検証は成功します。
-
ルールでfalseが返された場合、この結果によりオブジェクトが保存されなくなり、構成されたエラー・メッセージがエンド・ユーザーに表示されます。
Groovyスクリプト・リファレンス・ガイドのオブジェクト・レベルの検証ルールの定義に関する項を参照してください。
-
トリガー
トリガーは、標準オブジェクトまたはカスタム・オブジェクトのデフォルト処理ロジックを補完するために記述できるスクリプトです。 特定のイベントが発生すると、トリガー定義で指定したアクションが自動的に実行されます。 トリガーは、標準オブジェクトまたはカスタム・オブジェクトの「サーバー・スクリプト」ノードを使用して、オブジェクト・レベルとフィールド・レベルの両方で定義できます。 オブジェクト・トリガーを定義して、レコードの作成、更新、削除などの標準処理ロジックを拡張します。
トリガーを定義するときに、スクリプトを自動的に実行する特定のイベントを選択します。 この特定のイベントはトリガーとも呼ばれます。 Oracleでは、トリガー・スクリプトを定義する際に選択できる、これらのトリガー・イベントのセット番号が提供されます。
トリガーを定義する際の正しいトリガー点を選択します:
-
フィールドレベルのトリガーは、別のフィールド値の変更に応じてアクションを実行するために作成するスクリプトです。 フィールド・レベルでトリガーを定義する場合は、「フィールドの変更後」トリガーと、このトリガーが監視するフィールドを選択します。 次に、フィールドの値が変更されたときに実行するアクションを定義します。
指定したフィールドの値が変更されると、「フィールドの変更後」トリガーによって他の導出フィールド値が計算されます。 フィールドレベルの検証ルールが成功しても、他のフィールドレベルの検証ルールが失敗し、フィールドの値が実際に変更されない可能性があるため、この目的を達成するためにフィールドレベルの検証ルールを使用しないでください。 通常、フィールド変更導出ロジックはフィールドの値が変更された場合にのみ実行する必要があるため、フィールド変更後トリガーによってこの動作が保証されます。
Groovyスクリプト・リファレンス・ガイドの「値の変更に対応するためのフィールド・レベルのトリガーの定義」を参照してください。
-
同様に、オブジェクト・レベルのトリガーは、特定のイベントが発生したときにアクションを実行するスクリプトです。 オブジェクト・レベルのトリガーでは、次のような多くのトリガー・イベントを選択できます:
-
作成後
新しいオブジェクト・レコードが作成されたときに起動します。 通常、フィールドのデフォルト値を設定するために使用されます。
-
Before Invalidate
子オブジェクト・レコードのいずれかが作成、更新または削除されると、親オブジェクトで起動します。 関係ロジックで構築する場合。
-
削除前
オブジェクト・レコードの削除が試行されたときに起動します。 削除を防止する条件の作成に使用できます。
-
データベースでの挿入の前
新しいオブジェクトがデータベースに挿入される前に起動します。 依存レコードが存在することを確認したり、重複を確認するために使用できます。
-
データベースでの更新の前
既存のオブジェクトがデータベースで変更される前に起動します。 依存レコード値のチェックに使用できます。
-
データベースでの削除の前
既存のオブジェクトがデータベースから削除される前に起動します。 依存レコード値のチェックに使用できます。
-
データベースでのロールバックの前
-
データベースへの変更のポストの後
すべての変更がデータベースにポストされた後、永続的にコミットされる前に起動します。 現在のトランザクションの一部として保存される追加の変更を行うために使用できます。
たとえば、トラブル・チケットが作成されるたびに更新する必要があるOpenTroubleTicketsフィールドを持つContactオブジェクトを考えてみます。 「変更がデータベースに転記された後」トリガー・イベントを使用して、TroubleTicketオブジェクトにトリガーを作成できます。 イベントが発生すると、トリガーはOpenTroubleTicketsフィールドを新しい数で自動的に更新できます。
選択できるトリガー「イベント」の完全なリストは、Groovyスクリプト・リファレンス・ガイドの「デフォルト処理を完了するためのオブジェクト・レベル・トリガーの定義」を参照してください。
-
最適なパフォーマンスを得るには、トリガーを使用する際に次のガイドラインに従ってください:
-
オブジェクト当たり10個のトリガーを超えないようにしてください。
-
単一のトリガー内で論理的に関連するアクションを結合します。 1つのトリガーによって、複数のトリガーよりもパフォーマンスが向上します。
-
トリガーを定義する際は、正しいトリガー・ポイントを選択します。
-
トリガー内で検証ロジックを使用しないでください。 かわりに、検証ロジックに対して検証ルールを使用します。
-
newView() APIを使用する前に、関連オブジェクトまたは関連コレクション・アクセッサがすでに存在するかどうかを確認します。
関係がすでに存在する場合は、newView()を使用してオブジェクトを問い合せないでください。 これにより、追加の問合せの起動が回避されます。
-
オブジェクトをプログラムで問い合せる場合は、基礎となる問合せが制限されるように、効率的なビュー基準を選択します。
オブジェクト関数とグローバル関数
再利用可能なコードは、オブジェクト関数またはグローバル関数のいずれかとして記述できます。 複数の異なるコンテキストから同じコードを呼び出す予定がある場合は、関数を使用します。 オブジェクト関数は、同じオブジェクト内の任意のスクリプトによってコールすることも、ユーザー・インタフェースのボタンによってトリガーすることもできます。 グローバル関数は、任意のオブジェクトのスクリプトまたはその他のグローバル関数から呼び出すことができます。
-
オブジェクト関数は、特定のオブジェクト固有のビジネス・ロジックをカプセル化するコードに役立ちます。 同じオブジェクトに関連する他のスクリプトから、オブジェクト関数を名前で呼び出すことができます。 また、ユーザー・インタフェースでボタンまたはリンクを使用してコールできます。
サポートされている戻り型とオプションのパラメータ型は、グローバル関数と同じです。 関数の戻り値およびパラメータの最も一般的なタイプのリストは、Groovyスクリプト・リファレンス・ガイドのグローバル関数でのユーティリティ・コードの定義を参照してください。
Groovyスクリプト・リファレンス・ガイドのオブジェクト関数を使用した再利用可能な動作の定義も参照してください。
-
グローバル関数は、複数のオブジェクトが共有するコードに役立ちます。 Groovyスクリプトを使用したユーザー定義関数を記述し、アプリケーション・コンポーザ全体を通してすべてのGroovyスクリプト・エディタで参照できます。 たとえば、2つのグローバル関数を作成して、Groovyスクリプトのブロックの開始を記録し、診断メッセージを記録する標準ヘルパー・ルーチンを定義できます。
グローバル関数を呼び出すには、関数名の前にadf.util.プレフィクスを付けます。 関数を定義する場合は、戻り値を指定し、オプションで、呼び出し元が呼び出されたときに渡す必要がある1つ以上の型付きパラメータを指定できます。
関数の戻り値およびパラメータの最も一般的なタイプのリストは、Groovyスクリプト・リファレンス・ガイドのグローバル関数でのユーティリティ・コードの定義を参照してください。
-
パフォーマンスを最適化するために、フェッチできるレコードの最大数は500レコードに制限されます。 選択したデータ・サイズが原因でジョブがExprTimeoutExceptionで失敗する場合は、setMaxFetchSizeを使用してデータ・サイズを小さくしてください。 または、選択的フィルタリングを使用して、ビュー・オブジェクトでフェッチされたレコード数を500レコード未満にフィルタします。
特権関数
オブジェクト関数またはグローバル関数のいずれかを定義すると、実行時ユーザーがレコードを作成または更新する権限を持たないオブジェクトに対して関数が実行されることがあります。 オブジェクトのデータへのアクセス権がないユーザーが、次の2つの操作を実行して、完全なアクセス権を持つファンクションを実行できるようにします:
-
関数の定義時に、権限チェック・ボックスを選択して、その機能が特権であることを示します。
-
オブジェクト関数を正常に実行できるように、権限付きスクリプト管理ロールに適切なレベルのアクセス権があることを確認します。 オブジェクトへのアクセス権は自動的に付与されません。 かわりに、アプリケーション・コンポーザのセキュリティUIを使用してアクセス権を付与する必要があります。
実行時に、ユーザーがUIから特権関数を起動すると、一時ログイン・セッションが特権ロールである特権スクリプト管理(ORA_CRM_EXTN_PRIVILEGE_SCRIPT_ROLE)でアクティブ化されます。 この特権ロールは機能内のオブジェクトにアクセスできるため、権限の問題はありません。 一時ログイン・セッションは、単一の関数呼び出しの期間中、または関数が内部的に呼び出すすべての期間だけ継続します。
たとえば、セールス要員は、取引先レコードではなく商談レコードにのみアクセスできます。 営業担当が商談を編集するとき、権限のあるGroovyスクリプトを使用して関連アカウントを更新するボタンがあります。 営業担当にはアカウント・オブジェクトに対する更新権限がありませんが、営業担当がボタンをクリックすると、権限のあるGroovyスクリプトが実行され、権限のあるロール・コンテキストに切り替えてアカウント・レコードの更新が完了します。
これを行うには、アプリケーション・コンポーザ・セキュリティUIを使用して、特権ロールである特権スクリプト管理へのアカウント・アクセス権を付与します。