ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Enterprise Scheduler開発者ガイド
11g リリース1 (11.1.1.7)
B66615-04
  目次へ移動
目次

前
 
次
 

16 非同期Javaジョブの使用

この章では、Javaコードを起動する、長時間実行されるジョブ、またはコンテナ管理でないジョブをサポートするために、Oracle Enterprise Schedulerを使用して非同期Javaジョブを起動する方法について説明します。

この章では、次の項目について説明します。

16.1 非同期Javaジョブの使用の概要

通常、Oracle Enterprise SchedulerのJavaジョブ・リクエストは、Oracle WebLogic Server内部の専用スレッドで実行されますが、長時間実行されるJavaジョブ・リクエスト、またはコンテナ管理でないJavaジョブ・リクエストを発行する機能が必要となる場合があります。

Oracle Enterprise Schedulerでは、次の特徴を持つ非同期Javaジョブの起動がサポートされています。

16.2 非同期Javaジョブの作成

Oracle Enterprise Schedulerの非同期Javaジョブは、Oracle Enterprise Schedulerのジョブ・リクエストと外部メカニズムで構成されています。Oracle Enterprise Schedulerのジョブ・リクエストは、標準のOracle Enterprise SchedulerのJavaジョブ・リクエストと同様に実装されますが、標準のOracle Enterprise Schedulerリクエストとは異なり、シナリオによっては非同期Javaジョブ・リクエストによる作業が行われない場合があります。非同期Javaジョブ・リクエストの目的は、外部メカニズムをトリガーすることのみです。外部メカニズムはペイロード(データベースの監視や円周率の計算など、存続期間が長いプロセス)を実行しますが、Oracle Enterprise SchedulerのJavaジョブを実行するスレッドとは分離可能である必要があります。外部メカニズムとしてSOAコンポジット(BPEL)を使用したり、Oracle ADFビジネス・コンポーネントの非同期Webサービス、別のスレッド、JVM、マシンまたは他のメカニズムを使用できます。外部メカニズムとクライアント・アプリケーションの間の通信方法は、ジョブ所有者によって決定されます。ただし、非同期Javaジョブで重要なのは、非同期ジョブを表す物理的なJavaオブジェクトへのポインタが、Oracle Enterprise Schedulerのメモリーに格納されないということです。この理由は次のとおりです。

16.2.1 非同期Javaジョブの非同期インタフェースの実装

非同期Javaジョブの起動には、AsyncExecutableインタフェースの実装が必要です。

16.2.2 非同期Javaジョブのexecute()メソッド

非同期Javaジョブのexecute()メソッドの役割は、実際の作業が実行される外部メカニズムを設定することです。このメソッドは、外部メカニズムを開始した後、戻ります。非同期Javaジョブの起動execute()メソッドでは、実際の作業は実行できません。executeメソッドの実行中に例外がスローされ、ジョブの初期化中に問題が発生して実行に失敗したことがOracle Enterprise Schedulerに通知される場合があります。executeメソッドの実行中の例外によって、Oracle Enterprise Schedulerに対して、外部メカニズムで実行中の実際の作業に問題が発生したと通知されることはありません。Oracle Enterprise Schedulerでは、例外が捕捉された場合は後続の処理を行わないため、開始または使用された可能性のあるリソースが解放されていることを、ジョブ所有者が確認する必要があります。例外がスローされない場合、Oracle Enterprise Schedulerによってジョブが実行状態になり、ガベージ・コレクションできるように、ジョブのオブジェクトのハンドルが解放されます。

16.2.3 非同期Javaジョブからのリモート・ジョブの起動

非同期Javaジョブにより、WebサービスAddressingヘッダーを設定して、リモート・ジョブの作業を簡略化できます。

相関

WSA messageIDヘッダーを使用して、レスポンス・メッセージをリクエストに関連付けます。Oracle Enterprise Schedulerでは、メソッドRequestExecutionContext.getIdStringが提供されており、このメソッドにより、WSA messageIDヘッダーの値に使用されるIDが返されます。

返信Addressing

WSA ReplyToおよびFaultToヘッダーは、Oracle Enterprise Schedulerの汎用コールバック・サービスへの直接返信に使用できます。現在、Oracle Enterprise Schedulerでは、これらのアドレスの取得はサポートされていません。

16.2.4 ステータス更新を伴うOracle Enterprise Schedulerへのコールバック

Oracle Enterprise Schedulerでは、非同期コールバックのWebサービス操作setAsyncRequestStatusが提供されています(例16-15のインタフェースを参照)。これには、ステータスやステータス・メッセージなどの入力情報、および明示的に指定する相関情報が必要です。

Oracle Enterprise Schedulerでは、別のメカニズム、つまり、非同期コールバックのための汎用のJava Required Files Webサービス・プロバイダが提供されています。このWebサービス・プロバイダではあらゆるタイプのペイロードが受け入れられ、メッセージはSOAPMessageオブジェクトとして配信されます。メッセージをリクエストに関連付けるために、WSA relatesToヘッダーが抽出されます。このヘッダーに、元のリクエストのWSA messageIDヘッダーが移入されます。Actionヘッダーは、レスポンスが非同期ジョブの完了とフォルトのいずれに起因するかを決定するのに使用します。レスポンスがフォルトに起因する場合、非同期ジョブのリクエスト・ステータスは、一時的にERRORに設定されます。レスポンスが非同期ジョブの正常完了に起因する場合、非同期ジョブのリクエスト・ステータスは、一時的にSUCCESSに設定されます。SOAPMessage本文が抽出され、Updatable.onEventメソッドに渡される文字列に変換されます。

Webサービス・プロバイダのアドレスは、http://<host>:<port>/ess-async/essasynccallbackです。

16.2.5 非同期Javaジョブの更新

Oracle Enterprise Schedulerでは、インタフェースoracle.as.scheduler.Updatableが提供されており、このメソッドを使用すると、アプリケーション・コードで開始された更新イベントをジョブ・リクエストで受信できます。ジョブ・リクエストが更新されると、Oracle Enterprise Schedulerにより、クライアント・クラスにUpdatableインタフェースを実装するかどうかが決定されます。クライアント・クラスにUpdatableインタフェースを実装する場合、ホスティング・アプリケーションのMDBのコンテキストでジョブ・クラスの新規オブジェクトがインスタンス化され、onEventメソッドがコールされます。このメソッドでは、Webサービスの起動により決定されたリクエスト・ステータス、およびジョブに認識されるフォーマットで情報を表した文字列(Oracle Enterprise Scheduler WebサービスからのSOAPMessage本文など)を使用します。このメソッドでは、情報のログへの記録などの処理が実行される場合があります。その後、ステータスおよびステータス・メッセージを含むUpdateActionオブジェクトが返されます。

リクエストの実行に関連するユーザーのコンテキストで、onEventに対するコールが発生します。

ジョブにUpdatableインタフェースが実装されていない場合、イベントはonEventに渡されたステータス(Oracle Enterprise Schedulerへの非同期コールバックから決定されるステータスなど)に基づいて処理されます。

Updatableインタフェースの詳細は、例16-12を参照してください。

16.2.6 非同期ジョブ完了時のOracle Enterprise Schedulerへの通知

非同期ジョブの完了時にOracle Enterprise Schedulerに通知するには、次の2通りの方法があります。

  • Webサービス・インタフェースの使用

  • EJBインタフェースの使用

16.2.6.1 非同期ジョブ完了時のWebサービスを使用した通知

Oracle Enterprise SchedulerのWebサービス操作setAsyncRequestStatusを起動すると、これにより、非同期リクエストのステータスおよび関連情報が設定されます。この操作に関連して、次の情報が必要となります。

setAsyncRequestStatus(String requestExecutionContext, AsyncStatus status, String statusMessage)

