22 ジョブ・リクエスト・ログと出力

この章では、Oracle Enterprise Schedulerを使用して、管理者とユーザーが後で使用できるように保存する必要があるジョブ・リクエスト・ログと出力を生成する方法について説明します。

ジョブ・リクエストによって生成されるログは、管理者が問題を診断したり、ジョブ固有の状態を確認するのに役立ちます。ログには、Fusion Middleware Controlからアクセスできます。さらに、一部のジョブでは、ジョブの完了後にユーザーが確認できるジョブ固有のデータに関するレポートなどの出力が、その作業の一環として生成されます。コードで、リクエスト・ログ情報およびリクエストの出力を作成および格納できます。

この章の内容は次のとおりです。

22.1 リクエスト・ログ

Oracle Enterprise Schedulerでは、ジョブがリクエストのロギングに使用できるAPIが提供されています。プロセス・ジョブを除くすべてのジョブ・タイプで、ロギングAPIが使用されます。また、Oracle Enterprise Schedulerは、コンテンツ・ストア内のリクエスト・ログを処理するAPIも提供します。

Oracle Enterprise Schedulerでは、リクエストごとに1つのログがサポートされます。このログにはREQUESTID.logという形式の名前が付けられます。ロギングAPIでは、コンテンツ・ストアに直接ログが記録され、ログ・コンテンツはロールバックできません。

Fusion Middleware Controlによるジョブ・リクエストの表示の詳細は、『Oracle Fusion Middleware Oracle Enterprise Schedulerの管理』ジョブ・リクエスト・ログの表示に関する項を参照してください。

22.1.1 システム・プロパティ

APIによりメッセージが記録されるシステム・プロパティSYS_EXT_requestLogLevel制約は、リクエスト・ログに格納されます。

プロパティの値は、デフォルトでINFOに設定されます。有効な値の完全なセットは、SEVEREWARNINGINFOCONFIGFINEFINERFINESTです。JavaおよびPL/SQL APIを使用して、リクエストのログ・レベルを検出します。

プロセス・ジョブではロギングAPIが使用されないため、SYS_EXT_requestLogLevelはプロセス・ジョブに適用されないことに注意してください。

22.1.2 ログ・ヘッダー

ロギング・コードにより、次の見出し情報で始まるログにエントリが書き込まれます。このヘッダーは、ロギングAPIによりログに書込まれる各レコードの先頭に自動的に付けられるため、プロセス・ジョブには適用されません。

####[TIMESTAMP] [LOGLEVEL]
 
Sample log lines:
####[2011-07-11T14:20:32.276-07:00] [INFO] This is a log record.
####[2011-07-11T14:20:32.282-07:00] [INFO] This is the first line of a multi-line log record:
second line of multi-line log record.

22.1.3 Javaジョブからのリクエスト・ロギング

Javaリクエスト・ロガーを使用して、Javaまたは非同期Javaジョブの実行および更新ステージ中、およびすべてのジョブ実行タイプの前処理および後処理中にログを記録できます。

ジョブ・ロジックでは、ContentFactory APIを使用して、リクエスト・ログへのメッセージの記録に使用できるRequestLoggerを取得する必要があります。Oracle Enterprise Schedulerでは、ロガーが取得されるたびに、SYS_EXT_requestLogLevelシステム・プロパティの現行値を使用して、ロギング・レベルを制限します。

22.1.3.1 Javaジョブ・ログ出力用API

Javaジョブのロジックで、oracle.as.scheduler.request.ContentFactoryクラスのgetRequestLoggerメソッド(表22-1を参照)を使用して、ログ・エントリを追加するためのRequestLoggerインスタンスを取得できます。リクエスト・ロガーでは、リソース・バンドルはサポートされていないことに注意してください。

ログの処理に使用できるJava APIは次のとおりです。

  • ContentFactoryクラスは、ログの作成やエントリの追加に使用できるRequestLoggerのインスタンスを取得するために使用します。表22-1を参照してください。

  • RequestLoggerクラスは、ログを書き込むために使用します。表22-2を参照してください。

oracle.as.scheduler.request.ContentFactoryクラスには、コードが、出力コンテンツ・フレームワークにアクセスしたり、出力自体を作成するために使用できるインスタンスにアクセスできるようにするメソッドが備えられています。

表22-1 リクエスト・ログを作成するためのContentFactoryメソッド

メソッド 説明

getRequestLogger( long requestId )

指定されたrequestIdに対してRequestLoggerインスタンスを返し、requestId.logという名前のログ・コンテンツをOracle Enterprise Schedulerコンテンツ・ストアに作成します。

ロガー・インスタンスを取得すると、エントリを追加するために、表22-2に示されているメソッドを使用できます。

表22-2 リクエスト・ログを作成するためのRequestLoggerメソッド

メソッド 説明

log( Level level, String msg )

fine( String msg )

finer( String msg )

finest( String msg )

これらのメソッドによって、指定されたレベルでメッセージがログに記録されます。

指定されたロギング・レベルが、SYS_EXT_requestLogLevelシステム・プロパティで指定されたログ・レベル以上である場合にのみ、メッセージがログに記録されます。このプロパティが設定されていない場合のデフォルト・ログ・レベルはINFOです。

logメソッドを使用する場合、java.util.logging.Levelでは、次に降順で示す値をサポートします。

  • SEVERE

  • WARNING

  • INFO

  • CONFIG

  • FINE

  • FINER

  • FINEST

22.1.3.2 Javaリクエスト・ロギングの例

例22-1に、ロギングを行う非常に単純なJavaジョブの例を示します。

例22-1 Javaのリクエスト・ロギングの例

import oracle.as.scheduler.request.ContentFactory;
import oracle.as.scheduler.request.RequestLogger;
import java.util.logging.Level;

class ExampleJavaLogger{
 
  private boolean m_loggingEnabled = false;
  private RequestLogger m_requestLogger = null;
 
  public void execute( RequestExecutionContext ctx,
                       RequestParameters params )
  {
    try
    {
      m_requestLogger = ContentFactory.getRequestLogger(ctx.getRequestId());
      m_loggingEnabled = true;
    }
    catch (Exception ex)
    {
      // failed to get request logger
    }
 
    log(Level.INFO, "Starting the job.");
    // ...
    log(Level.INFO, "Ending the job.");
  }
 
  private void log( Level level, String message )
  {
    if (m_loggingEnabled)
    {
        m_requestLogger.log(level, message);
    }
  }
}

22.1.4 PL/SQLジョブからのリクエスト・ロギング

PL/SQLからログを作成する場合は、ログ・エントリを書き込むために、コードでESS_JOB PL/SQLパッケージを使用できます。

22.1.4.1 ログを作成するためのESS_JOBパッケージ・サポート

Oracle Enterprise Schedulerには、PL/SQLコードからログを作成するためのファンクションおよびプロシージャを含むESS_JOBパッケージが備えられています。

表22-3 リクエスト・ロギング用のESS_JOBファンクションおよびプロシージャ

メソッド 説明

procedure write_log( p_level in integer, p_text in varchar2 );

現行セッションに関連付けられているOracle Enterprise Schedulerリクエストに対して、p_textをメッセージとしてリクエスト・ログ・コンテンツに書き込みます。

指定されたロギング・レベルが、SYS_EXT_requestLogLevelシステム・プロパティで指定されたログ・レベル以上である場合にのみ、メッセージがログに記録されます。このプロパティが設定されていない場合のデフォルト・ログ・レベルはLEVEL_INFOです。

ログ・レベルの値は、java.util.logging.Levelで定義された値に対応します。

p_levelパラメータに次の値を使用します(降順で示します)。

  • LEVEL_SEVERE

  • LEVEL_WARNING

  • LEVEL_INFO

  • LEVEL_CONFIG

  • LEVEL_FINE

  • LEVEL_FINER

  • LEVEL_FINEST

