この章では、Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成する方法と、Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するために実行する必要があるOracle Databaseタスクについて説明します。
PL/SQLプロシージャを作成してジョブ定義を定義すると、Oracle Enterprise Schedulerランタイム・サービスを使用して、PL/SQLプロシージャに対するジョブ・リクエストを発行できるようになります。
この章では、次の項目について説明します。
ランタイム・サービスの使用方法の詳細は、第14章「ランタイム・サービスの使用」を参照してください。
Oracle Enterprise Schedulerを使用すると、Javaクラス、PL/SQLストアド・プロシージャ、分岐プロセスとして実行されるプロセス・リクエストなど、様々なタイプのジョブ・リクエストを実行できます。Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、次を実行する必要があります:
Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成または取得します。
PL/SQLストアド・プロシージャをOracle Databaseにロードして必要な権限を付与し、その他の必要なDBAタスクを実行します。
Oracle JDeveloperを使用してジョブ・タイプおよびジョブ定義オブジェクトを作成し、それらのオブジェクトをOracle Enterprise Schedulerアプリケーション・メタデータとともに格納します。
Oracle JDeveloperを使用して、PL/SQLストアド・プロシージャを実行および発行するOracle Enterprise Scheduler APIを持つアプリケーションを作成します。
最後に、Oracle Enterprise Scheduler APIを使用するアプリケーションを作成したら、Oracle JDeveloperを使用してアプリケーションをデプロイして実行します。
実行時に、ジョブ・リクエストを発行した後、ジョブ・リクエストを監視および管理できるようになります。詳細は、第14章「ランタイム・サービスの使用」を参照してください。
Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャ・ジョブ・リクエストに非同期実行モデルを使用します。つまり、Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャを直接コールするのではなく、Oracle Enterprise Scheduler (Oracle Databaseに含まれる)を使用します。PL/SQLストアド・プロシージャ・ジョブ・リクエストを実行する準備が整うと、Oracle Enterprise Schedulerにより、即時に1回のみ実行されるOracle Enterprise Schedulerジョブが作成されます。このOracle Enterprise Schedulerジョブは、PL/SQLストアド・プロシージャを指定するアプリケーションを実行するコンテナ・インスタンスに関連付けられているOracle Enterprise Schedulerランタイム・スキーマ・ユーザーによって所有されます。最後に、Oracle Enterprise Schedulerジョブが実行されると、PL/SQLストアド・プロシージャが動的SQLを使用してコールされます。PL/SQLストアド・プロシージャが(正常な戻り値または例外の発生によって)完了すると、Oracle Enterprise Schedulerジョブが完了します。
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、PL/SQLプロシージャに、Oracle Enterprise Schedulerアプリケーションで動作するための特定の特性がある必要があり、かつ、特定のOracle Database権限がPL/SQLストアド・プロシージャに割り当てられていることをDBAが確認する必要があります。
PL/SQLストアド・プロシージャの作成には、次のステップが含まれます。
Oracle Enterprise Schedulerで使用するための正しいシグネチャを持つPL/SQLストアド・プロシージャを定義します。
PL/SQLストアド・プロシージャをOracle Enterprise Schedulerで使用できるようにするために必要なDBAタスクを実行します。
Oracle Enterprise SchedulerからコールするPL/SQLストアド・プロシージャは、特定のシグネチャを持ち、次のような特定のプロシージャ・パラメータを含む必要があります。
PROCEDURE my_proc(request_handle IN VARCHAR2);
request_handle
パラメータは、実行されるOracle Enterprise Schedulerリクエストの実行コンテキストを表す不透明な値です。
例8-1に、Oracle Enterprise Schedulerで使用するサンプルのHELLO_WORLD
ストアド・プロシージャを示します。
例8-1 HELLO_WORLD PL/SQLストアド・プロシージャ
create or replace procedure HELLO_WORLD( request_handle in varchar2 ) as v_request_id number := null; v_prop_name varchar2(500) := null; v_prop_int integer := null; begin -- Get the Oracle Enterprise Scheduler request ID being executed. begin v_request_id := ess_runtime.get_request_id(request_handle); exception when others then raise_application_error(-20000, 'Failed to get request id for request handle ' || request_handle || '. [' || SQLERRM || ']'); end; -- Retrieve value of an existing request property. begin v_prop_name := 'mytestIntProp'; v_prop_int := ess_runtime.get_reqprop_int(v_request_id, v_prop_name); exception when others then rollback; raise_application_error(-20001, 'Failed to get request property ' || v_prop_name || ' for Oracle Enterprise Scheduler request ID ' || v_request_id || '. [' || SQLERRM || ']' ); end; -- Update an existing request property with a new value. -- This procedure is responsible for commit/rollback of the update operation. begin v_prop_name := 'myJobdefProp'; ess_runtime.update_reqprop_varchar2(v_request_id, v_prop_name, 'myUpdatedalue'); commit; exception when others then rollback; raise_application_error(-20002, 'Failed to update request property ' || v_prop_name || ' for Oracle Enterprise Scheduler request ID ' || v_request_id || '. [' || SQLERRM || ']' ); end; end helloworld; /
Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャ・ジョブ・タイプに非同期実行モデルを使用します。Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャを直接コールするのではなく、Oracle Databaseに含まれるOracle Enterprise Schedulerを使用します。PL/SQLストアド・プロシージャ・リクエストを実行する準備が整うと、Oracle Enterprise Schedulerにより、即時に1回のみ実行されるOracle Enterprise Schedulerジョブが作成されます。このジョブは、PL/SQLストアド・プロシージャに関連付けられているアプリケーションを実行するコンテナ・インスタンスに関連付けられているOracle Enterprise Schedulerランタイム・スキーマ・ユーザーによって所有されます。PL/SQLストアド・プロシージャは、Oracle Enterprise Schedulerジョブの実行時に、動的SQLを使用してコールされます。PL/SQLストアド・プロシージャが(正常な戻り値または例外の発生によって)完了すると、Oracle Enterprise Schedulerジョブが完了します。
PL/SQLストアド・プロシージャでは、RAISE_APPLICATION_ERROR
例外を発生させることによって、例外およびその他の問題を処理できます。RAISE_APPLICATION_ERROR
では、PL/SQLストアド・プロシージャのエラー・コードが-20000から-20999の範囲である必要があります。PL/SQLストアド・プロシージャで例外を発生させる必要がある場合は、RAISE_APPLICATION_ERROR
を使用できます。RAISE_APPLICATION_ERROR
には、-20000から-20999の範囲のエラー・コードが必要です。
表8-1に、PL/SQLストアド・プロシージャの結果に基づくOracle Enterprise Schedulerの状態を示します。
表8-1 PL/SQLストアド・プロシージャの結果の終了状態
最終状態 | 説明 |
---|---|
|
PL/SQLストアド・プロシージャが例外を発生させることなく正常な結果を返すと、その後のリクエスト完了時のエラーにかかわらず、リクエストの状態は |
|
PL/SQLストアド・プロシージャが例外とともに結果を返すと、リクエストの状態はその例外のSQLエラー・コードに基づいて決まります。 SQLエラー・コードが-20900から-20919の範囲の場合、リクエストは |
|
PL/SQLストアド・プロシージャが例外とともに結果を返すと、リクエストの状態はその例外のSQLエラー・コードに基づいて決まります。 -20900から-20919の範囲外のエラー・コードの場合は、リクエストは -20920から-20929の範囲内の戻りコードの場合は、 |
Oracle Enterprise Schedulerでは、PL/SQLストアド・プロシージャの操作で必要となる可能性のある特定の操作を実行するためのPL/SQLパッケージESS_RUNTIME
が提供されています。これらのプロシージャを使用してジョブ・リクエスト操作を実行し、Oracle Enterprise Schedulerランタイム・スキーマのジョブ・リクエスト情報を取得できます。たとえば、これらのランタイム・プロシージャを使用してリクエストを発行し、Oracle Enterprise Schedulerジョブ・リクエストに関連付けられているリクエスト情報を取得および更新できます。
次のサンプル・コードは、ESS_RUNTIME
プロシージャの使用方法を示します。
v_request_id := ess_runtime.get_request_id(request_handle);
このリクエストにより、ジョブ・リクエストに関連付けられているリクエストIDが取得されます。
ESS_RUNTIME
パッケージ内の特定のプロシージャでは、リクエスト・ハンドル・パラメータが必要であり、実行されるリクエストに関する情報を提供します(これらのプロシージャは、PL/SQLストアド・プロシージャ・リクエストを実行するPL/SQLストアド・プロシージャからのみコールする必要があります)。ESS_RUNTIME
パッケージ内の一部のプロシージャは、実行するリクエストのコンテキスト外からコールできます。これらのプロシージャには、リクエストIDパラメータを含めることができます。
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを作成して使用する場合は、次のことに注意する必要があります。
Oracle Enterprise Schedulerリクエストが発行されるときにPL/SQLストアド・プロシージャが存在する必要はありませんが、リクエストを実行する準備が整ったときには、PL/SQLストアド・プロシージャが存在し、Oracle Enterprise Schedulerランタイム・スキーマ・ユーザーがコールできる必要があります。
PL/SQLストアド・プロシージャは、Oracle Enterprise Schedulerランタイム・スキーマと同じデータベース上に存在する必要があります。
Oracle Enterprise Schedulerで使用するPL/SQLストアド・プロシージャを作成したら、DBAがPL/SQLストアド・プロシージャをOracle Databaseにロードして、必要な権限を付与する必要があります。
DBAは権限を付与する前に、Oracle Databaseと、Oracle Enterprise Scheduler PL/SQLストアド・プロシージャ・リクエストを発行する、デプロイされたJava EEアプリケーションに関連付けられているOracle Enterprise Schedulerランタイム・スキーマを決定する必要があります。
PL/SQLストアド・プロシージャ権限を付与する場合は、次の定義を使用します。
ess_schema
: Java EEアプリケーションに関連付けられているOracle Enterprise Schedulerランタイム・スキーマを指定します。
user_schema
: アプリケーション・ユーザー・スキーマの名前を指定します。
PROC_NAME
: Oracle Enterprise Schedulerジョブ・リクエストに関連付けられているPL/SQLストアド・プロシージャの名前を指定します。
Oracle Database権限を付与する手順は、次のとおりです。
Oracle Databaseで、アプリケーション・ユーザー・スキーマにESS_RUNTIME
パッケージの実行権限を付与します。次に例を示します。
GRANT EXECUTE ON ess_schema.ess_runtime to user_schema;
Oracle Databaseで、ESS_RUNTIME
パッケージにプライベート・シノニムを作成します。これは、PL/SQLストアド・プロシージャで完全なschema_name.ESS_RUNIME
を使用するかわりに、単にESS_RUNTIME
としてESS_RUNTIME
を参照できる便利なステップです。次に例を示します。
create or replace synonym user_schema.ess_runtime for ess_schema.ess_runtime;
Oracle Databaseで、Oracle Enterprise Schedulerランタイム・スキーマ・ユーザーにPL/SQLストアド・プロシージャの実行権限を付与します。
GRANT EXECUTE ON user_schema.proc_name to ess_schema;
たとえば、Oracle Enterprise Schedulerランタイム・スキーマがTEST_ORAESS
で、アプリケーション・ユーザー・スキーマがHOWTO
であり、PL/SQLプロシージャの名前がHELLO_WORLD
である場合は、次のようなDBA操作が必要になります。
GRANT EXECUTE ON test_oraess.ess_runtime to howto; create or replace synonym howto.ess_runtime for test_oraess.ess_runtime; GRANT EXECUTE ON howto.hello_world to test_oraess;
ESS_RUNTIME
パッケージの権限を付与するDBAタスクについて示されている最初の2つのステップは、ESS_RUNTIME
パッケージがPL/SQLプロシージャにより参照される場合にのみ必要です。これらの2つのステップは、ESS_RUNTIME
パッケージがそのアプリケーション・ユーザー・スキーマから使用されることがない場合には必要ありません。示されている3番目のステップは、Oracle Enterprise Schedulerからユーザー定義のPL/SQLストアド・プロシージャをコールできるようにするものであるため、常に必要となります。
Oracle Enterprise Scheduler PL/SQLストアド・プロシージャ・ジョブで使用される、特定のアプリケーション・ユーザー・スキーマ内のすべてのPL/SQLストアド・プロシージャは、常に同じ(単一の)Oracle Enterprise Schedulerランタイム・スキーマに関連付けられている必要があります。これは技術的に必要ありませんが、DBAのセットアップが大幅に簡略化され、PL/SQLストアド・プロシージャでESS_RUNTIME
を参照する場合に、プロシージャでOracle Enterprise Schedulerランタイム・スキーマを明示的に指定する必要がなくなります。
Oracle Enterprise SchedulerでPL/SQLストアド・プロシージャを使用するには、メタデータ・サービスを見つけて、ジョブ定義を作成する必要があります。ジョブ定義は、名前とジョブ・タイプを指定して作成します。ジョブ定義を作成するときには、特定のシステム・プロパティも設定する必要があります。これにより、メタデータ・サービスを使用してジョブ定義とその他の関連オブジェクトを格納できるようになります。
メタデータ・サービスの使用方法の詳細は、第6章「メタデータ・サービスの使用」を参照してください。
Oracle Enterprise Schedulerシステム・プロパティを使用して、PL/SQLストアド・プロシージャをコールするOracle Enterprise Schedulerジョブに特定の属性を指定できます。
これらのSystemPropertyプロパティは、SQLジョブ・タイプのPROCEDURE_NAME
とSQL_JOB_CLASS
にのみ適用されます。
PROCEDURE_NAME
システム・プロパティは、実行されるPL/SQLストアド・プロシージャの名前を指定します。ストアド・プロシージャの名前は、schema.nameという形式である必要があります。このプロパティは、ジョブ・タイプまたはジョブ定義のいずれかに対して指定する必要があります。
SQL_JOB_CLASS
システム・プロパティは、SQLジョブ・リクエストを実行するために使用されるOracle Enterprise Schedulerジョブに割り当てるOracle Enterprise Schedulerジョブ・クラスを指定します。このプロパティは、リクエストに使用されるOracle Enterprise Schedulerジョブが、特定のOracle Databaseリソース・コンシューマ・グループに関連付けられる必要があるか、データベース・サービスへのアフィニティを持つ必要がある場合を除き、指定する必要はありません。
Oracle Enterprise Schedulerでは、Oracle Enterprise Schedulerジョブを使用して、SQLジョブ・リクエストに対してPL/SQLストアド・プロシージャを実行します。Oracle Enterprise Schedulerジョブ・クラスは、データベース・サービスに対するアフィニティを持つ必要があるジョブ、またはOracle Databaseリソース・コンシューマ・グループに関連付けられるジョブに関連付けることができます。Oracle Enterprise Schedulerジョブ・クラスを使用して正常にジョブを作成するには、Oracle Enterprise Schedulerジョブ所有者に、そのジョブ・クラスに対するEXECUTE
権限が必要です。
SQL_JOB_CLASS
システム・プロパティが指定されない場合、デフォルトのOracle Enterprise Schedulerジョブ・クラスがOracle Enterprise Schedulerジョブに使用されます。デフォルトのジョブ・クラスは、デフォルトのリソース・コンシューマ・グループに関連付けられます。これはデフォルト・サービスに属することになり、このことは、サービス・アフィニティを持たず、Oracle RAC環境ではクラスタ内のどのデータベース・インスタンスでもジョブを実行し得ることを意味します。Oracle Enterprise Scheduler SQLリクエストでこのデフォルト・ジョブ・クラスを使用するために必要な追加の権限付与はありません。
Oracle Enterprise SchedulerのJobType
オブジェクトでは、実行タイプを指定し、ジョブ・リクエストの共通プロパティ・セットを定義します。1つのジョブ・タイプを定義して、1つ以上のジョブ定義で共有できます。Oracle Enterprise Schedulerでは、次の3つの実行タイプがサポートされています。
JAVA_TYPE
: Javaで実装され、コンテナ内で実行されるジョブ定義に使用します。
SQL_TYPE
: データベース・サーバーでPL/SQLストアド・プロシージャとして実行されるジョブ定義に使用します。
PROCESS_TYPE
: 個別のプロセスとして実行される、バイナリおよびスクリプトのジョブ定義に使用します。
JobType
を指定する場合、JobType
に関連付けられる特性を定義するプロパティも指定できます。表8-2に、PL/SQLストアド・プロシージャ・ジョブ・タイプに適したSystemProperties
を示します。
表8-2 PL/SQLストアド・プロシージャ・ジョブ・タイプ用のOracle Enterprise Schedulerシステム・プロパティ
システム・プロパティ | 説明 |
---|---|
|
PL/SQLジョブ実行の一部として実行するストアド・プロシージャの名前を指定します。
|
|
SQLジョブ・リクエストを実行するために使用されるOracle Enterprise Schedulerジョブに割り当てるOracle Enterprise Schedulerジョブ・クラスを指定します。 これは、 |
PL/SQLジョブ・タイプを作成および格納するには、次を実行します:
JobType
コンストラクタを使用して、String
名とJobType.ExecutionType.SQL_TYPE
引数を指定します。
新しいJobType
に適切なプロパティを設定します。
第6.2項「メタデータ・サービスへのアクセス」に示されているように、メタデータ・ポインタを取得します。メタデータ・サービスのaddJobType()
メソッドを使用して、JobType
をメタデータに格納します。
メタデータ・リポジトリ内でメタデータ・オブジェクトを一意に識別するMetadataObjectId
を使用します。MetadataObjectID
には、一意の識別子を使用したメタデータ・オブジェクトの完全修飾名が含まれます。
サンプル・コードは、第8.4.3項「Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用」を参照してください。
PL/SQLをOracle Enterprise Schedulerで使用するには、ジョブ定義を作成および格納する必要があります。ジョブ定義は、Oracle Enterprise Schedulerでジョブ・リクエストを定義する基本作業単位です。各ジョブ定義は、1つのジョブ・タイプにのみ属します。
注意: ジョブ・タイプを指定してジョブ定義を作成した後で、タイプやジョブ定義名を変更することはできません。タイプまたはジョブ定義名を変更するには、新しいジョブ定義を作成する必要があります。 |
第8.4.3項「Oracle Enterprise SchedulerアプリケーションでのPL/SQLストアド・プロシージャの使用」には、ジョブ定義コンストラクタとジョブ・タイプを使用してジョブ定義を作成する方法が示されています。
例8-2に、SQLジョブ・タイプに対してジョブ・タイプとジョブ定義アプリケーション・メタデータを作成するサンプル・コードを示します。
例8-2 PL/SQLストアド・プロシージャを使用したOracle Enterprise Schedulerのプログラム
import oracle.as.scheduler.JobType; import oracle.as.scheduler.JobDefinition; import oracle.as.scheduler.MetadataService; import oracle.as.scheduler.MetadataServiceHandle; import oracle.as.scheduler.MetadataObjectId; import oracle.as.scheduler.ParameterInfo; import oracle.as.scheduler.ParameterInfo.DataType; import oracle.as.scheduler.ParameterList; void createDefinition( ) { MetadataService metadata = ... MetadataServiceHandle mshandle = null; try { ParameterInfo pinfo; ParameterList plist; mshandle = metadata.open(); // Define and add a PL/SQL job type for the application metadata. String jobTypeName = "PLSQLJobDefType"; JobType jobType = null; MetadataObjectId jobTypeId = null; jobType = new JobType(jobTypeName, JobType.ExecutionType.SQL_TYPE); plist = new ParameterList(); pinfo = SystemProperty.getSysPropInfo(SystemProperty.PROCEDURE_NAME); plist.add(info.getName(), pinfo.getDataType(), "HOWTO.HELLO_WORLD", false); pinfo = SystemProperty.getSysPropInfo(SystemProperty.PRODUCT); plist.add(pinfo.getName(), pinfo.getDataType(), "HOW_TO_PROD", false); jobType.setParameters(plist); jobTypeId = metadata.addJobType(mshandle, jobType, "HOW_TO_PROD"); // Define and add a job definition for the application metadata. String jobDefName = "PLSQLJobDef"; JobDefinition jobDef = null; MetadataObjectId jobDefId = null; jobDef = new JobDefinition(jobDefName, jobTypeId); jobDef.setDescription("Demo PLSQL Job Definition " + jobDefName); plist = new ParameterList(); plist.add("myJobdefProp", DataType.STRING, "myJobdefVal", false); jobDef.setParameters(plist); jobDefId = metadata.addJobDefinition(mshandle, jobDef, "HOW_TO_PROD"); } catch (Exception e) { [...] } finally { // always close metadata service handle in finally block if (null != mshandle) { metadata.close(mshandle); mshandle = null; } } }