ここで

  • requestExecutionContextは、開始イベントの一部として渡す必要がある文字列です。このパラメータは、Oracle Enterprise SchedulerジョブのRequestExecutionContextオブジェクトから導出されます。

  • statusSUCCESSERRORWARNINGPAUSECANCELBIZ_ERRORまたはUPDATEのいずれかです。

  • statusMessageは次のとおりです。

    • ステータスがERRORまたはBIZ_ERRORの場合は、エラー・メッセージとなります。

    • ステータスがWARNINGの場合は、警告メッセージとなります。

    • ステータスがPAUSEDの場合は、一時停止状態となります。

    • ステータスがUPDATEの場合は、定義してジョブにより適宜解析したカスタマイズ済文字列となります。

    • ステータスがSUCCESSまたはCANCELの場合、値は無視されます。

WebアプリケーションにおけるWebサービスの実装の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の「WebサービスのFusion Webアプリケーションへの統合」および『Oracle Fusion Middleware Webサービスのためのセキュリティおよび管理者ガイド』の「WebLogic Webサービスの保護と管理」を参照してください。

16.2.6.2 非同期ジョブ完了時のEJBを使用した通知

非同期Javaジョブのexecute()メソッドが正常に起動され、ジョブ・リクエストが外部メカニズムで実行されている場合、Oracle Enterprise Schedulerでは、他のジョブの処理が続行されます。ジョブ・リクエストが完了するか、またはエラーが発生した場合、そのジョブの発行元アプリケーションに通知を返す必要があります。この通信チャネルは、エージェントおよびクライアント・アプリケーション所有者に依存します。その後、発行元アプリケーションによって、ジョブのステータスがOracle Enterprise SchedulerにローカルEJBを介して通知されます。このEJBにもリモート・インタフェースがある場合、かわりに、外部メカニズムによりリモートEJB自体が起動されることもあります。EJBによって、ジョブ・ステータスが設定され、適切な後処理が行われます。すべてのEJB参照をカプセル化するヘルパー・クラスが提供されています。このヘルパーは依存関係インジェクションを使用するため、コンテナ内部で使用されている場合にのみ動作します。ヘルパー・クラスには成功、エラー、警告および取消しを通知するためのメソッドが含まれています。

16.2.7 非同期JavaジョブのAsyncCancellableインタフェース

ジョブを取消し可能にする場合は、AsyncCancellableインタフェースを実装する必要もあります。このインタフェースは、その取消しメソッドにより、当該ジョブに対してRequestExecutionContextRequestParametersも提供される点で、通常の取消し可能なインタフェースとは異なります。指定されたコンテキストおよびパラメータを使用して、ペイロードを実行中の外部メカニズムを判別し、停止するよう要求する必要があります。(ジョブのAsyncCancellable.cancel()の実装ではなく)外部メカニズムにより、Oracle Enterprise Schedulerにジョブが取り消されたことが通知されます。


注意:

現在、実行中のOracle ADFビジネス・コンポーネントの非同期Webサービス・プロセスを終了する方法はありません。


16.2.8 イベント配信ネットワークを介してBPELプロセスを起動する非同期Javaジョブのサンプル

非同期リクエストを使用して、BPELプロセスをOracle Enterprise Schedulerから起動できます。Oracle Enterprise Schedulerの非同期Javaジョブを使用して、BPELプロセスを起動します。BPELプロセスが完了すると(成功したか、エラーや警告が発生したか、または取り消されたかどうかに関係なく)、BPELプロセスにより、Oracle Enterprise SchedulerのWebサービス操作を使用してOracle Enterprise Schedulerに通知されます。

BPELプロセスを起動するこの方法の手順は、次のとおりです。

  1. Oracle Enterprise Schedulerの非同期Javaジョブを作成します。

  2. BPELプロセスをOracle Enterprise SchedulerのJavaジョブから起動します。

  3. BPELプロセスが完了したら、Oracle Enterprise Scheduler Webサービスに完了ステータスでコールバックします。Webサービス操作のメソッドを使用して、Oracle Enterprise Schedulerにリクエストの完了を通知します。詳細は、第16.2.6.1項「非同期ジョブ完了時のWebサービスを使用した通知」を参照してください。

  4. Oracle Enterprise Schedulerでは、完了情報が受信されると、リクエストについて必要な後処理(必要に応じて)を完了します。

関連するWebサービスを直接起動したり、例16-1に示すように、BPELプロセスを起動することをイベント・メディエータに指示するイベントを公開できます。

例16-1 イベント・メディエータを介してBPELプロセスを起動するジョブ

import oracle.as.scheduler.RequestParameters;
import oracle.as.scheduler.ExecutionCancelledException;
import oracle.as.scheduler.ExecutionErrorException;
import oracle.as.scheduler.ExecutionPausedException;
import oracle.as.scheduler.ExecutionWarningException;
import oracle.as.scheduler.RequestExecutionContext;
 
import javax.xml.namespace.QName;
import oracle.fabric.blocks.event.BusinessEventConnection;
import oracle.fabric.blocks.event.BusinessEventConnectionFactory;
import oracle.fabric.common.BusinessEvent;
import oracle.integration.platform.blocks.event.BusinessEventBuilder;
import oracle.integration.platform.blocks.event.BusinessEventConnectionFactorySupport;
import oracle.xml.parser.v2.XMLDocument;
import org.w3c.dom.Element;
 
 
// Async imports
import oracle.as.scheduler.AsyncExecutable;
import oracle.as.scheduler.AsyncCancellable;
 
 
public class BPELJob implements AsyncExecutable, AsyncCancellable
{
    public BPELJob() {
    }
 
    public void execute(RequestExecutionContext ctx, RequestParameters params)
        throws ExecutionErrorException,
               ExecutionWarningException,
               ExecutionCancelledException,
               ExecutionPausedException
    {
        // Publish an event to the Event Mediator
        publishEvent(ctx.getRequestId() + "", ctx.toString(), "ESS_EVENT");
    }
 
    // Cancel
 
    public void cancel (RequestExecutionContext ctx,
                        RequestParameters requestParams) {
        publishEvent(ctx.getRequestId() + "", ctx.toString(), "CANCEL_ESS_EVENT");
        return;
    } // cancel
 
    // Event publishing
 
    private final String eventName = "ESSDemoEvent";
    private final String eventElement = "ESSDemoEventElement";
    private final String eventNamespace =
            "http://xmlns.oracle.com/apps/ta/essdemo/events/edl";
    private final String schemaNamespace =
            "http://xmlns.oracle.com/apps/ta/essdemo/events/schema";
 
    private XMLDocument buildEventPayload(String correlationId, String key, String
                                          eventType) {
        Element masterElem, childElem1, childElem2, childElem3;
        XMLDocument document = new XMLDocument();
        masterElem = document.createElementNS(schemaNamespace, eventElement);
        document.appendChild(masterElem);
        childElem1 = document.createElementNS(schemaNamespace, "requestId");
        childElem1.appendChild(document.createTextNode(correlationId));
        masterElem.appendChild(childElem1);
        childElem2 = document.createElementNS(schemaNamespace,
                                              "executionContext");
        childElem2.appendChild(document.createTextNode(key));
        masterElem.appendChild(childElem2);
        childElem3 = document.createElementNS(schemaNamespace, "eventType");
        childElem3.appendChild(document.createTextNode(eventType));
        masterElem.appendChild(childElem3);
        return document;
    }
 
 
    private void publishEvent(String correlationId, String key, String eventType) {
 
            try {
                 // Get event connection
                 BusinessEventConnectionFactory cf =
                        BusinessEventConnectionFactorySupport.
                        findRelevantBusinessEventConnectionFactory(true);
 
                 if (cf != null) {
                     BusinessEventConnection conn =
                             cf.createBusinessEventConnection();
 
                     //  Build event
                     BusinessEventBuilder builder =
                             BusinessEventBuilder.newInstance();
 
                     // Specify the event name and namespace. In this prototype,
                     // they are constants, eventNamespace, eventName
                     builder.setEventName(new QName(eventNamespace, eventName));
 
                     // Specify the event payload. In this prototype, the
                     // getXMLPayload custom method constructs the payload
                     builder.setBody(buildEventPayload(correlationId, key,
                                     eventType).getDocumentElement());
                     BusinessEvent event = builder.createEvent();
 
                     //  Publish event
                     conn.publishEvent(event, 5);
 
                     // For debug only
                     System.out.println("Event was sent sucessfully");
                 } else {
                     // For debug only
                     System.out.println("cf is null");
                 }
             } catch (Exception exp) {
                 // For debug only
                 System.out.println("Failed sending event: " + exp.getMessage());
                 exp.printStackTrace();
             }
        } // publishEvent
}