22.1.4.2 PL/SQLのリクエスト・ロギングの例

SQLリクエスト・ジョブ・プロシージャによるリクエスト・ロギングの例を次に示します。

create or replace procedure log_example_job
( request_handle in varchar2 )
as
  v_request_id  number := null;
begin
  ess_job.write_log(ess_job.level_fine,
                    'LOG_EXAMPLE_JOB Procedure Begin');
 
  -- Oracle Enterprise Scheduler request id being executed.
  begin
    v_request_id := ess_runtime.get_request_id(request_handle);
  exception
    when others then
      ess_job.write_log(ess_job.level_severe,
                        'Bad request handle: '||request_handle);
      raise_application_error(-20000,
         'Failed to get request id for request handle '||request_handle,
         true);
  end;
 
  -- Job logic
  ess_job.write_log(ess_job.level_info,
                    'Executing job logic...');
 
  ess_job.write_log(ess_job.level_fine,
                    'LOG_EXAMPLE_JOB Procedure End');
end;
/

22.1.5 プロセス・ジョブからのリクエスト・ロギング

プロセス・ジョブからジョブ・リクエスト・ログに書き込むことができます。この動作は、特定のレベルでエントリを書き込むためのAPIに実行コードからアクセスできる、JavaおよびPL/SQLジョブとは大きく異なります。プロセス・ジョブでは、かわりに、ジョブの標準出力および標準エラーが、リクエストのログ作業ディレクトリ(Oracle Enterprise Schedulerにより設定される場所)にあるファイルにリダイレクトされます。Oracle Enterprise Schedulerは、このファイルをインポートし、コンテンツ・ストア内のリクエスト・ログに付加します。

つまり、プロセス・ジョブからログを記録するために必要なのは、ジョブ・ロジック・コードから標準出力に書き込むことのみです。

ログ・ファイルの読取りに使用されるエンコーディングは、「プロセス・ジョブのロケール」の説明に従って決定されます。

プロセス・ジョブから特定のレベルでログを記録できないことに注意してください(レベルを設定するためのAPIが使用できないため)。このため、ログ・コンテンツはSYS_EXT_requestLogLevelシステム・プロパティによって制限されません。Oracle Enterprise Schedulerでは、常にログ・ファイルのコンテンツをコンテンツ・ストア内のリクエスト・ログに付加します。

22.1.6 EJBジョブからのリクエスト・ロギングおよび出力

EJBジョブはリモートで実行されるJavaジョブであるため、リモートEJBジョブ実装はコンテンツをログおよび出力に書込むことができます。このコンテンツを処理するには、oracle.as.scheduler.request.RemoteContentHelper APIを使用します。次の箇条書きの項目は、必要なステップの概要を示しています。例22-2に、この機能を表すEJBジョブ実装を示します。

  • RemoteContentHelperを設定します。パラメータRequestExecutionContextおよびRequestParametersは、ジョブ実装のexecute()メソッドから取得できます。

    RemoteContentHelper rch=new RemoteContentHelper(RequestExecutionContext, RequestParameters);
    
  • コンテンツをログ・ファイルに書き込みます。

    rch.log(Level.INFO, logMessage)
    
  • テキスト出力を書き込みます。

    RuntimeServiceHandle rsh = null;
     ContentHandle ch = null;
     String contentName = "Content1";
     String contentData = "Some text content";
     try {
        rsh = rch.getRuntimeService().open();
        ch = rch.openOutputContent(rsh, contentName, ContentType.Text,        EnumSet.of(ContentHandle.ContentOpenOptions.Write));
        rchelper().write(ch, contentData);
     } catch (Exception ex) {
        throw new ExecutionErrorException(ex);
     } finally {
        rch.closeOutputContent(ch);
        rch.getRuntimeService().close(rsh);
     }
    
  • バイナリ出力を書き込みます。

    RuntimeServiceHandle rsh = null;
     ContentHandle ch = null;
     String contentName = "Content1";
     String contentData = "Some binary content"; //Binary content can differ in the     variable declaration.
     try {
         rsh = rch.getRuntimeService().open();
         ch = rch.openOutputContent(rsh, contentName, ContentType.Binary,         EnumSet.of(ContentHandle.ContentOpenOptions.Write));
         rchelper().write(ch, contentData.getBytes());
     } catch (Exception ex) {
         throw new ExecutionErrorException(ex);
     } finally {
         rch.closeOutputContent(ch);
         rch.getRuntimeService().close(rsh);
     }
    

例22-2に、出力およびログの処理方法を表すEJBジョブ実装を示します。

例22-2 SimpleSyncEssBean

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.EnumSet;
 
import javax.ejb.Stateless;
 
import oracle.as.scheduler.RuntimeServiceHandle;
import oracle.as.scheduler.ExecutionCancelledException;
import oracle.as.scheduler.ExecutionErrorException;
import oracle.as.scheduler.ExecutionPausedException;
import oracle.as.scheduler.ExecutionWarningException;
import oracle.as.scheduler.RemoteExecutable;
import oracle.as.scheduler.RequestExecutionContext;
import oracle.as.scheduler.RequestParameters;
import oracle.as.scheduler.request.RemoteContentHelper;
import oracle.as.scheduler.request.ContentDetail;
import oracle.as.scheduler.request.ContentHandle;
import oracle.as.scheduler.request.ContentType;
 
@Stateless(name = "SimpleSyncEssBean")
public class SimpleSyncEssBean implements RemoteExecutable {
    private RemoteContentHelper m_rch = null;
 
    public void execute(RequestExecutionContext requestExecutionContext,
                        RequestParameters requestParameters) throws ExecutionErrorException, ExecutionWarningException,
                                                                    ExecutionCancelledException,
                                                                    ExecutionPausedException {
        long requestId = requestExecutionContext.getRequestId();
        // setup helper now so it is available to println
        m_rch = setupRemoteContentHelper(requestExecutionContext, requestParameters);
 
        ContentType contentType = ContentType.Text;
        String contentName = requestId + "Output.txt";
 
        ArrayList<String> srcLines = new ArrayList<String>();
        srcLines.add("SimpleSyncEssBean Output Details \n");
        boolean success = false;
        String exmsg = "";
 
        try {
            createOutputContent(contentName, contentType, srcLines);
            success = verifyOutputContent(contentName, contentType, srcLines);
        } catch (ExecutionErrorException ex) {
            exmsg = ex.getMessage();
        }
 
        if (!success) {
            throw new ExecutionErrorException("Output test failed: " + contentName                 + ", " + exmsg);
        } else {
            printToLog("Output test succeeded: " + contentName);
        }
        printToLog(" SimpleSyncEssBean job succeeded. RequestId:" + requestId);
    }
 
    /**
     * Creates the remote content helper for log/output.
     */
    private RemoteContentHelper setupRemoteContentHelper(RequestExecutionContext        ctx, RequestParameters params) throws ExecutionErrorException {

        RemoteContentHelper rch = null;
        try {
            rch = new RemoteContentHelper(ctx, params);
        } catch (Exception ex) {
            throw new ExecutionErrorException(ex);
        }
 
        return rch;
    }
 
    /**
     * Gets the remote content helper that is setup.
     * Throws if it is not setup.
     */
    private RemoteContentHelper rchelper() throws ExecutionErrorException {
        if (null == m_rch) {
            throw new ExecutionErrorException("RemoteContentHelper is not setup");
        }
 
        return m_rch;
    }
 
 
    private void printToLog(String message) throws ExecutionErrorException {
        System.out.println(message);
        if (m_rch != null) {
            try {
                m_rch.log(Level.INFO, message);
            } catch (Exception ex) {
                // ignore
            }
        } else {
            rchelper();
        }
 
    }
 
    /**
     * Writes dataList as either Text or Binary output content.
     */
    private void createOutputContent(String contentName, ContentType contentType,
                                     ArrayList<String> dataList) throws ExecutionErrorException {
        RuntimeServiceHandle rsh = null;
        ContentHandle ch = null;
        try {
            rsh = rchelper().getRuntimeService().open();
            ch =
                rchelper().openOutputContent(rsh, contentName, contentType,
                                             EnumSet.of(ContentHandle.ContentOpenOptions.Write));
 
            for (String data : dataList) {
                if (ContentType.Text == contentType) {
                    rchelper().write(ch, data);
                } else {
                    rchelper().write(ch, data.getBytes());
                }
            }
        } catch (Exception ex) {
            throw new ExecutionErrorException(ex);
        } finally {
            if (ch != null) {
                try {
                    rchelper().closeOutputContent(ch);
                } catch (Exception ex) {
                    printToLog("Error while closing ch: " + ex.getMessage());
                    //ex.printStackTrace();
                    throw new ExecutionErrorException(ex);
                }
            }
            if (rsh != null) {
                try {
                    rchelper().getRuntimeService().close(rsh);
                } catch (Exception ex) {
                    printToLog("Error while closing rsh: " + ex.getMessage());
                    //ex.printStackTrace();
                    throw new ExecutionErrorException(ex);
                }
            }
        }
    }
 
    /**
     * Verifies Text or Binary output content.
     */
    private boolean verifyOutputContent(String contentName,         ContentType contentType, ArrayList<String> srcDataList)         throws ExecutionErrorException {

        String actualData = getOutputContent(contentName, contentType);
 
        StringBuffer sb = new StringBuffer();
        for (String str : srcDataList) {
            sb.append(str);
        }
        String srcData = sb.toString();
 
        boolean success = srcData.equals(actualData);
 
        if (!success) {
            printToLog("Test failed for " + contentName);
            printToLog("Expected data: <\n" + srcData + ">");
            printToLog("Actual data: <\n" + actualData + ">");
        }
 
        try {
            if (rchelper().outputContentExists(contentName)) {
                ContentDetail detail =                     rchelper().getOutputContentDetail(contentName);
                printToLog("ContentDetail:\n" + detail);
            } else {
                printToLog("The output content details are not present:\n");
            }
 
        } catch (Exception ex) {
            String exm = "Failed to get output content detail: " + contentName;
            printToLog(exm);
            throw new ExecutionErrorException(ex);
        }
 
        return success;
    }
 
 
    /**
     * Gets either Text or Binary output content as String.
     */
    private String getOutputContent(String contentName, ContentType contentType)        throws ExecutionErrorException {
        RuntimeServiceHandle rsh = null;
        long requestId = rchelper().getRequestExecutionContext().getRequestId();
        ContentHandle ch = null;
        String result = null;
        try {
            rsh = rchelper().getRuntimeService().open();
            ch =
                rchelper().openOutputContent(rsh, contentName, contentType,
                                             EnumSet.of(ContentHandle.ContentOpenOptions.Read));
 
            if (ContentType.Text == contentType) {
                char[] chars = rchelper().getTextContent(ch, Integer.MAX_VALUE);
                result = new String(chars);
            } else {
                byte[] bytes = rchelper().getBinaryContent(ch, Integer.MAX_VALUE);
                result = new String(bytes);
            }
        } catch (Exception ex) {
            throw new ExecutionErrorException(ex);
        } finally {
            if (ch != null) {
                try {
                    rchelper().closeOutputContent(ch);
                } catch (Exception ex) {
                    printToLog("Error while closing ch: " + ex.getMessage());
                    //ex.printStackTrace();
                    throw new ExecutionErrorException(ex);
                }
            }
            if (rsh != null) {
                try {
                    rchelper().getRuntimeService().close(rsh);
                } catch (Exception ex) {
                    printToLog("Error while closing rsh: " + ex.getMessage());
                    //ex.printStackTrace();
                    throw new ExecutionErrorException(ex);
                }
            }
        }
 
        return result;
    }
 
}

22.1.7 Webサービス・ジョブからのリクエスト・ロギング

進捗状況メッセージは、非同期ジョブにのみ提供されます。Oracle Enterprise Scheduler AsyncWebServiceJobコールバック・エンドポイントは、新しいlogAsyncWSJobProgressMessage一方向操作をサポートします。この操作では、非同期SOAコンポジット(またはその他の非同期Webサービス)により、相関のws-addressing、および同じコールバック・エンドポイントおよび関連付けされたコールバックOWSMポリシーを使用して進捗状況メッセージを記録できます。これにより、非同期SOAコンポジットからのロギング進捗状況メッセージのための簡易的で便利なオプションが提供されます。

Oracle Enterprise Schedulerの非同期Webサービス・ジョブのコールバック・エンドポイントWSDLは、この操作の使用に必要な情報を提供します。WSDLの一部分を例22-3に示します。

例22-3 非同期Webサービス・ジョブ・コールバック・エンドポイントWSDL

 <xsd:complexType name="logAsyncWSJobProgressMessage">
          <xsd:sequence>
               <xsd:element name="level" type="tns:logLevel" form="qualified"/>
               <xsd:element name="message" type="xsd:string" form="qualified"/>
          </xsd:sequence>
     </xsd:complexType>
 
     <xsd:element name="logAsyncWSJobProgressMessage" type="tns:logAsyncWSJobProgressMessage"/>
    <message name="logAsyncWSJobProgressMessageInput">
        <part name="parameters" element="tns:logAsyncWSJobProgressMessage"/>
    </message>
 
    <portType name="RequestPort">
        <operation name="logAsyncWSJobProgressMessage">
            <input message="tns:logAsyncWSJobProgressMessageInput"                  xmlns:ns1="http://www.w3.org/2006/05/addressing/wsdl"                   ns1:Action="logAsyncWSJobProgressMessage"/>
        </operation>
    </portType>

22.1.8 リクエスト・ログを処理するためのAPI

oracle.as.scheduler.RuntimeServiceクラスのメソッドを使用して、Oracle Enterprise Schedulerコンテンツ・ストアに格納されているログを処理できます。最初に、RuntimeServiceHandleインスタンスを取得する必要があります。このインスタンスを、これらのRuntimeServiceメソッドそれぞれの引数として渡します。

RuntimeServiceHandleの詳細は、「ランタイム・サービスへのアクセスおよびランタイム・サービス・ハンドルの取得方法」を参照してください。

表22-4 リクエスト・ログを処理するためのRuntimeServiceメソッド

メソッド 説明

getLogContentDetail(RuntimeServiceHandle handle, long requestId)

リクエストに対してContentDetailインスタンスをログ・コンテンツの詳細とともに返すか、ログが存在しない場合はNULLを返します。

openLogContent( RuntimeServiceHandle handle, long requestId )

指定されたリクエストに対して、リクエスト・ログを開いてログ・データを取得し、ContentHandleインスタンスを返します。ハンドルを使用して出力データを取得できます。ハンドルを解放するには、コンテンツを閉じる必要があります。

getLogLines( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxLines )

リクエスト・ログから最大maxLines行の文字列配列を返します。最後のコールからこのメソッドまで続けられます。コンテンツ・ハンドルは、前のコールからopenLogContentまでです。これにより、ログから行の文字列配列が行終了文字なしで返されます。行がない場合、配列は空になります。

getTextContent( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxChars )

ログまたは出力テキスト・コンテンツから、最大maxChars文字の文字配列を返します。

closeContent( RuntimeServiceHandle handle, ContentHandle contentHandle )

以前開いたログまたは出力コンテンツを閉じ、ハンドルを解放します。

22.2 リクエスト出力