16.2.8.1 Oracle Enterprise Schedulerを使用したBPELプロセスのデザインタイムのサンプル

非同期Javaジョブを使用して、BPELプロセスを実行できます。プロセスはイベントによって起動され、そのプロセスを起動したイベント・メディエータによって処理されます。たとえば、図16-1を参照してください。

  • プロセスの実際の作業は、DoMyWorkモジュールで行われます。

  • 作業が正常に完了すると、AssignAsyncSuccess/AsyncCallbackSUCCESSに制御が移行し、ステータスとしてSUCCESSが指定され、ステータス・メッセージが指定されずに、Oracle Enterprise SchedulerのWebサービス・コールバックが起動されます。

  • Oracle Enterprise Schedulerのリクエストが取り消されると、Oracle Enterprise Schedulerジョブの取消しメソッドがコールされます。次に、ジョブ・オブジェクトにより、それを取り消す必要があることがリモート・ジョブに通知されます。取消しが成功すると、リモート・ジョブにより、コールバック・メカニズムを使用してOracle Enterprise Schedulerに通知され、ステータスがCANCELに設定されます。この場合、制御は右端にあるブランチに移行します。

  • フォルトが発生した場合、制御は中間ブランチに移行します。AsyncCallbackERRORにより、ステータスERRORおよびフォルトからのエラー・メッセージを指定するOracle Enterprise SchedulerのWebサービス・コールバックが起動されます。AsyncCallbackCANCELにより、ステータスCANCELを指定する(ステータス・メッセージは指定されません)Oracle Enterprise SchedulerのWebサービス・コールバックが起動されます。

図16-1 非同期リクエストによってBPELプロセスをコールして返すJavaジョブ

非同期リクエストによって返されます。
「図16-1 非同期リクエストによってBPELプロセスをコールして返すJavaジョブ」の説明

BPELプロセスでは、AssignAsyncError割当てアクティビティについての図16-2図16-3および図16-4に示すように、Oracle Enterprise Schedulerの非同期コールバックに対するWebサービス操作の値が必要です。

図16-2 statusMessage要素に対するAsyncCallBackError引数のマッピング

statusMessage要素に対するマッピング
「図16-2 statusMessage要素に対するAsyncCallBackError引数のマッピング」の説明

図16-3 requestExecutionContextに対するAsyncCallbackErrorの引数マッピング

requestExecutionContextに対するマッピング
「図16-3 requestExecutionContextに対するAsyncCallbackError引数のマッピング」の説明

図16-4 status要素に対するAsyncCallbackError引数のマッピング

AsyncCallbackErrorの引数マッピング
「図16-4 status要素に対するAsyncCallbackError引数のマッピング」の説明

16.3 非同期ジョブとしてのBPELプロセスの実装を示すユースケース

非同期ジョブとしてのBPELプロセスの実装のユースケースは、次のとおりです。

デザイン・パターンのサマリー

Oracle Enterprise Schedulerの非同期ジョブはAsyncExecutableインタフェースを実装するJavaジョブであり、このインタフェースは、Oracle Enterprise Schedulerでexecute()メソッドを実装することによって起動されます。このメソッドを使用すると、execute()メソッドが完了する、長時間実行されるタスクやリモートのタスク(ビジネス・イベントの呼出しなど)を開始でき、その間、ジョブはOracle Enterprise SchedulerによってRUNNINGステータスに維持されます。リモート・タスクが完了すると、次のいずれかを実装することにより、ステータス・メッセージを使用してOracle Enterprise Schedulerにその完了が通知されます。

このパターンでは、起動されるリモート・タスクが、非同期ジョブのexecute()メソッドでビジネス・イベントを呼び出すことによってトリガーされるBPELプロセスであることを前提としています。完了、エラーまたは取消しを経たプロセスの終了時に、BPELプロセスによってOracle Enterprise Scheduler Webサービスが起動され、ステータスが適宜設定されます。

関連コンポーネント

図16-5に、Oracle Enterprise Scheduler、SOAメディエータおよびBPELを示します。

図16-5 Oracle Enterprise Schedulerの非同期ジョブからのBPELコール

非同期ジョブからのBPELコール
「図16-5 Oracle Enterprise Schedulerの非同期ジョブからのBPELコール」の説明

16.3.1 推奨されるデザイン・パターンの概要

ユースケースによっては、Oracle Enterprise SchedulerジョブによってBPELプロセスを双方向方式で起動して、他のジョブに進む前にこのBPELプロセスの完了を追跡する必要があります。Oracle Fusion ApplicationsでJavaコード(Oracle Enterprise SchedulerまたはOracle ADFビジネス・コンポーネント)から非同期Webサービスを起動することは禁止されているため、Oracle Enterprise Schedulerジョブによって非同期BPELプロセスを直接起動することはできず、非同期ジョブの実装タイプに依存する必要があります。

このアプローチはOracle Fusion Middlewareの既存の機能(イベントやBPELなど)を利用するため、お薦めします。

16.3.2 考えられるアプローチ

Oracle Enterprise Schedulerの非同期ジョブ機能のかわりに次のアプローチが考えられますが、許可されていません。

  • JAX-WSプロキシを介したOracle ADFビジネス・コンポーネントやBPELなどの非同期Webサービスの起動 - スレッドのブロックおよびコールバック・サービスがOracle Enterprise Schedulerで許可されていません。

  • BPELをトリガーするビジネス・イベントの呼出し: BPELでOracle ADFビジネス・コンポーネント・サービスを起動し、そのADFビジネス・コンポーネント・サービスでRuntimeService EJBを起動してステータスを設定しますが、複雑でエラーが発生しやすい手順です。

16.3.3 ユースケース・サマリー

ある経費システムでは経費をインポートして処理するためのOracle Enterprise Schedulerジョブが定期的に実行され、この処理では、通知と承認にヒューマン・ワークフローを活用するために、BPELプロセスの発行が必要となります。このユースケースでは、Oracle Enterprise Schedulerジョブで経費と明細をインポートし、経費ごとに非同期BPEL機能をトリガーするサブリクエストを経費単位で発行します。このサブリクエストはOracle Enterprise Schedulerの非同期ジョブとして実装され、このジョブでは、ビジネス・イベントを呼び出してそのJava execute()メソッドを完了し、BPELの起動時には実行状態を継続してヒューマン・タスク通知を発行し、ユーザー操作の結果を待機します。この結果が取得されると、BPELによって、この特定のサブリクエストが完了したことを通知するOracle Enterprise Scheduler Webサービスが起動されます。

16.4 非同期ジョブを使用したBPELの実装方法

BPELでOracle Enterprise Schedulerの非同期ジョブを実装するには、次の手順を実行する必要があります。

  1. execute()cancel()の各メソッドを記述して、AsyncExecutableAsyncCancellableの各インタフェースを実装するOracle Enterprise SchedulerのJavaジョブを作成します。

  2. Oracle Enterprise Schedulerの非同期ジョブ定義を作成します。

  3. イベント・ペイロード・スキーマ(XSD)およびイベント定義(EDL)の各ファイルを設計します。

  4. Oracle Enterprise Schedulerの非同期ジョブのexecute()および(必要に応じて)取消しメソッドから、ビジネス・イベントをプログラムによって呼び出します。

  5. メディエータおよびBPELを使用してSOAコンポジットを設計します。

  6. エラーに対してフォルト処理と相関onMessageブランチを追加し、ジョブ・ステータス更新を取り消します。

16.4.1 ユースケース: Oracle JDeveloperライブラリの追加

Oracle Enterprise Schedulerアプリケーションでは、アプリケーション・コアおよびEnterprise Scheduler ServiceのOracle JDeveloperライブラリを追加し、Oracle Enterprise SchedulerのAsyncExecutableAsyncCancellableの両方のインタフェースを実装する、(標準に従って)適切なクラス・ネーミングとディレクトリ構造を使用して新規Javaクラスを作成するようにしてください。これらのインタフェースを両方ともインポートするには、例16-2に示すように、Oracle Enterprise Schedulerジョブの必要な動作を開始するためにOracle Enterprise SchedulerのRuntimeService Beanによって起動されるexecute()cancel()の各メソッドを実装する必要があります。

例16-2 Oracle JDeveloperライブラリの追加

public class ASMEventAsyncJob implements AsyncExecutable, AsyncCancellable {
    public ASMEventAsyncJob() {
        super();
    }
 
    public void execute(RequestExecutionContext ctx, RequestParameters params)
        throws ExecutionErrorException,
               ExecutionWarningException,
               ExecutionCancelledException,
               ExecutionPausedException
    {
        publishEvent(ctx.getRequestId() + "", ctx.toString(), "ESS_EVENT");
        return;
 
     }
 
 
    public void cancel (RequestExecutionContext ctx,
                        RequestParameters requestParams) {
        publishEvent(ctx.getRequestId() + "", ctx.toString(), "CANCEL_ESS_EVENT");
        return;
    } // cancel

16.4.2 ユースケース: 非同期ジョブ定義の作成

Oracle Enterprise SchedulerのJDeveloperワークスペースで、「新規」をクリックし、Enterprise Scheduler Serviceのテクノロジ・グループを選択して「ジョブ定義」を選択します。図16-6に示すように、Oracle Enterprise Schedulerのジョブ定義の名前を入力して、指定されたJavaJobTypeを選択し、ステップ1で作成したクラスをこのジョブ定義に対してオーバーライドするJavaクラスとして選択します。

図16-6 「ジョブ定義の作成」

ジョブ定義の作成
「図16-6 ジョブ定義の作成」の説明

ここで、図16-7に示すように、このジョブ定義に対してオーバーライドするJavaクラスとして、ステップ1で開発したクラスを選択し、ユースケースの必要に応じてパラメータおよびアクセス制御を定義します。

図16-7 ジョブ・タイプが定義されたジョブ定義の作成

「ジョブ・タイプ」を含む「ジョブ定義の作成」
「図16-7 ジョブ・タイプが定義されたジョブ定義の作成」の説明

16.4.3 ユースケース: イベント・ペイロード・スキーマ・ファイルおよびイベント定義ファイルの設計

SOAコンポジット・デザイナには、ビジネス・イベントのペイロード定義(EDL)の設計に役立つUI機能がありますが、スキーマ(.xsd)を最初に設計する必要があります。例16-3に、サンプルのXSDファイルを示します。

例16-3 サンプルXSDファイル

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://xmlns.oracle.com/apps/ta/essdemo/events/schema"
            targetNamespace="http://xmlns.oracle.com/apps/ta/essdemo/events/schema"
            attributeFormDefault="unqualified"
            elementFormDefault="qualified">
  <xsd:element name="ESSDemoEventElement" type="ESSDemoEventElementType"/>
  <xsd:complexType name="ESSDemoEventElementType">
      <xsd:sequence>
        <xsd:element name="requestId" type="xsd:string"/>
        <xsd:element name="executionContext" type="xsd:string"/>
        <xsd:element name="eventType" type="xsd:string"/>
      </xsd:sequence>
</xsd:complexType>
 
</xsd:schema>

ペイロードの要素タイプを完了したら、EDLを手動で作成するか、またはイベント定義ビルダーを使用できます。ビルダーを使用するには、SOAコンポジット・エディタを開き、図16-8に示すように、UIの上部にある稲妻アイコンをクリックして「イベント定義の作成」ウィンドウを開きます。

図16-8 「イベント定義の作成」

イベント定義の作成
「図16-8 「イベント定義の作成」」の説明

次に、名前およびネームスペースを割り当てて「追加」をクリックし、図16-9に示すように、この定義に新規イベントを追加します。

図16-9 「イベントの追加」

イベントの追加
「図16-9 「イベントの追加」」の説明

「OK」をクリックします。イベント定義サマリーに完成したイベント定義が表示されます。図16-10に示すように、要件の必要に応じて、さらにイベントを追加します。

図16-10 「イベント」リスト

「イベント」リスト
「図16-10 「イベント」リスト」の説明

例16-4に、作成されたEDLファイルのサンプルを示します。

例16-4 EDLファイル

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://schemas.oracle.com/events/edl"
             targetNamespace="http://xmlns.oracle.com/
             AsyncEssDemoComposite/EventDefinition1">
    <schema-import namespace="http://xmlns.oracle.com/singleString"
                   location="xsd/singleString.xsd"/>
    <schema-import namespace="http://xmlns.oracle.com/apps/ta
                   /essdemo/events/schema"
                   location="xsd/ESSDemoEventSchema.xsd"/>
    <event-definition name="ESSEvent">
        <content xmlns:ns1="http://xmlns.oracle.com/apps/ta/essdemo/events/schema"
                 element="ns1:ESSDemoEventElement"/>
    </event-definition>
</definitions>

16.4.4 非同期ジョブのメソッドからのビジネス・イベントのプログラムによる呼出し

Oracle Enterprise Schedulerの非同期ジョブから呼び出されたビジネス・イベントには、いずれのジョブが完了したか、取り消されたか、またはエラーが発生したかをBPELで示すために、リクエストの実行コンテキストのtoString()値が含まれている必要があります。Javaからのビジネス・イベントのプログラムによる呼出しについては、ビジネス・イベントを呼び出すJavaコードを記述する方法の仕様を含む、ADFからのSOAの起動に関する項で説明しています。呼び出されたこのビジネス・イベントをサブスクライブするSOAコンポジットを宣言して作成するには、イベント・スキーマ(.xsd)および定義(EDL)を設計する必要があります。Javaコードにより、このXML文書を最初から作成する必要があり、QName値(ペイロード構造における要素やネームスペースの属性など)と完全に一致する必要があります。

execute()メソッドは、Oracle Enterprise Schedulerによりジョブの実行が開始されるときに起動されますが、エンド・ユーザーまたは外部エンティティからOracle Enterprise Schedulerに実行中のジョブを取り消すよう指示があった場合は、Oracle Enterprise SchedulerによってジョブのステータスがCANCELLINGに設定され、cancel()メソッドが起動されます。両方のメソッドで、類似するペイロード・タイプやネームスペースを含むイベントが呼び出されるようにすることをお薦めします。これにより、相関セットを使用して進行中のBPELプロセスに取消しイベントを送信できるようにし、そのBPELプロセスで代替機能を実行してOracle Enterprise Scheduler Webサービスを起動し、ジョブ・ステータスをCANCELLEDに設定できるようにします。

このサンプルでは、イベント呼出しコードがOracle Enterprise Schedulerジョブのクラス・コードに配置されていますが、最適なアプローチはOracle ADFライブラリとしてコードを共有することであり、このプロジェクトにそのライブラリをインポートして公開コードの重複を減らすことができます。

(BPEL相関セットで進行中の取消しが許可されるように) requestIDおよび実行コンテキストのtoString()値を渡すイベント呼出しコードをコールするサンプル・コードを次に示します。

publishEvent(ctx.getRequestId() + "", ctx.toString(), "ESS_EVENT");

例16-5に、サンプルのイベント呼出しコードを示します。

例16-5 イベント呼出しコード

    private final String eventElement = "ESSDemoEventElement";
    private final String eventNamespace = "http://xmlns.oracle.com/apps/ta/essdemo/events/edl";
    private final String schemaNamespace = "http://xmlns.oracle.com/apps/ta/essdemo/events/schema";
 