ジョブを使用して実行時に出力コンテンツを作成できます。たとえば、ユーザーへのレポートで有用なデータをジョブで収集するとします。実行時に生成した出力は、クライアント・ユーザー・インタフェースまたはFusion Middleware Controlを使用して後から取得できます。

コードによって作成される出力は、Oracle Enterprise Schedulerコンテンツ・ストア内で直接作成でき、またファイル・システム内で作成しコンテンツ・ストアにインポートすることもできます。Oracle Enterprise Schedulerにより自動的にインポートすることも、ジョブでOracle Enterprise Scheduler APIを使用して明示的にインポートすることもできます。

ファイル・システムを使用する場合は、Oracle Enterprise Schedulerのess-config.xmlファイルで構成された場所にある特定のディレクトリに書き込みます。Oracle Enterprise Schedulerにより、すべてのリクエストから書き込まれたファイルを格納するためのリクエスト・ファイル・ディレクトリが作成されます。コードでは、リクエスト用に作成されたこのディレクトリのサブディレクトリに書き込みます。Oracle Enterprise Schedulerによって、すべてのリクエストの出力が自動的にコンテンツ・ストアにインポートされ、リクエスト固有のサブディレクトリは削除されます。

Oracle Enterprise Schedulerは、コンテンツ・ストア内の出力コンテンツを管理するためのAPIを提供します。

22.2.1 リクエスト・ファイル・ディレクトリの使用

リクエスト・ファイル・ディレクトリは、Oracle Enterprise Schedulerのess-config.xmlファイルで指定されます。Oracle Enterprise Schedulerでは、リクエストごとに、このリクエスト・ファイル・ディレクトリのリクエスト固有のサブディレクトリを作成できます。これは、一時ファイル用の作業ディレクトリおよびコンテンツ・ストアにインポートする必要がある出力ファイル用の出力ディレクトリです。

コードでは実行時に、それぞれのリクエスト固有のディレクトリに一時ファイルおよび出力ファイルを書き込むことができます。Oracle Enterprise Schedulerにより、リクエストの出力ディレクトリ内のファイルがコンテンツ・ストアにインポートされます。コンテンツのインポートのタイミングは、リクエスト・ファイル・ディレクトリが共有とローカルのどちらであるかに応じて異なります。「リクエスト・ファイル・ディレクトリの共通動作」「共有リクエスト・ファイル・ディレクトリの動作」および「ローカル・リクエスト・ファイル・ディレクトリの動作」を参照してください。

リクエストのすべての出力がコンテンツ・ストアに自動的にインポートされた後、Oracle Enterprise Schedulerによって、リクエスト固有の出力ディレクトリとそのコンテンツが削除されます。

リクエスト・ファイル・ディレクトリはローカルにすることもでき、この場合、単一のサーバーでの作業にのみ使用することを意味します。または共有することもでき、この場合、複数のサーバーで実行される作業によって単一のディレクトリが使用されます。実行時の動作は、ディレクトリがローカルまたは共有のいずれに構成されているかによって異なります。

例22-4に示されているように、ディレクトリはess-config.xmlファイルで指定されます。Oracle Enterprise Schedulerは、RequestFileDirectoryに基づいてUSER_FILE_DIR (SYS_userFileDir)を設定し、プロパティを読取り専用にします。ジョブは、USER_FILE_DIRを設定することでこれをオーバーライドできません。

例22-4 ess-config.xmlファイルによるリクエスト・ファイル・ディレクトリの構成

<ess:EssConfig xmlns:ess="http://ess.oracle.com"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <ess:EssProperties>
        <ess:EssProperty key="RequestFileDirectory" value="/etc/outputfiles" 
	           immutable="true"/>
        <ess:EssProperty key="RequestFileDirectoryShared" value="false" 
            immutable="true"/>
    </ess:EssProperties>
</ess:EssConfig>
22.2.1.1 リクエスト・ファイル・ディレクトリの共通動作

Oracle Enterprise Schedulerにより、出力ディレクトリからすべてのリクエスト出力ファイルがコンテンツ・ストアに自動的にインポートされ、リクエスト作業ディレクトリとそこに含まれるすべてのファイルが削除されます。

既存のコンテンツが以前にインポートされたものである場合には、常に、インポートされたファイルによって同じファイル名の既存のコンテンツが上書きされます。既存のコンテンツがAPIを使用して作成された場合は、新しいファイルと異なるものとみなされ、新しいファイルで上書きされずに無視されます。つまり、APIにより作成されたコンテンツが優先されます。

Oracle Enterprise Schedulerでは、長さゼロの出力ファイルはインポートされません。

22.2.1.2 共有リクエスト・ファイル・ディレクトリの動作

リクエストによって作成されたすべてのファイルは、リクエストが完了して終了状態になるまで、その作業ディレクトリおよび出力ディレクトリに保持されます。共有ファイル・ディレクトリにあるリクエストによって作成されたすべてのファイルは、リクエストのすべてのステージで使用できます。

22.2.1.2.1 共有リクエスト・ファイル・ディレクトリを使用する場合のエラー処理

Oracle Enterprise Schedulerによって、ジョブ・リクエストがRUNNING状態に遷移する前に、リクエスト作業ディレクトリが作成されます。ディレクトリの作成中にエラーが発生すると、常に、リクエストのシステム・エラーが発生します。

ジョブの処理では、ログのインポートはリクエストが終了状態に遷移した後に行われます。ログのインポート中にエラーが発生すると、エラーがログに記録され、リクエスト・ログがファイル・システム内に残されます。ログはコンテンツ・ストアに手動でインポートする必要があります。

すべてのジョブ・タイプで、出力ファイルのインポートはリクエストが終了状態に遷移した後に行われます。出力ファイルのインポート中にエラーが発生すると、エラーがログに記録され、ファイル・システム上の該当ディレクトリに出力ファイルが残されます。出力ファイルを削除する必要があります。

22.2.1.3 ローカル・リクエスト・ファイル・ディレクトリの動作

ステージのリクエストが実行される前には必ず、Oracle Enterprise Schedulerによって、リクエスト固有のディレクトリが作成されます。リクエスト・ファイル・ディレクトリがローカルである場合は、どのサーバーのローカルにも存在することが保証されている場所である必要があります。この場合、あるステージのリクエストによって作成されたファイルが、次のステージでも使用できるとは保証されません。これは、各ステージは独立した作業単位であり、異なるサーバーで実行される可能性があるためです。

ローカル・リクエスト・ファイル・ディレクトリには、Oracle Enterprise Schedulerによって各ステージに対するアクションが実行されることを除き、共通動作が適用されます。これは、各ステージが異なるサーバーで実行される場合があり、次のステージではファイルが存在しない可能性があることから、Oracle Enterprise Schedulerでは各ステージのファイルを取得してクリーン・アップする必要があるためです。

以前にインポートされたすべての出力ファイルにリクエストからアクセスする必要がある場合は、パラメータSYS_EXT_executeAutoExport = trueを設定できます。これが設定されている場合、実行ステージの始めに、以前にインポートされた出力ファイルがOracle Enterprise Schedulerによって自動的にリクエストの作業出力ディレクトリにエクスポートされます。これにより、実行ステージの終わりにファイルがコンテンツ・ストアに再びインポートされる前に、ファイルを更新できるようになります。(コンテンツがエクスポートされても、コンテンツ・ストアからコンテンツは削除されないことに注意してください。)さらに、Oracle Enterprise Schedulerには、以前にインポートされた出力ファイルをリクエストによって選択的にエクスポートするためのAPIが備えられています。

22.2.1.3.1 ローカル・リクエスト・ファイル・ディレクトリを使用する場合のエラー処理

ローカル・リクエスト・ファイル・ディレクトリを使用する場合、ファイルのインポートは各ステージ(前処理、実行、更新、後処理)の終わりに行われます。ログまたは出力ファイルのインポート中にエラーが発生した場合、インポートに失敗したログおよび出力ファイルはrequest_file_directory/preserveにあるミラー・ディレクトリに移動されます。たとえば、リクエスト18の場合は、request_file_directory/preserve/18になります。

前処理ステージでは、ステージの始めにリクエスト・ディレクトリを作成するときか、またはステージの終わりに出力ファイルをインポートするときにエラーが発生すると、リクエストに対するシステム・エラーが発生します。

後処理ステージでは、ステージの始めにリクエスト・ディレクトリを作成するときか、またはステージの終わりに出力ファイルをインポートするときにエラーが発生すると、リクエストに対する警告が発生します。

Javaジョブ、非同期Javaジョブおよびプロセス・ジョブ・リクエストの実行ステージでは、ステージの始めにリクエスト・ディレクトリを作成するときか、以前にインポートされた出力ファイルを自動的にエクスポートするとき(SYS_EXT_executeAutoExportシステム・プロパティを使用する場合など)、またはステージの終わりに出力ファイルをインポートするときにエラーが発生すると、リクエストに対するシステム・エラーが発生します。

リクエストがプロセス・ジョブの場合、リクエスト・ログをインポートするときに発生したエラーはログに記録され、エラーとして処理されません。ログはファイル・システム内に残され、コンテンツ・ストアに手動でインポートできます。プロセス・ジョブの実行中に内部エラーが発生した場合は、ジョブの実行を続行できるため、ジョブおよび出力ファイルはインポートされません。ログおよび出力ファイルは、ジョブの終了時に自動的またはユーザーにより手動でインポートされます。ジョブがERROR_MANUAL_RECOVERYに遷移した場合は、ユーザーがリクエスト・ログおよび出力ファイルをクリーン・アップする必要があります。

更新ステージでは、リクエスト・ディレクトリを作成するときか、または出力ファイルをインポートするときに発生したエラーは、ログに記録されるのみです。

22.2.2 システム・プロパティ

リクエスト・ファイル・ディレクトリを使用して出力ファイルを自動的にインポートする場合は、SYS_EXT_supportOutputFilesシステム・プロパティを設定する必要があります。

リクエストの出力ディレクトリを使用して出力ファイルを作成するには、ジョブでシステム・プロパティSYS_EXT_supportOutputFilesを使用してパラメータを定義する必要があります。ジョブで作成するファイルの種類に応じて、プロパティは次のいずれかの方法で設定できます。

  • コンテンツ・ストアにインポートするファイルをリクエストの出力ディレクトリに書き込むには、「output」に設定します。

  • 一時ファイルなど、インポートしないファイルをリクエスト作業ディレクトリに書き込むには、「work」に設定します。

  • ジョブで出力ファイルや一時ファイルが作成されない場合は、「none」に設定するか、未定義のままにします。

表22-5 リクエスト出力を作成するためのシステム・プロパティ

メソッド 説明

SYS_EXT_supportOutputFiles

ジョブによりファイル・システムにファイルが作成されるかどうかを示す文字列プロパティ。サポートされる値は、workoutputおよびnoneです。無効な値はnoneとして処理されます。

SYS_EXT_executeAutoExport

以前にインポートされた出力ファイルを実行ステージの始めにエクスポートするかどうかを示すブール型プロパティ。コンテンツが自動的にエクスポートされても、コンテンツ・ストアからコンテンツは削除されません。

22.2.3 Javaジョブからのリクエスト出力の作成

Javaからリクエスト出力を作成するには、ジョブのコードで、Oracle Enterprise Scheduler APIを使用してコンテンツ・ストアに出力コンテンツを直接作成するか、ジョブによりファイル・システム内のリクエストの出力ディレクトリにファイルを作成できます。ジョブによりリクエストの出力ディレクトリにファイルが作成される場合、これらのファイルをコンテンツ・ストアに明示的にインポートするか、Oracle Enterprise Schedulerによりファイルをコンテンツ・ストアに自動的にインポートできます。

ジョブでは、APIを使用してテキストまたはバイナリ出力コンテンツを作成できます。インポートされる出力ファイルは常にバイナリ・コンテンツとしてインポートされます。つまり、バイトは解釈されません。

22.2.3.1 Javaジョブからのリクエスト出力を処理するためのAPI

リクエスト出力の処理に使用できるJava APIは次のとおりです。

  • ContentFactoryクラスを使用して、RequestOutputおよびOutputContentHelper出力など、出力コンテンツを作成して管理するために使用できるその他のクラスのインスタンスを取得します。表22-6を参照してください。

  • RequestOutputクラスを使用して、コンテンツ・ストアに出力コンテンツを直接作成します。表22-7を参照してください。

  • OutputContentHelperクラスを使用して、リクエスト出力ファイル・ディレクトリにファイルとして作成したコンテンツを明示的に管理し、コンテンツ・ストアと相互作用します。表22-8を参照してください。

oracle.as.scheduler.request.ContentFactoryクラスには、コードが出力コンテンツ・フレームワークにアクセスしたり、出力自体を作成するために使用可能なインスタンスにアクセスできるメソッドが備えられています。

表22-6 Javaリクエスト出力用のContentFactoryメソッド

メソッド 説明

getRequestOutput( RuntimeServiceHandle rsh, long requestId, ContentType contentType, String contentName )

指定されたリクエストに対して出力とともにRequestOutputインスタンスを返し、そのリクエストの出力コンテンツを作成します。各書込みでは、指定されたリクエスト・サービス・ハンドルが使用されます。トランザクションのコミットまたはロールバックは、コール側のコードで行う必要があります。

getOutputContentHelper( long requestId )

StandardまたはExtendedリクエスト・モードで、リクエストに対して出力コンテンツを作成するためのOutputContentHelperインスタンスを返します。各操作が個別のトランザクションで実行されます。

getOutputContentHelper( long requestId, RuntimeServiceHandle rsh )

StandardまたはExtendedリクエスト・モードで、リクエストに対して出力コンテンツを作成するためのOutputContentHelperインスタンスを返します。各操作では指定されたハンドルが使用され、トランザクションのコミットまたはロールバックはコール元が行います。

oracle.as.scheduler.request.RequestOutputクラスは、コードによって作成される出力を表します。ContentFactory.getRequestOutputからこのクラスのインスタンスを取得してから、そのwriteメソッドを使用して作成中の出力コンテンツに書き込みます。

表22-7 Javaリクエスト出力用のRequestOutputメソッド

メソッド 説明

writeln( String str )

テキスト出力コンテンツに、strとそれに続く改行文字を付加します。

write( String str )

テキスト出力コンテンツにstrを付加します。

write( String str, int offset, int length )

テキスト出力コンテンツにstrを付加します。

write( char[] chars )

テキスト出力コンテンツにcharsを付加します。

write( char[] chars, int offset, int length )

テキスト出力コンテンツにcharsを付加します。

write( byte[] bytes )

バイナリ出力コンテンツにbytesを付加します。

write( byte[] bytes, int offset, int length )

バイナリ出力コンテンツにbytesを付加します。

oracle.as.scheduler.request.OutputContentHelperクラスのメソッドは、Javaジョブにおいて多くの出力ファイル処理を行います。コードでは、これらのメソッドを使用してリクエスト・ファイル・ディレクトリおよびコンテンツ・ストアそのものを操作できます。

コンテンツ・ストアにコンテンツをインポートするためのメソッドでは、インポート中にトランザクション・セマンティクスを指定するために使用できるOutputContentHelper.CommitSemantics列挙インスタンスを取得することに注意してください。詳細は、表22-9を参照してください。

表22-8 Javaリクエスト出力用のOutputContentHelperメソッド

メソッド 説明

workDirectoryExists( )