    private XMLDocument buildEventPayload(String correlationId, String key, String
            eventType) {
        Element masterElem, childElem1, childElem2, childElem3;
        XMLDocument document = new XMLDocument();
        masterElem = document.createElementNS(schemaNamespace, eventElement);
        document.appendChild(masterElem);
        childElem1 = document.createElementNS(schemaNamespace, "requestId");
        childElem1.appendChild(document.createTextNode(correlationId));
        masterElem.appendChild(childElem1);
        childElem2 = document.createElementNS(schemaNamespace,
                     "executionContext");
        childElem2.appendChild(document.createTextNode(key));
        masterElem.appendChild(childElem2);
        childElem3 = document.createElementNS(schemaNamespace, "eventType");
        childElem3.appendChild(document.createTextNode(eventType));
        masterElem.appendChild(childElem3);
        return document;
    }
 
 
    public void publishEvent(String correlationId, String key, String eventType) {
            // Determine whether we are outside of a JTA transaction
            try {
                 // Get event connection
                 BusinessEventConnectionFactory cf = BusinessEventConnectionFactorySupport.findRelevantBusinessEventConnectionFactory
        (true);
 
                 if (cf != null) {
                     BusinessEventConnection conn =
                             cf.createBusinessEventConnection();
 
                     //  Build event
                     BusinessEventBuilder builder = BusinessEventBuilder.newInstance();
 
                     // Specify the event name and namespace. In this prototype,
                     // they are constants, eventNamespace, eventName
                     builder.setEventName(new QName(eventNamespace, eventName));
 
                     // Specify the event payload. In this prototype, the
                     // getXMLPayload custom method constructs the payload
                     builder.setBody(buildEventPayload(correlationId, key,
                             eventType).getDocumentElement());
                     BusinessEvent event = builder.createEvent();
 
                     //  Publish event
                     conn.publishEvent(event, 5);
 
                     // For debug only
                     System.out.println("Event was sent sucessfully");
                     conn.close();
                 } else {
                     // For debug only
                     System.out.println("cf is null");
                 }
             } catch (Exception exp) {
                 // For debug only
                 System.out.println("Failed sending event: " + exp.getMessage());
                 exp.printStackTrace();
             }
        } // publishEvent
}
 

16.4.5 メディエータおよびBPELを使用したSOAコンポジットの設計

このユースケースはBPEL機能によって異なるため、イベント・サブスクリプション用のメディエータを含むSOAコンポジットを作成する必要があり、これにより、ペイロードを変換してBPELプロセスを起動できます。

SOAワークスペースで、新規SOAコンポジットを作成します。このパターンに対してコンポジットを設定するには、Oracle Enterprise Schedulerで呼び出されたイベントをサブスクライブするメディエータを追加して、BPELプロセスに接続します。Oracle Enterprise Scheduler WebサービスWSDLにサービス参照を追加します。次に例を示します。

http://myhost.com:7001/ess/esswebservice?WSDL

1つ以上のネストされたスコープを使用して、BPELプロセスで必要な機能を引き続き作成します。機能は少なくとも1つのプライマリ・スコープ内に存在する必要があり、図16-11に示すように、このスコープでonMessageイベント(進行中の取消しメッセージの受信用)およびフォルト・ハンドラ・ブランチを追加できます。

図16-11 BPELおよびESSWebServiceを使用したコンポジット

BPELおよびESSWebServiceを使用したコンポジット
「図16-11 BPELおよびESSWebServiceを使用したコンポジット」の説明

Oracle Enterprise Scheduler Webサービスの起動の詳細は、第11章「Oracle Enterprise Scheduler Webサービスの使用」を参照してください。

16.4.6 エラーに対するフォルト処理と相関onMessageブランチの追加およびジョブの取消し

Oracle Enterprise Schedulerでは、execute()メソッドのJavaコードが完了した後、Oracle Enterprise Schedulerの非同期ジョブのハートビート監視は一切行われません。ジョブは発行されると、リモート・ジョブ・コード、BPELまたはエンド・ユーザーがOracle Enterprise Schedulerを直接操作してそのジョブのステータスを設定するまで、RUNNING状態でOracle Enterprise Schedulerインフラストラクチャ内に存在します。このため、BPELプロセスの設計では、Oracle Enterprise Schedulerジョブの存続期間中に最もよく発生する、少なくとも2つのタイプのシナリオを処理するように、また、監視UIにジョブの適切な状態を反映してエンド・ユーザーに示すために、できるかぎり状態情報をOracle Enterprise Schedulerに送信して戻すようにする必要があります。

BPEL処理の取消し

たとえば、監視UIをエンド・ユーザーが操作してジョブの取消しをリクエストする場合、図16-12に示すように、Oracle Enterprise Schedulerでは、ジョブのステータスがCANCELLINGに更新され、リモート機能が整理されるのを待機して、ジョブが取り消されたことを確認します。

図16-12 BPEL処理の取消し

BPEL処理の取消し
「図16-12 BPEL処理の取消し」の説明

BPEL処理エラー

また、リモート機能で障害が発生した場合、この障害については、リモート機能(この場合にはBPEL)からOracle Enterprise Schedulerに通知する必要があり、このとき、Oracle Enterprise Schedulerに対して、ジョブのステータスがERRORであることを通知し、実行されたすべてのロギングとステータス・メッセージを提供することが必要になります。これを図16-13に示します。

図16-13 BPEL処理エラー

BPEL処理エラー
「図16-13 BPEL処理エラー」の説明

取消しを確認して適切なステータスをOracle Enterprise Schedulerインフラストラクチャに調整して戻すために、受信する取消しメッセージの受入れや障害のトラップをサポートし、いずれの場合でもOracle Enterprise Schedulerサブシステムを更新できるよう、特定のレイアウト内でBPELを設計する必要があります。このためには、BPELプロセスに、この非同期ジョブの機能を含む少なくとも1つのスコープが存在する必要があります。これにより、取消しやエラーの状態の処理は十分に制御され、その後、これらの状態はOracle Enterprise Schedulerランタイムにおけるジョブのステータスを更新するためにOracle Enterprise Scheduler Webサービスに送信される必要があります。

これらの状態をサポートする基本的なプロセス・フローを作成するには、次の手順を順番に完了する必要があります。

  1. 相関セットを作成して、受信Receiveアクティビティを模倣するためにフラグを付けます。

  2. サブステップ1で作成した相関セットを使用して、onMessageブランチを作成します。

  3. フォルト処理ブランチを作成します。

  4. 必要に応じて、onMessageブランチとフォルト処理ブランチにクリーン・アップ・アクティビティを移入し、Oracle Enterprise Scheduler Webサービスを適切なステータスで起動します。

16.4.6.1 相関セットの作成および開始アクティビティの定義

BPELプロセスで他のアクティビティを実行中か、または非同期コールバックを待機中に取消しイベントの受信をサポートするには、プロセスが相関セットを使用して構成されている必要があります。相関セットは、BPELエンジンに対してBPELプロセスを一意に識別するために使用される1つ以上の受信ペイロード属性から作成されるキー値であり、これにより、新規プロセスを開始するかわりに、一致する属性のセットを含む追加サービス・リクエストを現在実行中のプロセスにルーティングできます。相関は非同期リクエスト・レスポンスに使用される標準機能ですが、スコープ・レベルのonMessageブランチによって、BPELプロセスでの実行フローを変更するためにも使用できます。

相関セットを設定するには、デザイナでBPELプロセスを開き、Receiveアクティビティをダブルクリックして、「相関」タブをクリックします。

相関セットには、この相関セットのライフ・サイクルの開始点となるアクティビティを示す開始プロパティが含まれていることに注意してください。この場合、BPELプロセスは相関セットのライフ・サイクルが開始する必要がある時点に開始され、これにより、相関イベントはプロセスのどの時点であってもこのプロセスにルーティングされます。

相関セットを作成する手順は、次のとおりです。

  • 任意のReceive、InvokeまたはonMessageアクティビティの「相関」タブで「新規」アイコンをクリックし、相関セットの名前を指定します。

  • 次に、「追加」をクリックして、相関キーとして使用する1つ以上のプロパティ属性を定義します。

  • 変数属性を設定プロパティとして選択して、「OK」をクリックします。

  • ステップ2と3を必要に応じて繰り返し、常に一意となる属性セットを作成します。

  • 相関セットのライフ・サイクルが開始するアクティビティで、相関の「開始」フラグを「はい」に設定します。

図16-14に、相関セットが定義され、「開始」フラグが「はい」に設定されたプライマリ(最初の) Receiveアクティビティを示します。