リクエストの作業ディレクトリが存在する場合にtrueを返します。任意のステージにあるジョブで、一時ファイルの作成を試行する前に、作業ディレクトリが存在するかどうかを判別できるようにします。

Oracle Enterprise Schedulerによって作業ディレクトリが作成されるようにするには、ジョブでSYS_EXT_supportOutputFilesシステム・プロパティにworkまたはoutputの値を定義する必要があります。

outputDirectoryExists( );

リクエストの出力ディレクトリが存在する場合にtrueを返します。更新などの任意のステージにあるジョブで、出力ファイルの作成を試行する前に、出力ディレクトリが存在するかどうかを判別できるようにします。

Oracle Enterprise Schedulerによって出力ディレクトリが作成されるようにするには、ジョブでSYS_EXT_supportOutputFilesシステム・プロパティにoutputの値を定義する必要があります。

isRequestWorkDirectoryShared( );

リクエスト・ファイル・ディレクトリが共有されている場合にtrueを返します。その場合、リクエストの作業ディレクトリまたは出力ディレクトリに、いずれかのステージにおいて作成されたすべてのファイルが、リクエストのそれ以降のすべてのステージで使用できるようになります。

getResolvedWorkDirectory( );

現在のサーバーに解決されるリクエスト作業ディレクトリを含む文字列を返します。ジョブでは作業ディレクトリに一時ファイルを作成でき、作業ディレクトリは、リクエストの実行終了時(RequestFileDirectoryが共有されている場合)または各ステージ(前処理、実行、更新、後処理)の終わり(RequestFileDirectoryがローカルである場合)に、Oracle Enterprise Schedulerによって自動的に削除されます。

getResolvedOutputDirectory( );

現在のサーバーに解決されるリクエストの出力ディレクトリを含む文字列を返します。ジョブでは、Oracle Enterprise Schedulerコンテンツ・ストアに自動的または手動でインポートできる出力ファイルを出力ディレクトリに作成できます。

importOutputFiles( List<String> fileNames, CommitSemantics semantics );

解決された出力ディレクトリから、指定されたファイルをインポートして、ImportExportResultインスタンスを返します。既存のコンテンツがAPIを使用して作成されている場合を除き、インポートされたコンテンツによって、同じ名前を持つ既存のコンテンツが上書きされます。その場合、ファイルはインポートされません。

importOutputFiles( CommitSemantics semantics );

解決された出力ディレクトリから、すべてのファイルをインポートして、ImportExportResultインスタンスを返します。既存のコンテンツがAPIを使用して作成されている場合を除き、インポートされたコンテンツによって、同じ名前を持つ既存のコンテンツが上書きされます。その場合、ファイルはインポートされません。

exportOutputContent( List<String> contentNames );

リクエストの出力ディレクトリ内のファイルに、指定された以前にインポート済の出力コンテンツをエクスポートして、ImportExportResultを返します。エクスポートされたファイルによって、同じ名前を持つすべての既存のファイルが上書きされます。APIを使用して作成された出力コンテンツはエクスポートできないことに注意してください。

exportOutputContent( );

以前にインポートされたすべての出力コンテンツをリクエストの出力ディレクトリ内のファイルにエクスポートして、ImportExportResultインスタンスを返します。エクスポートされたファイルによって、同じ名前を持つすべての既存のファイルが上書きされます。APIを使用して作成された出力コンテンツはエクスポートできないことに注意してください。

queryOutputContent( )

コンテンツ・ストア内にある既存の出力コンテンツすべての詳細情報とともにContentDetailインスタンスのリストを返します。ここでは、インポートされた出力コンテンツとAPIを使用して作成された出力コンテンツ両方の情報が返されます。

queryOutputContent( String contentName )

コンテンツ・ストア内に出力コンテンツがある場合は、その詳細情報とともにContentDetailインスタンスを返し、ない場合はNULLを返します。ここでは、インポートされた出力コンテンツとAPIを使用して作成された出力コンテンツ両方の情報が返されます。

outputContentExists( String contentName )

リクエストに対して、コンテンツ・ストア内に指定された出力コンテンツが存在する場合にtrueを返します。ここでは、インポートされた出力コンテンツとAPIを使用して作成された出力コンテンツの情報が返されます。

deleteOutputContent( List<String> contentNames )

リクエストに対して、コンテンツ・ストアから、指定された出力コンテンツを削除します。インポートされた出力コンテンツとAPIを使用して作成された出力コンテンツを削除できます。

コンテンツ・ストアにコンテンツをインポートしているときにエラーが発生した場合の動作を指定するには、oracle.as.scheduler.request.OutputContentHelper.CommitSemantics列挙を使用します。

表22-9 コミット・セマンティクスを表すCommitSemantics列挙メンバー

フィールド 説明

StopOnFirstError

1つのファイルにエラーがある場合に、すべてのファイルに対する操作を停止します。ハンドルが内部である場合、これはコミットされます。

IgnoreErrors

エラーに関係なく、すべてのファイルに対する操作を行います。ハンドルが内部である場合、これはコミットされます。

Transactional

いずれかのファイルにエラーがある場合に、すべてのファイルに対する操作を停止します。ユーザー指定のハンドルでは、これは無効です。

22.2.3.2 Javaリクエスト出力の例

例22-5は、RequestOutput APIを使用した出力コンテンツの作成方法を示しています。出力コンテンツは、コンテンツ・ストア内に直接作成されます。

例22-6は、リクエストの出力ディレクトリに出力ファイルを作成する方法を示しています。ジョブでSYS_EXT_supportOutputFilesシステム・プロパティをoutputとして定義する必要があることに注意してください。この例は、Javaジョブ、非同期Javaジョブ、プリプロセッサまたはポストプロセッサに適用されます。

次の例では、出力ファイルを手動でエクスポートおよびインポートする方法を示します。これは、更新中にファイルからコンテンツを作成する必要がある場合に役立ちます。インポートされたファイルのみをエクスポートでき、APIを使用して作成されたファイルはエクスポートできないことに注意してください。

例では、以前に作成された可能性のあるファイルを更新してインポートする必要があるというシナリオを示します。

import oracle.as.scheduler.request.ContentFactory;
import oracle.as.scheduler.request.ImportExportResult;
import oracle.as.scheduler.request.ImportExportResult.ImportExportStatus;
import oracle.as.scheduler.request.OutputContentHelper;
import oracle.as.scheduler.request.OutputContentHelper.CommitSemantics;

class ExampleExportImport{
 
    OutputContentHelper helper = ContentFactory.getOutputContentHelper(requestId);
 
    if (!helper.outputDirectoryExists())
    {
        // error - make sure job definition defines SYS_EXT_supportOutputFiles
    }
 
    String outputDir = helper.getResolvedOutputDirectory();
    String fileName = "myfile.out";
    List<String> fileNamesList = new ArrayList<String>();
    fileNamesList.add(fileName);
 
    // Export the file if it exists; otherwise, create it.
 
    if (helper.outputContentExists(fileName))
    {
        ImportExportResult exportResult =                  helper.exportOutputContent(fileNamesList);
        if (exportResult.getStatus() != ImportExportStatus.Success)
        {
          // handle error
        }
    }
    else
    {
        File f = new File(outputDir, fileName);
        f.createNewFile();
    }
 
    // ... update the file as needed ...
 
    // Import the new or updated file.
    // Updated file overwrites previous contents.
 
    ImportExportResult importResult =
        helper.importOutputFile(fileNamesList, CommitSemantics.IgnoreErrors);
 
    if (importResult.getStatus() != ImportExportStatus.Success)
    {
        // handle error
    }
}

例22-5 RequestOutputを使用した出力コンテンツの作成

import oracle.as.scheduler.request.ContentFactory;
import oracle.as.scheduler.request.ContentType;
import oracle.as.scheduler.request.RequestOutput;
 
class ExampleOutputContentCreator
{
    RuntimeService runtimeService = getRuntimeService();
    RuntimeServiceHandle handle;
    try {
      handle = runtimeService.open();
      RequestOutput requestOutput = ContentFactory.getRequestOutput(
            handle, requestId, ContentType.Text, “SampleOutput.txt");
 
      requestOutput.writeln(“Output data in sample output content.");
    }
    finally {
      runtimeService.close(handle);
    }
}

例22-6 自動インポート用の出力ファイルの作成

import oracle.as.scheduler.request.ContentFactory;
import oracle.as.scheduler.request.OutputContentHelper;

class ExampleOutputCreator{ 
 
    OutputContentHelper helper = ContentFactory.getOutputContentHelper(requestId);
    String outputDir = helper.getResolvedOutputDirectory();
 
    File f = new File(outputDir, "myfile");
    f.createNewFile();
    if (f.exists())
    {
        // write to file
    }
}

22.2.4 PL/SQLジョブからのリクエスト出力の作成

PL/SQLからリクエスト出力を作成する場合は、コンテンツ・ストアに直接出力コンテンツを作成するために、コードでESS_JOB PL/SQLパッケージを使用できます。

ジョブでは、パッケージ内のファンクションおよびプロシージャを使用して、テキストまたはバイナリ出力コンテンツを作成できます。

22.2.4.1 出力を作成するためのPL/SQLパッケージ・サポート

表22-10 リクエスト出力用のESS_JOBプロシージャおよびファンクション

メソッド 説明

open_text_output_content( p_content_name in varchar2 ) return varchar2

open_binary_output_content( p_content_name in varchar2 ) return varchar2

現在のセッションに関連付けられているリクエストに対して、指定された出力コンテンツを開いてハンドルを返します。

適切なコンテンツ・タイプ定数によりopen_output_contentをコールする便利なファンクションです。詳細は、open_output_contentを参照してください。

open_output_content( p_content_name in varchar2, p_content_type in integer ) return varchar2;

現在のセッションに関連付けられているリクエストに対して、出力コンテンツp_content_nameを開いて不透明なハンドルを返します。

指定された名前の出力コンテンツ・エントリが存在しない場合、そのエントリが新規に作成されます。すでに存在する場合は、その名前に対して確立されているコンテンツ・タイプと指定されたコンテンツ・タイプが一致する必要があります。

p_content_typeは、次のいずれかのコンテンツ・タイプ定数を持つコンテンツ・タイプを表します。

CONTENT_TYPE_TEXT (値: 1)(テキスト・コンテンツの場合)

CONTENT_TYPE_BINARY (値: 2)(バイナリ・コンテンツの場合)

これにより、出力コンテンツを操作する後続プロシージャに渡される不透明なハンドルが返されます。

このファンクションから正しい結果が返されると、コンテンツ・エントリはロックされます。このプロシージャが失敗した場合は、ロックされる場合とされない場合とがあります。コミットまたはロールバックによりロックが解放されます。テキスト・コンテンツのデータを書き込むにはwrite_text_contentまたはwrite_ntext_contentプロシージャを、バイナリ・コンテンツのデータを書き込むにはwrite_binary_contentプロシージャを使用する必要があります。

このメソッドによって返されるハンドルに関連付けられているリソースを解放するには、close_contentをコールする必要があります。クローズはトランザクションのコミットまたはロールバックの前に行う必要があります。

ノート: コンテンツ出力サポートにはDMLセマンティクスが含まれます。コミットおよびロールバックは、コール元が行います。

write_ntext_content( p_content_handle in varchar2, p_data in nvarchar2 )

write_text_content( p_content_handle in varchar2, p_data in varchar2 );

指定されたハンドルに関連付けられている出力コンテンツにデータをp_dataとして書き込みます。これらの操作は、CONTENT_TYPE_TEXTコンテンツ・タイプでのみサポートされます。

p_content_handleは、以前のopen_output_contentコールからの出力ハンドルです。

ノート: コンテンツ出力サポートにはDMLセマンティクスが含まれます。コミットおよびロールバックは、コール元が行います。

write_binary_content( p_content_handle in varchar2, p_data in raw );

指定されたハンドルに関連付けられている出力コンテンツにバイナリ・データをp_dataとして書き込みます。この操作は、CONTENT_TYPE_BINARYコンテンツ・タイプでのみサポートされます。

p_content_handleは、以前のopen_output_contentコールからの出力ハンドルです。

ノート: コンテンツ出力サポートにはDMLセマンティクスが含まれます。コミットおよびロールバックは、コール元が行います。

close_content( p_content_handle in varchar2 );

出力コンテンツ・ハンドルをクローズします。これにより、指定されたハンドルに関連付けられているリソースが解放され、ハンドルが無効になります。このメソッドは、トランザクションのコミットまたはロールバックより前にコールしてください。

p_content_handleは、以前のopen_output_contentコールからの出力ハンドルです。

ノート: コンテンツ出力サポートにはDMLセマンティクスが含まれます。コミットおよびロールバックは、コール元が行います。このメソッドでは、コミットまたはロールバックは自動的には実行されません。

output_content_exists( p_content_name in varchar2 ) return boolean;

現在のセッションに関連付けられているリクエストに対して、指定された名前を持つ出力コンテンツ・エントリがすでに存在する場合はtrueを返します。

p_content_nameは、出力コンテンツ・エンティティの名前です。

delete_output_content( p_content_name in varchar2 );

現在のセッションに関連付けられているリクエストに対して、指定された出力コンテンツを削除します。

p_content_nameは、出力コンテンツ・エンティティの名前です。

22.2.4.2 PL/SQL出力作成の例

例22-7では、テキスト・コンテンツを出力に書き込む方法およびログ・エントリを書き込む方法を示します。

例22-8では、出力にバイナリ・コンテンツを書き込む方法を示します。

例22-7 PL/SQL出力作成の例

create or replace procedure text_output_example_job
( request_handle in varchar2 )
as
  v_request_id  number := null;
  v_content_name  varchar2(100) := 'mycontent.txt';
  v_content_handle  varchar2(100);
  v_ntext nvarchar2(100);
begin
  ess_job.write_log(ess_job.LEVEL_FINE,
                    'TEXT_OUTPUT_EXAMPLE_JOB Procedure Begin');
 
  -- Oracle Enterprise Scheduler request id being executed.
  begin
    v_request_id := ess_runtime.get_request_id(request_handle);
  exception
    when others then
      ess_job.write_log(ess_job.LEVEL_SEVERE,
                        'Bad request handle: '||request_handle);
      raise_application_error(-20000,
         'Failed to get request id for request handle '||request_handle,
         true);
  end;
 
  begin
    -- ----------
    -- Delete content entry if it already exists.
    -- ----------
    if (not ess_job.output_content_exists(v_content_name)) then
      ess_job.write_log(ess_job.LEVEL_FINEST,
                        'Content does not exist: ' || v_content_name);
    else
      ess_job.write_log(ess_job.LEVEL_INFO,
                        'Deleting existing content: ' || v_content_name);
      ess_job.delete_output_content(v_content_name);
      commit;
    end if;
 
    -- ----------
    -- Write text content. Source data has some non-ascii chars.
    -- Illustrate multiple writes.
    -- ----------
    ess_job.write_log(ess_job.LEVEL_FINE,
                      'Write text content: '||v_content_name);
 
    v_content_handle := null;
    v_content_handle := ess_job.open_text_output_content(v_content_name);
 
    ess_job.write_text_content(v_content_handle,
                               'Data ');
    ess_job.write_ntext_content(v_content_handle,
                                unistr('(NTEXT data:\00c4\00c5)'));
    ess_job.write_text_content(v_content_handle,
                               ' for CONTENT ' || v_content_name);
 
    ess_job.close_content(v_content_handle);
    v_content_handle := null;
    commit;
  exception
    when others then
      ess_job.write_log(ess_job.LEVEL_WARNING,
                        'Error during text output operations. ' ||
                        'content: ' || v_content_name || chr(10) ||
                        'Error_Stack...' || chr(10) ||
                        dbms_utility.format_error_stack() || chr(10) ||
                        'Error_Backtace...' || chr(10) ||
                        dbms_utility.format_error_backtrace());
      if v_content_handle is not null then
        ess_job.close_content(v_content_handle);
        v_content_handle := null;
      end if;
      rollback;
      raise_application_error(-20000,
            'Output content operations failed for '||v_content_name);
  end;
 
  ess_job.write_log(ess_job.level_info,
                    'TEXT_OUTPUT_EXAMPLE_JOB Procedure End');
end;
/

例22-8 リクエスト出力の手動エクスポートおよびインポート

create or replace procedure binary_output_example_job
( request_handle in varchar2 )
as
  v_request_id  number := null;
  v_content_name  varchar2(100) := 'mycontent.bin';
  v_content_handle  varchar2(100);
  v_nchar_cs varchar2(100);
  v_dest_cs varchar2(100);
  v_ntext nvarchar2(100);
  v_raw raw(500);
begin
  ess_job.write_log(ess_job.LEVEL_FINE,
                    'BINARY_OUTPUT_EXAMPLE_JOB Procedure Begin');
 
  -- Oracle Enterprise Scheduler request id being executed.
  begin
   v_request_id := ess_runtime.get_request_id(request_handle);
  exception
    when others then
      ess_job.write_log(ess_job.LEVEL_SEVERE,
                        'Bad request handle: '||request_handle);
      raise_application_error(-20000,
         'Failed to get request id for request handle '||request_handle,
         true);
  end;
 
  begin
    -- ----------
    -- Delete content entry if it already exists.
    -- ----------
    if (not ess_job.output_content_exists(v_content_name)) then
      ess_job.write_log(ess_job.LEVEL_FINEST,
                        'Content does not exist: ' || v_content_name);
    else
      ess_job.write_log(ess_job.LEVEL_INFO,
                        'Deleting existing content: ' || v_content_name);
      ess_job.delete_output_content(v_content_name);
      commit;
    end if;
 
    -- ----------
    -- Write binary content.
    -- This is the UTF-8 representation of a string for a known byte
    -- encoding rather than whatever the charset/national charset
    -- happens to be for this database.
    -- Source data has couple non-ascii chars.
    -- ----------
 
    -- database national character set being used
    select value into v_nchar_cs
      from nls_database_parameters
      where parameter = 'NLS_NCHAR_CHARACTERSET';
    ess_job.write_log(ess_job.LEVEL_FINEST,
                      'NLS_NCHAR_CHARACTERSET = '||v_nchar_cs);
 
    ess_job.write_log(ess_job.LEVEL_FINE,
                      'Write binary content: '||v_content_name);
 
    v_content_handle := null;
    v_content_handle := ess_job.open_binary_output_content(v_content_name);
 
    v_ntext := unistr('Data (NTEXT data:\00c4\00c5) for CONTENT ' ||
                      v_content_name);
 
    v_dest_cs := 'AL32UTF8';
    v_raw := utl_raw.cast_to_raw(convert(v_ntext, v_dest_cs, v_nchar_cs));
    ess_job.write_binary_content(v_content_handle, v_raw);
    ess_job.write_log(ess_job.LEVEL_FINE,
                      'Wrote '||utl_raw.length(v_raw)||' bytes' ||
                      ' using ' || v_dest_cs || ' charset');
 
    ess_job.close_content(v_content_handle);
    v_content_handle := null;
    commit;
  exception
    when others then
      ess_job.write_log(ess_job.LEVEL_WARNING,
                        'Error during binary output operations. ' ||
                        'content_name=' || v_content_name || chr(10) ||
                        'Error_Stack...' || chr(10) ||
                        dbms_utility.format_error_stack());
      if v_content_handle is not null then
        ess_job.close_content(v_content_handle);
        v_content_handle := null;
      end if;
      rollback;
      raise_application_error(-20000,
            'Output content operations failed for '||v_content_name);
  end;
 
  ess_job.write_log(ess_job.level_info,
                    'BINARY_OUTPUT_EXAMPLE_JOB Procedure End');
end;
/

22.2.5 プロセス・ジョブからのリクエスト出力の作成

すべてのプロセス・ジョブで使用できるESS_OUTPUT_WORK_DIR環境変数により指定された場所にコンテンツを書き込むことによって、プロセス・ジョブ・ロジックから出力を作成します。他のジョブと同様に、SYS_EXT_supportOutputFilesシステム・プロパティがoutputに設定されており、ジョブに対して環境変数が定義されるようになっていることを確認してください。

プロセス・コードによりファイルが書き込まれると、Oracle Enterprise Schedulerにより自動的に、ディレクトリ内の出力ファイルがバイナリ・コンテンツとしてコンテンツ・ストアにインポートされます。

22.2.6 EJBジョブからのリクエスト出力の作成

EJBジョブから出力を作成する方法の詳細と例については、「EJBジョブからのリクエスト・ロギングおよび出力」を参照してください。

22.2.7 Webサービス・ジョブからのリクエスト出力の作成

同期および非同期のWebサービスの場合、リクエスト出力コンテンツは、次に説明するようにレスポンス・メッセージ・ペイロードから自動的に作成されます。出力コンテンツは、WebServiceJobOutput-REQUESTID.txt (REQUESTIDはリクエストのリクエストID)という名前のテキスト・データです。

同期Webサービスの場合、レスポンス・メッセージ・ペイロードはリクエスト出力として取得されます。

非同期Webサービスの場合、EssWsJobAsyncCallbackServiceで受信されるコールバック/レスポンス・メッセージ・ペイロードは、ジョブ・ステータスがSUCCESSになると取得されます。

22.2.8 リクエスト出力を処理するためのAPI

oracle.as.scheduler.RuntimeServiceクラスのメソッドを使用して、Oracle Enterprise Schedulerコンテンツ・ストアに格納されているリクエスト出力を処理できます。最初に、RuntimeServiceHandleインスタンスを取得する必要があります。このインスタンスを、これらのRuntimeServiceメソッドそれぞれの引数として渡します。RuntimeServiceHandleの詳細は、「ランタイム・サービスへのアクセスおよびランタイム・サービス・ハンドルの取得方法」を参照してください。

表22-11 リクエスト出力を処理するためのRuntimeServiceメソッド

メソッド 説明

getOutputContentDetail( RuntimeServiceHandle handle, long requestId, String contentName )

指定されたリクエストに対する指定された出力コンテンツのContentDetailインスタンスを返すか、コンテンツが存在しない場合はNULLを返します。

getOutputContentDetail( RuntimeServiceHandle handle, long requestId )

リクエストに対するすべての出力コンテンツのContentDetailリスト・インスタンスを返します。出力コンテンツがない場合、リストは空です。

openOutputContent( RuntimeServiceHandle handle, long requestId, String contentName )

指定されたリクエスト出力を開いて指定されたコンテンツの出力データを取得し、ContentHandleインスタンスを返します。ハンドルを使用して出力データを取得できます。ハンドルを解放するには、コンテンツを閉じる必要があります。

getTextContent( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxChars )

ログまたは出力テキスト・コンテンツから、最大maxChars文字のchar配列を返します。

getBinaryContent( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxBytes )

バイナリ・コンテンツから最大でmaxBytesバイトのバイト配列を返します。

closeContent( RuntimeServiceHandle handle, ContentHandle contentHandle )

以前開いたログまたは出力コンテンツを閉じ、ハンドルを解放します。