図16-14 Receiveアクティビティの相関

Receiveアクティビティの相関
「図16-14 Receiveアクティビティの相関」の説明

図16-15に、単一のプロパティが定義されたCorrelationSet_1定義を示します(一意キーが作成されていることを確認するには、必要に応じて追加プロパティを定義します)。

図16-15 「相関セットの編集」

相関セットの編集
「図16-15 「相関セットの編集」」の説明

16.4.6.2 相関セットを使用したonMessageブランチの作成

相関セットを開始のために定義して設定すると、受信する取消しメッセージを受け入れるために必要なアクティビティを含むonMessageブランチをスコープに作成して、補正やクリーンアップを実行し、ジョブの完了ステータスをCANCELに割り当てることができるようになります。


注意:

この時点で、onMessageブランチにInvokeアクティビティが含まれていたり、上位順序のスコープでinvokeを実行することが許可されなくなることがあり、この場合、フロー内で必要なinvokeアクティビティの全体数は減少します。


次の手順を実行して、図16-16に示すように、以前に作成した相関セットをonMessageブランチのアクティビティに追加します。

  • プロセス機能を含むネストされたスコープで、「OnMessageブランチの追加」アイコンをクリックし、スコープの隅に新規フローを作成します。

  • onMessageブランチのアクティビティをダブルクリックしてアクティビティ・エディタを開きます。

  • 「相関」タブを選択します。

  • 「追加」(+)アイコンをクリックして以前に作成した相関セットを選択し、「開始」フラグが「いいえ」に設定されていることを確認して、「OK」をクリックします。

図16-16 BPEL OnMessageブランチ

BPEL OnMessageブランチ

16.4.6.3 フォルト・ブランチの作成

ネストされた作業スコープで様々なアクティビティを実行する過程において、BPELではビジネス・サービスまたはシステム機能からフォルトが発生する場合があります。ほとんどの場合、プロセスのコールにスローして戻すことができる1つ以上のWSDL定義フォルトがビジネス・サービスによって定義されます。通常、BPEL CatchAllフォルト・ブランチでは、発生するすべてのフォルトがそのタイプや原因に関係なくトラップされますが、特定のビジネス・フォルトに対して、異なる動作セットを実行するという要件が製品チームに存在する場合があります。特定のビジネス・フォルトに対して独自の補正動作が実行されるようにする場合、開発者は、WSDL定義済フォルトごとに、指定されたフォルト処理ブランチを作成する必要があります。これらの指定されたフォルト・ハンドラ・ブランチに加えて、スコープから発生するシステム・レベルまたは管理対象外のフォルトをトラップするには、CatchAllフォルト処理ブランチの追加が引き続き必要です。

CatchFaultおよびCatchAllのスコープ・アイコンをクリックして必要なフォルト処理ブランチを作成し、次に、指定されたフォルト処理ブランチをダブルクリックして、これらのブランチが捕捉する指定されたフォルトを定義します。

図16-17に示す使用可能なステータスに注意してください。

図16-17 BPELフローのCatchブランチ

BPELフローのCatchブランチ
「図16-17 BPELフローのCatchブランチ」の説明

16.4.6.4 onMessageおよびフォルト・ブランチへの移入

必要に応じて、onMessageとフォルト・ブランチにクリーン・アップ・アクティビティを移入し、Oracle Enterprise Scheduler Webサービスを適切なステータスで起動する必要があります。

フォルトが発生したり、onMessageブランチを経由して取消しメッセージを受信した場合は、ジョブのステータスとステータス・メッセージを監視UIに適切に反映するために、Oracle Enterprise Scheduler Webサービスを介して、Oracle Enterprise Schedulerインフラストラクチャを直接更新する必要があります。この結果、各フォルト処理ブランチまたはonMessageブランチは、適切なステータスとステータス・メッセージ値をOracle Enterprise Scheduler Webサービスのinvoke変数に割り当てる必要があり、必要に応じて、invokeアクティビティを含めるか、または意図的に、ジョブ・ステータスの結果に左右されないよう設計された上位順序のスコープに戻り、invokeアクティビティをOracle Enterprise Scheduler Webサービスで実行してから完了します。

また、必要に応じてアクティビティをonMessageおよびフォルト・ブランチにドラッグし、クリーンアップ、記録または補正を行います。

図16-18に、onMessageおよびフォルト処理ブランチを含むスコープの例を示します。

図16-18 BPELフロー全体のサンプル

BPELフロー全体のサンプル
「図16-18 BPELフロー全体のサンプル」の説明

16.4.7 デプロイメントの検証

正常に機能するかどうかテストするには、次の一連の手順を実行する必要があります。

  1. 次のサイトにナビゲートしてEDN-DB-LOGページを表示し、ログは有効であると表示されていることを確認します。そうでない場合、「有効化」のリンクをクリックします。

    http://host:port/soa-infra/events/edn-db-log
    
  2. 独自のアプリケーション(ジョブ・リクエストを発行するためのFusion Middleware Controlのタスク・フロー・ユーザー・インタフェース)を使用してジョブを発行し、ジョブのステータスがRUNNINGであることを確認します。

  3. イベントが即座にEDN-DB-LOGページに表示されます。例16-6に示すように、このイベント・ペイロードを確認します。

    例16-6 イベント・ペイロード

    Example:Enqueing event: http://xmlns.oracle.com/apps/ta/essdemo/events/edl::ESSDemoEvent from J
    Body: <business-event xmlns:ns="http://xmlns.oracle.com/apps/ta/essdemo/events/edl" xmlns="http://oracle.com/fabric/businessEvent">
    <name>ns:ESSDemoEvent</name>
    <id>df8e34c1-4c65-4379-b9be-2c692670ebbe</id>
    <content>
    <ESSDemoEventElement xmlns="http://xmlns.oracle.com/apps/ta/essdemo/events/schema">
    <requestId>3</requestId>
    <executionContext>3, false, null, 6A4A16757764CD60E0402382B7703F44, 12</executionContext>
    <eventType>ESS_EVENT</eventType>
    </ESSDemoEventElement>
    </content>
    </business-event>
    Subject name:
    Enqueing complete
    Enqueing event: http://xmlns.oracle.com/apps/ta/essdemo/events/edl::ESSDemoEvent from J
    Body: <business-event xmlns:ns="http://xmlns.oracle.com/apps/ta/essdemo/events/edl" xmlns="http://oracle.com/fabric/businessEvent">
    <name>ns:ESSDemoEvent</name>
    <id>a4104da8-5579-4434-ab8b-d31a226e3b0f</id>
    <content>
    <ESSDemoEventElement xmlns="http://xmlns.oracle.com/apps/ta/essdemo/events/schema">
    <requestId>4</requestId>
    <executionContext>4, false, null, 6A4A2BC7E5477C60E0402382B77041C9, 12</executionContext>
    <eventType>ESS_EVENT</eventType>
    </ESSDemoEventElement>
    </content>
    </business-event>
    
  4. サブスクライブするメディエータがトリガーされたら、例16-7に示すように、Fusion Middleware Control ($DOMAIN_HOME/as.log)またはsoa-diagnostic logs ($DOMAIN_HOME/servers/<serverName>logs/<serverName>.log)を確認して、イベントの結果としてのメディエータのアクティビティを確認できます。

    例16-7 メディエータのアクティビティ

    INFO: MediatorServiceEngine received an event =
    {http://xmlns.oracle.com/apps/ta/ess/demo/events/edl}ESSDemoEvent
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.common.persistence.MediatorPersistor persistCallback
    INFO: No call back info set in incoming message
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.common.persistence.MediatorPersistor persistCallback
    INFO: Message properties :
    {id=041ecfcf-8b73-4055-b5c0-0b89af04f425, tracking.compositeInstanceId=50003, tracking.ecid=0000I2pqzVCBLA5xrOI7SY19uEYF00004g:47979}
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.dispatch.InitialMessageDispatcher dispatch
    INFO: Executing Routing Service..
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.dispatch.InitialMessageDispatcher processCases
    INFO: Unfiltered case list size :1
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.monitor.MediatorActivityMonitor createMediatorCaseInstance
    INFO: Creating case instance with name :ESSDemoProcess.essdemoprocess_client.process
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.dispatch.InitialMessageDispatcher processCase
    INFO: Immediate case
    {ESSDemoProcess.adedemoprocess_client.process}with case id :
    {5B52B4A02B9211DEAF64D3EF6E2FB21D}will be executed
    Apr 17, 2009 1:57:26 PM oracle.tip.mediator.service.filter.FilterFactory createFilterHandler
    INFO: No Condition defined
    
  5. Oracle Enterprise Manager Fusion Middleware ControlコンソールでSOAコンポジットのインスタンスを確認して、エラーを確認します。

    http://host:port/em
    
  6. BPELプロセスにエラーがなく、ヒューマン・ワークフロー通知からのレスポンスが予期されている場合、ワークリストにナビゲートして割り当てられた承認者としてログインし、設計の要件ごとに通知を承認するか、または拒否します。

  7. ここから、BPELプロセスを完了してOracle Enterprise Scheduler Webサービスを起動し、ジョブの完了ステータスとステータス・メッセージを設定する必要があります。監視UIの診断ログで、スタック・トレースとログ・メッセージを確認します。

  8. また、Oracle Enterprise SchedulerスキーマのREQUEST_HISTORY表で、ジョブの状態の詳細を確認できます。

16.4.8 ユースケースのトラブルシューティング

Oracle ADF UI機能(監視や発行のタスク・フローなど)に関する問題をトラブルシューティングするには、サーバーのコンソール・ログ、アプリケーション・ログおよびサーバー診断ログを使用して、失敗の原因と理由を確認します。

イベント機能に関する問題(リクエストの実行コンテキストが失われない状態でイベントがBPELプロセスに到達しないなど)をトラブルシューティングするには、EDNデータベース・ログ・ページ(http://host:post/soa-infra/events/edn-db-log)を使用してイベント・ペイロードを検査し、スキーマ定義と慎重に比較します(多少不一致があってもトランスフォーメーションは成功する場合がありますが、BPELに対してリクエスト・コンテキスト値が欠落したスケルトン・ペイロードが生成されます)。Oracle JDeveloperおよびサードパーティのツールを使用して、イベント・ペイロードのスキーマを検証したり、そのペイロードに対してトランスフォーメーションをデバッグできます。

メディエータ(BPEL SOA機能)をトラブルシューティングするには、診断にOracle Enterprise Managerおよびサーバー・コンソールまたは診断ログ・ファイルを使用して、ロギングにAppsLoggerセンサー変数を使用します。

実行時のOracle Enterprise Schedulerのトラブルシューティングの詳細は、『Oracle Fusion Middleware Oracle Enterprise Scheduler管理者ガイド』の「Oracle Enterprise Schedulerのトラブルシューティング」を参照してください。

16.5 非同期ジョブのタイムアウトおよびリカバリの処理

Oracle Enterprise Schedulerの非同期Javaジョブは、リモート・ジョブに依存してOracle Enterprise Schedulerを完了ステータスで更新した後、リクエスト処理を完了できます。リモート通信の性質上、ネットワーク障害などが原因で、リモートのリクエスト・ステータスがOracle Enterprise Schedulerで受信されない場合があります。このような場合、リクエストは非終了状態でスタックされることがあります。

タイムアウト・リクエストの終了状態への遷移は、次のことを可能にするので、重要です:

16.5.1 非同期リクエストのタイムアウト

Oracle Enterprise Schedulerのシステム・プロパティSystemProperty.ASYNC_REQUEST_TIMEOUTを使用すると、非同期Javaジョブに対するジョブ・リクエストのタイムアウト値を設定できます。デフォルトでは、このプロパティは有効化されておらず、その値はゼロ以下となっています。

プロパティは、ジョブ定義メタデータで設定されたり、ジョブ・リクエストの発行時に設定される場合があります。値は、ジョブ・リクエストによりローカル実行が開始されたときから、非同期ジョブの最終ステータスがリモート・ジョブから受信されるまでの期間(分単位)を表します。

16.5.1.1 タイムアウト値の設定

指定された非同期ジョブ・リクエストの場合、システム・プロパティSystemProperty.ASYNC_REQUEST_TIMEOUTを0より大きい値に設定します。

16.5.1.2 タイムアウトした非同期ジョブ・リクエストの検出

指定されたリクエストについて、RequestDetail.isTimedOutはタイムアウトのステータスを示します。タイムアウトしたリクエストは、例16-8に示す問合せを使用して検出できます。

例16-8 タイムアウト・ステータスの表示

Filter timedOutRunningFilter = new Filter(
    RuntimeService.QueryField.TIMED_OUT.fieldName(),
    Filter.Comparator.EQUALS,
    Boolean.TRUE)
.and(
    RuntimeService.QueryField.STATE.fieldName(),
    Filter.Comparator.EQUALS,
    State.RUNNING.value());
runtimeService.queryRequests(handle, timedOutRunningFilter, null, true);

例16-9に示すように、REQUEST_HISTORY_VIEWを使用して、同様の問合せを実行できます。

例16-9 REQUEST_HISTORY_VIEWの使用

SELECT requestId FROM request_history_view WHERE timedout='Y' AND state=3;

16.5.1.3 タイムアウトがない非同期リクエストの完了

タイムアウト値がない場合、リモート・ジョブがステータスをOracle Enterprise Schedulerに配信せずに完了した非同期リクエストは、RuntimeMXBean.completeAsyncRequestを使用して直接完了することがあります。注意が必要であることを示すフラグをリクエストに付けるためのタイムアウト値がないため、タイムアウトのないリクエストを慎重に追跡する必要があります。

タイムアウトがないジョブ・リクエストの管理の詳細は、『Oracle Fusion Middleware Oracle Enterprise Scheduler管理者ガイド』の「Oracle Enterprise Schedulerのトラブルシューティング」を参照してください。

16.5.1.4 非同期ジョブ・リクエストのタイムアウト時の処理内容

Oracle Enterprise Schedulerでは、プロパティSystemProperty.ASYNC_REQUEST_TIMEOUTが設定された非同期ジョブ・リクエストを定期的に確認します。最終ステータスが受信されずに時間が超過すると、タイムアウトしたというフラグがジョブに付けられます。それ以外の場合、ジョブの状態は影響を受けず、RUNNING状態のままとなります。その一方で、Oracle Enterprise Schedulerでは、リモート・ジョブからのステータス更新を引き続き受け入れます。フラグは、リモート・ジョブのステータス調査が必要である可能性があることを示します。

16.5.2 手動リカバリ対象としてマークされた非同期ジョブの処理

リモート・ジョブは完了したが、そのステータスがOracle Enterprise Schedulerに配信されなかった場合、リクエストを手動で完了できます。

ジョブが実行中かどうかがわからない場合など、ジョブのステータスを自動で決定できない場合もあります。ジョブが実行中の場合、ジョブ・リクエストが終了状態に遷移しないようにする必要があります。ジョブが終了状態に遷移すると、非互換性ロックが解放され、互換性のないジョブ・リクエストが同時に実行される可能性があります。

次に例を示します。

  • リモート・サービスが開始したときに非同期Javaジョブでエラーが発生し、リモート・サービスが実際に起動されたことが不明確になります。リモート・ジョブが実行中かどうかが判断されるまで、ジョブ・リクエストがエラー状態にならないようにする必要があります。ジョブが実行中である可能性がある場合、ジョブでは、ジョブ・リクエストがERROR_MANUAL_RECOVERY状態に遷移する必要があることをOracle Enterprise Schedulerに示すために、oracle.as.scheduler.ExecutionManualRecoveryExceptionをスローする必要があります。

  • Oracle Enterprise Schedulerの非同期Javaジョブはjava.lang.Errorをスローしますが、これにより、リモート・サービスが起動されたかどうかをOracle Enterprise Schedulerに示すことはありません。

  • 生成されたジョブはクラスタ化された環境で実行中であり、ジョブ・リクエストはOracle Enterprise Scheduler instance1で実行中です。Oracle Enterprise Scheduler instance1サーバーは、関連するPerlエージェントとともに停止します。instance1がしばらくの間リカバリしない場合、ジョブ・ステータスは不明となります。このタイプの状況では、プロパティState.ERROR_MANUAL_RECOVERYを使用します。これは、リカバリ操作が手動で起動されるまでジョブ・リクエストの処理を一時停止する非終端状態です。取得された非互換性ロックは、手動リカバリが完了するまで保持されます。

手動リカバリ対象としてマークされた非同期ジョブの処理の詳細は、『Oracle Fusion Middleware Oracle Enterprise Scheduler管理者ガイド』の「Oracle Enterprise Schedulerのトラブルシューティング」の手動リカバリを要するスタック非同期ジョブの処理に関する項を参照してください。

16.5.3 ジョブ・リクエストの手動リカバリに対するRecoverRequestの使用

一部のジョブ・リクエストが不完全な状態でスタック状態となった場合、最初に、ジョブ・リクエストが通常の方法で完了できるかどうかを判断する必要があります。たとえば、ジョブ・リクエストがRUNNING状態の場合、リモートで実行中の非同期Javaジョブのためである場合があります。リモート・ジョブが応答できない場合、ジョブ・リクエストの取消しを試行する必要があります。これにより、ジョブ・リクエストはCANCELLING状態に遷移します。ジョブ・リクエストがCANCELLED状態に遷移しない場合は、リカバリ対象の候補にすることができます。

リカバリ対象となるリクエストの子リクエストはすべて、すでに完了している必要があり、これは、そのプロセス・フェーズがProcessPhase.Completeであることを意味します。RequestDetail.getProcessPhase()を実行して、プロセス・フェーズを取得できます。

RuntimeService.queryRequestsを使用すると、例16-10に示すフィルタを使用して、不完全な子リクエストを判別する問合せを実行できます。

例16-10 不完全な子リクエストのフィルタリング

Filter filter =
            new Filter(RuntimeService.QueryField.ABSPARENTID.fieldName(),
                       Filter.Comparator.EQUALS, requestId)
            .and(RuntimeService.QueryField.REQUESTID.fieldName(),
                 Filter.Comparator.NOT_EQUALS, requestId)
            .and(RuntimeService.QueryField.PROCESS_PHASE.fieldName(),
                 Filter.Comparator.NOT_EQUALS,
                 ProcessPhase.Complete.value());

いずれかの子リクエストで手動リカバリが必要であると判断された場合、最初に、これらのジョブに対してrecoverRequestを起動します。不完全な子リクエストを含む親リクエストに対してrecoverRequestが起動されると、例外がスローされます。この例外メッセージには、不完全な子リクエストがリストされます。例16-11に、recoverRequest構文を示します。

例16-11 recoverRequest

   /**
     * Attempts to force a request to complete under certain conditions.
     * <p>
     * 1. The request must already by in a terminal state, {@code
     *    State.CANCELLING}, or {@code State.ERROR_MANUAL_RECOVER}.
     *    If a request is in another state,
     *    {@code RuntimeService.cancel} must be called first. If the
     *    request does not eventually transition to {@code State.CANCELLED},
     *    then this operation may be invoked on the request.
     * 2. All child requests of the given request must already be complete.
     * <p>
     * A <b>completed></b> request is a request in a terminal state with
     * a process phase of {@code ProcessPhase.Complete}.
     * <p>
     * Note that this operation will lock the request.
     * <p>
     * @param requestId the request identifier of the request.
     * @throws IOException if a protocol error occurred.
     * @throws InstanceNotFoundException if the request is not found
     * @throws OperationException if the given request has child requests
     *  that are not complete.
     * @throws RuntimeOperationsException if a RuntimeService subsystem failure
     * occurs.
     */
    public void recoverRequest( long requestId )
        throws IOException, InstanceNotFoundException, OperationsException,
               RuntimeOperationsException;

同期Javaジョブの手動による処理の詳細は、『Oracle Fusion Middleware Oracle Enterprise Scheduler管理者ガイド』の「Oracle Enterprise Schedulerのトラブルシューティング」、手動リカバリを要する同期Javaジョブの処理に関する項を参照してください。

16.6 Oracle Enterprise Schedulerのインタフェースとクラス

Oracle Enterprise Schedulerの新規非同期コールバック・インタフェースとクラスのサンプル・コードを例16-12例16-13例16-14および例16-15に示します。

例16-12 Oracle Enterprise SchedulerのUpdatableインタフェース

public interface Updatable
{
   /**
    * Invoked by Enterprise Scheduler when a job request is updated.
    * This method must eventually return control to the caller.
    *
    * @param  context  An oracle.as.scheduler.RequestExecutionContext 
    * object for this request.
    *
    * @param parameters  the request parameters associated with this request
    *
    * @param resultCode the {@code
    * oracle.as.scheduler.async.UpdateAction.ActionCode} indicating the
    * action that generated this event.
    *
    * @param messagePayload a {@code String} representing the body of this
    * event. The content and format are not known by the Enterprise Scheduler.
    */
    public UpdateAction onEvent( RequestExecutionContext context, 
RequestParameters parameters,
                             oracle.as.scheduler.async.AsyncStatus resultCode,
                             String messagePayload );
}

UpdateActionクラスはUpdatable.onEventによって返されます。

例16-13 Oracle Enterprise SchedulerのUpdateActionクラス

package oracle.as.scheduler.async;
 
/**
 * Enumeration of return values from application execution callout. The
 * action returned determines how the subsequent processing of the request
 * will proceed.
 */
public class UpdateAction
{
    /**
     * Constructor. Creates an UpdateAction object from the status
     * and message components.
     *
     * @param status Indicates the status of execution of this update event.
     * This status may result in a state transition for the request.
     *
     * @param message A message that, depending on the value of {@code status},
     * may be used for various purposes.
     */
    public UpdateAction( AsyncStatus status, String message );
 
    public AsyncStatus getAsyncStatus( );
    
    public String getMessage( );
}

AsyncStatus列挙が変更されました。

例16-14 Oracle Enterprise SchedulerのAsyncStatus列挙

Package oracle.as.scheduler.async;
 
/**
* Valid values for the callback status of an asynchronous java job.
 * Returning an {@code AsyncStatus} does not guarantee that the state of the
 * request will change to the corresponding value. The new state of the request
 * will depend on the old state, the async status, the result of the
 * post-Process handler (if any), and any errors that may occur in
 * subsequent processing.
 */
public enum AsyncStatus
{
    /**
     * The asynchronous job ran successfully.
     */
    SUCCESS,
 
    /**
     * The asynchronous job has paused for the execution of sub-requests.
     */
    PAUSE,
 
    /**
     * The asynchronous job is issuing a WARNING.
     */
    WARNING,
 
    /**
     * The asynchronous job encountered an error.
     */
    ERROR,
 
    /**
     * The asynchronous job has canceled its execution. Usually this
     * originates from a {@code RuntimeService.cancel} call.
     */
    CANCEL,
 
    /**
     * The asynchronous job is updated. The request state is not changed
     * by this action.
     */
    UPDATE
}
    /**
     * The asynchronous job encountered a business error.
     */
    BIZ_ERROR,
 
    /**
     * The asynchronous job requests manual recovery to complete the request.
     */
    ERROR_MANUAL_RECOVERY;

例16-15 既存の非同期コールバックWebサービス操作

   /**
     * Set the status of an Oracle Enterprise Scheduler asynchronous java job.
     *
     * @param requestExecutionContext A java.lang.String representing
     * an oracle.as.scheduler.RequestExecutionContext object.
     * @param status
     * @param statusMessage 
     *   An error message if the status is ERROR,
     *   A business error message if the status is BIZ_ERROR,
     *   A warning message if the status is WARNING, 
     *   A paused state if the status is PAUSED.
     *   The value is ignored if the status is SUCCESS or CANCEL.
     *   
     */
    public void setAsyncRequestStatus( String requestExecutionContext,
                                       AsyncStatus status,
                                       String statusMessage )
        throws RequestNotFoundException, RuntimeServiceException ;