17 Creating Job Request Logs and Output

This chapter describes how to use Oracle Enterprise Scheduler to generate job request logs and output that should be saved for later use by administrators and users.

Logs generated by job requests help administrators diagnose problems and see job-specific status. Logs are accessible through the Fusion Middleware Control. In addition, some jobs generate output as part of their work, such as a report about job-specific data that a user can review after the job has completed. Your code can create and store request log information as well as request output.

This chapter includes the following sections:

17.1 Creating Request Logs

You can create job request logs from your job code. Oracle Enterprise Scheduler provides APIs for creating and writing logs and interacting with the content store.

Oracle Enterprise Scheduler supports a single log per request. The log will have a name of the form REQUESTID.log. The logging APIs log directly to the content store, and log content may not be rolled back.

For more about viewing job request logs with Fusion Middleware Control, see Viewing Job Request Logs in Oracle Fusion Middleware Administrator's Guide for Oracle Enterprise Scheduler.

17.1.1 System Properties

When logging for Java and PL/SQL jobs, what actually shows up in the log will be constrained by how the SYS_EXT_requestLogLevel system property has been set. The property determines the logging level supported by the Java and PL/SQL request logging APIs.

The property's value defaults to INFO. The complete set of valid values are SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST. Use Java and PL/SQL APIs to discover the request log level.

Note that because process jobs do not use the logging API, logging levels aren't supported in them.

17.1.2 APIs for Handling Request Logs

You can use methods of the oracle.as.scheduler.RuntimeService class to handle logs stored in the Oracle Enterprise Scheduler content store. You'll need to first get a RuntimeServiceHandle instance. You'll pass this instance as an argument for each of these RuntimeService methods.

For more on the RuntimeServiceHandle, see Section 14.2.1, "How to Access the Runtime Service and Obtain a Runtime Service Handle".

Table 17-1 RuntimeService Methods for Handling Request Logs

Method Description

getLogContentDetail(RuntimeServiceHandle handle, long requestId )

Returns a ContentDetail instance with the log content detail for the request, or null if the log does not exist.

openLogContent( RuntimeServiceHandle handle, long requestId )

Returns a ContentHandle instance from opening the request log to retrieve log data for the specified request. You can use the handle to retrieve output data. The content must be closed to release the handle.

getLogLines( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxLines )

Returns a String array with at most maxLines lines from the request log, continuing from the last call to this method. The content handle is from the previous call to openLogContent. This returns a String array of lines from the log without line terminators; if no more lines, array will be empty.

getTextContent( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxChars )

Returns a char array with at most maxChars characters from the log or output text content.

closeContent( RuntimeServiceHandle handle, ContentHandle contentHandle )

Closes the previously opened log or output content and releases the handle.


17.1.3 Log Header

Your logging code will write entries to a log that begins with the following heading information. This header is prefixed to each record written to the log.

Example 17-1

####[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.

17.1.4 Creating Request Logs from a Java Job

You can use the Java request logger to log during the execute and update stages of a Java or asynchronous Java job, as well as during pre-processing and post-processing for all job execution types.

The job logic must use the ContentFactory API to get the request logger. Oracle Enterprise Scheduler will use the current value of the SYS_EXT_requestLogLevel system property to constrain logging level each time the logger is retrieved.

17.1.4.1 APIs for Java Job Logging

In your Java job's logic, you can use the oracle.as.scheduler.request.ContentFactory class getRequestLogger method (see Table 17-2) to get a RequestLogger instance for adding log entries. Note that the request logger will not support a resource bundle.

The Java APIs available for handling logs include the following:

  • Use the ContentFactory class to get instances of a RequestLogger you can use to create the log and add entries. See Table 17-2.

  • Use the RequestLogger class to write the log. See Table 17-3.

The oracle.as.scheduler.request.ContentFactory class provides methods to get your code access to the output content framework, as well as to an instance you can use to create the output itself.

Table 17-2 ContentFactory Methods for Creating Request Logs

Method Description

getRequestLogger( long requestId )

Returns a RequestLogger instance for the specified requestId and creates log content named requestId.log in Oracle Enterprise Scheduler content store.


Once you have a logger instance, you can use the methods in Table 17-3 to add entries.

Table 17-3 RequestLogger Methods for Creating Request Logs

Method Description

log( Level level, String msg )

fine( String msg )

finer( String msg )

finest( String msg )

These methods log messages at the specified levels.

The message is logged only if the specified logging level is equal or greater than the log level specified by the SYS_EXT_requestLogLevel system property. If the property isn't set, the default log level is INFO.

When using the log method, the java.util.logging.Level supports the following values, in descending order.

  • SEVERE

  • WARNING

  • INFO

  • CONFIG

  • FINE

  • FINER

  • FINEST


17.1.4.2 Example

Example 17-2 shows a very simple Java job example that does logging.

Example 17-2 Java Request Logging Example

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);
    }
  }
}

17.1.5 Creating Request Logs from a PL/SQL Job

To create logs from PL/SQL, your code can use the ESS_JOB PL/SQL package to write log entries.

17.1.5.1 ESS_JOB Package Support for Creating Logs

Oracle Enterprise Scheduler provides the ESS_JOB package with functions and procedures for logging from PL/SQL code.

Table 17-4 ESS_JOB Functions and Procedures for Request Logging

Method Description

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

Writes p_text as a message to request log content for the Oracle Enterprise Scheduler request associated with the current session.

The message is logged only if the specified logging level is equal or greater than the log level specified by the SYS_EXT_requestLogLevel system property. If the property isn't set, the default log level is LEVEL_INFO.

Log level values correspond to those defined in java.util.logging.Level.

Use the following values for the p_level parameter (shown in descending order):

  • LEVEL_SEVERE

  • LEVEL_WARNING

  • LEVEL_INFO

  • LEVEL_CONFIG

  • LEVEL_FINE

  • LEVEL_FINER

  • LEVEL_FINEST


17.1.5.2 PL/SQL Request Logging Example

An example of request logging by a SQL request job procedure is shown below.

Example 17-3 PLSQL Request Logging

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;
/

17.1.6 Creating Request Logs from a Process Job

You can write to the job request log from process job. The way this works is quite different from Java and PL/SQL jobs, where the executing code has access to an API for writing entries at a particular level. Instead, for a process job, the job's standard output and standard error are redirected to a file in the request's log work directory (a location set by Oracle Enterprise Scheduler). Oracle Enterprise Scheduler will import this file and append it to the request log in the content store.

In other words, to log from a process job, you need only write to standard output from job logic code.

The encoding used to read the log file is determined as follows. If the application ess-config.xml defines LANG in the Env properties, Oracle Enterprise Scheduler will use the encoding from that. Otherwise, Oracle Enterprise Scheduler will use the default encoding of the container.

Note that you can't log at particular levels from a process job (where the API for setting the level isn't available). So the SYS_EXT_requestLogLevel system property will not constrain log contents. Oracle Enterprise Scheduler will always append the contents of the log file to the request log in the content store.

17.2 Creating Request Output

You can have your job write files as output at runtime. For example, your job might collect data that would be useful in a report for users. When you generate output at runtime, it's available to be retrieved later through a client user interface or the Fusion Middleware Control.

The output your code creates can be imported into the Oracle Enterprise Scheduler content store, from which it can be retrieved later. You can do this either by writing to the file system in the usual way, or by using Oracle Enterprise Scheduler APIs to import directly to the store.

When you use the file system, you write to a particular directory whose location has been configured in the Oracle Enterprise Scheduler ess-config.xml file. Oracle Enterprise Scheduler creates a request file directory to contain files written from all requests. Your code writes to a subdirectory of this created specifically for the request. Oracle Enterprise Scheduler automatically imports all of the request's output to the content store, then deletes request-specific subdirectories.

Oracle Enterprise Scheduler provides APIs for accessing the content store and writing output from both Java and PL/SQL code.

17.2.1 Using the Request File Directory

The request file directory is specified in the Oracle Enterprise Scheduler ess-config.xml file. For each request, Oracle Enterprise Scheduler can create request-specific subdirectories of this request file directory: a working directory for temporary files and an output directory for output files that should be saved in the content store.

Your code can write temporary and output files to their respective request-specific directories at runtime. Oracle Enterprise Scheduler will import to the content store files in the request's output directory. When the content is imported depends on whether the request file directory is shared or local, as described in Section 17.2.1.1, Section 17.2.1.2, and Section 17.2.1.3.

After automatically importing all of the request's output to the content store, Oracle Enterprise Scheduler deletes the request-specific output directory and its contents.

The request file directory can be local, meaning that it is used only for work done on a single server. It can also instead be shared, in which a single directory is used for work done on multiple servers. Runtime behavior differs depending on whether the directory is configured to be local or shared.

The directory is specified in the ess-config.xml file, as shown in Example 17-4.

Example 17-4 Request File Directory Configuration with ess-config.xml file

<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>

17.2.1.1 Common Request File Directory Behavior

Oracle Enterprise Scheduler will automatically import all request output files from the output directory to the content store, and will delete the request working directory and all files in it.

Imported files always overwrite existing content of the same file name as long as the existing content was previously imported. If the existing content was created using the API, then it is considered to be distinct from the new file, and the new file will not overwrite and will be ignored. In other words, content created with the API has precedence.

Oracle Enterprise Scheduler will not import output files of zero length.

17.2.1.2 Shared Request File Directory Behavior

Any files created by the request will remain in its working and output directories until the request completes and goes to a terminal state. Any files created by a request in a shared file directory will be available to all stages of the request.

17.2.1.2.1 Error Handling When a Shared Request File Directory is Used

Oracle Enterprise Scheduler creates the request work directory before the job request transitions to RUNNING state. Any error while creating the directory results in a system error for the request.

For process a job, importing the log occurs after the request transitions to a terminal state. If an error occurs while importing the log, the error is logged and the request log is left in the file system. You will need to manually import the log to the content store.

Importing output files for any job type occurs after the request transitions to a terminal state. If there is an error while importing output files, the error is logged and the output files are left in their directories on the file system. You will need to remove the output files.

17.2.1.3 Local Request File Directory Behavior

Oracle Enterprise Scheduler will create request-specific directories before any stage of the request runs. If the request file directory is local, it must be a location that is guaranteed to exist locally on every server. In this case, files created by one stage of the request are not guaranteed to be available in the next stage because stages are independent units of work and may run on different servers.

For a local request file directory, the common behavior holds except that Oracle Enterprise Scheduler performs the actions for each stage. The reason is that each stage may execute on a different server, and it is necessary for Oracle Enterprise Scheduler to capture and clean up the files for each stage because they may not be there for the next stage.

In case a request needs access to all previously imported output files, it can set the parameter SYS_EXT_executeAutoExport = true. If this is set, at the beginning of the execute stage, Oracle Enterprise Scheduler will automatically export previously imported output files to the request's working output directory. This gives you an opportunity to update the file before it is imported back to the content store at the end of the execute stage. (Note that the content isn't removed from the content store when the content is exported.) Furthermore, Oracle Enterprise Scheduler provides an API for a request to selectively export previously imported output files.

17.2.1.3.1 Error Handling When a Local Request File Directory is Used

When a local request file directory is used, file imports happen at the end of each stage (pre-processing, execution, update, post-processing). If an error occurs while importing logs or output files, the log and output files that failed to import will be moved to a mirror directory at <request_file_directory>/preserve. For example, for request 18 this would be <request_file_directory>/preserve/18.

For the pre-processing stage, an error creating the request directory at the beginning of the stage or importing output files at the end of the stage will result in a system error for the request.

For the post-processing stage, an error creating the request directory at the beginning of the stage or importing output files at the end of the stage will result in a warning for the request.

For the execution stage of a Java job, asynchronous Java job, and process job request, an error creating the request directory or automatically exporting previously imported output files (such as when the SYS_EXT_executeAutoExport system property is used) at the beginning of the stage or importing output files at the end of the stage will result in a system error for the request.

If the request is a process job, an error importing the request log will be logged and not treated as an error. The log will be left in the file system, and you may manually import it to the content store. If there is an internal error during execution of a process job, log and output files will not be imported because the job could still be running. The log and output files will be imported when the job is terminated, either automatically or manually by the user. If the job goes to ERROR_MANUAL_RECOVERY, it is the user's responsibility to clean up the request log and output files.

For the update stage, an error creating the request directory or importing output files is logged only.

17.2.2 System Properties

Setting the SYS_EXT_supportOutputFiles system property is essential to using the request file directory and automatic importing of output files.

To use the request output directory to create output files, the job must define a parameter using the system property SYS_EXT_supportOutputFiles. Depending on what sort of files the job wants to create, the property can be set in one of the following ways:

  • Set it to "output" in order to have files written to the request output directory imported to the content store.

  • Set it to "work" in order to write files to the request working directory that are not intended for import, such as temporary files.

  • Set it to "none", or leave it undefined, if the job doesn't create any output or temporary files.

Table 17-5 System Properties for Creating Request Output

Method Description

SYS_EXT_supportOutputFiles

String property indicating whether job will create files in the file system. Supported values are "work", "output", and "none". An invalid value is treated as "none".

SYS_EXT_executeAutoExport

Boolean property indicating whether previously imported output files shall be exported at the start of the execute stage. The content isn't removed from the content store when it is automatically exported.


17.2.3 APIs for Handling Request Output

You can use methods of the oracle.as.scheduler.RuntimeService class to handle request output stored in the Oracle Enterprise Scheduler content store. You'll need to first get a RuntimeServiceHandle instance. You'll pass this instance as an argument for each of these RuntimeService methods. For more on the RuntimeServiceHandle, see Section 14.2.1, "How to Access the Runtime Service and Obtain a Runtime Service Handle".

Table 17-6 RuntimeService Methods for Handling Request Output

Method Description

getOutputContentDetail( RuntimeServiceHandle handle, long requestId, String contentName )

Returns a ContentDetail instance for the specified output content for the specified request, or null if the content does not exist.

getOutputContentDetail( RuntimeServiceHandle handle, long requestId )

Returns a ContentDetail List instance for all output content for the request. The list will be empty if there is no output content.

openOutputContent( RuntimeServiceHandle handle, long requestId, String contentName )

Opens the specified request output to retrieve output data for the specified content, returning ContentHandle instance. You can use the handle to retrieve output data. The content must be closed to release the handle.

getTextContent( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxChars )

Returns a char array with at most maxChars characters from the log or output text content.

getBinaryContent( RuntimeServiceHandle handle, ContentHandle contentHandle, int maxBytes )

Returns a byte array with at most maxBytes bytes from the binary content.

closeContent( RuntimeServiceHandle handle, ContentHandle contentHandle )

Closes the previously opened log or output content and releases the handle.


17.2.4 Creating Request Output from a Java Job

To create request output from Java, your job's code can use the Oracle Enterprise Scheduler API to import directly to the content store, or it can create files in the request output directory that are automatically imported to the content store.

Using the API, the job can create text or binary output content. Imported output files are always imported as binary content, meaning the bytes are uninterpreted.

17.2.4.1 APIs for Handling Request Output from a Java Job

The Java APIs available for handling request output include the following:

  • Use the ContentFactory class to get instances of other classes you can use to create content and write output. See Table 17-7.

  • Use the RequestOutput class to write output. See Table 17-8.

  • Use the OutputContentHelper class to interact with the content store and with the request file directory. See Table 17-9.

The oracle.as.scheduler.request.ContentFactory class provides methods to get your code access to the output content framework, as well as to an instance you can use to create the output itself.

Table 17-7 ContentFactory Methods for Java Request Output

Method Description

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

Returns a RequestOutput instance with output for the specified request and creates the output content for the request. Each write will use the specified request service handle; your calling code is responsible for committing or rolling back the transaction.

getOutputContentHelper( long requestId )

Returns a OutputContentHelper instance for creating output content for requests with Standard or Extended request mode. Each operation will be performed in a separate transaction.

getOutputContentHelper( long requestId, RuntimeServiceHandle rsh )

Returns a OutputContentHelper instance for creating output content for requests with Standard or Extended request mode. Each operation will use the provided handle, and it is the caller's responsibility to commit or rollback the transaction.


The oracle.as.scheduler.request.RequestOutput class represents the output your code is creating. You get an instance of this class from ContentFactory.getRequestOutput, then use its write methods to add content to the output you're creating.

Table 17-8 RequestOutput Methods for Java Request Output

Method Description

writeln( String str )

Appends str to the text output content, followed by a line feed character.

write( String str )

Appends str to the text output content.

write( String str, int offset, int length )

Appends str to the text output content.

write( char[] chars )

Appends chars to the text output content.

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

Appends chars to the text output content.

write( byte[] bytes )

Appends bytes to the binary output content.

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

Appends bytes to the binary output content.


Methods of the oracle.as.scheduler.request.OutputContentHelper class do the heavy lifting for output handling in Java jobs. Using these methods, your code can work with the request file directory and the content store itself.

Note that methods for importing content to the content store take a OutputContentHelper.CommitSemantics enum instance that you can use to specify transaction semantics during import. For more information, see Table 17-10.

Table 17-9 OutputContentHelper Methods for Java Request Output

Method Description

workDirectoryExists( )

Returns true if the request's work directory exists. Allows the job at any stage to determine if the work directory exists before it attempts to create temporary files.

The job must define the SYS_EXT_supportOutputFiles system property with a value of "work" or "output" to cause Oracle Enterprise Scheduler to create the work directory.

outputDirectoryExists( );

Returns true if the request's output directory exists. Allows the job at any stage, such as update, to determine if the output directory exists before it attempts to create output files.

The job must define the SYS_EXT_supportOutputFiles system property with a value of "output" to cause Oracle Enterprise Scheduler to create the output directory.

isRequestWorkDirectoryShared( );

Returns true if the request file directory is shared. If it is, then any files created in the request work dir or output dir in any stage will be available to all subsequent stages of the request.

getResolvedWorkDirectory( );

Returns a String with the request work directory as resolved to the current server. The job may create temporary files in the work directory, and Oracle Enterprise Scheduler will automatically delete the work directory at the end of request execution if the RequestFileDirectory is shared, or at the end of each stage (pre-processing, execution, update, post-processing) if the RequestFileDirectory is local.

getResolvedOutputDirectory( );

Returns a String with the request output directory, resolved to the current server. The job may create output files in the output directory that can be autmoatically or manually imported to the Oracle Enterprise Scheduler content store.

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

Returns an ImportExportResult instance from importing the specified files from the resolved output directory. Imported content overwrites existing content of the same name, unless the existing content was created using the API. In that case, the file will not be imported.

importOutputFiles( CommitSemantics semantics );

Returns an ImportExportResult instance from importing all files from the resolved output directory. Imported content overwrites existing content of the same name, unless the existing content was created using the API. In that case, the file will not be imported.

exportOutputContent( List<String> contentNames );

Returns an ImportExportResult from exporting the specified previously imported output content to files in the request output directory. The exported files will overwrite any existing files of the same names. Note that output content created using the API can not be exported.

exportOutputContent( );

Returns an ImportExportResult instance from exporting all previously imported output content to files in the request output directory. The exported files will overwrite any existing files of the same names. Note that output content created using the API can not be exported.

queryOutputContent( )

Returns a List of ContentDetail instances with detailed information for all existing output content in the content store. This returns information on both output content that was imported and output content created using the API.

queryOutputContent( String contentName )

Returns a ContentDetail instance with detailed information for the output content in the content store, if it exists (null if it doesn't). This returns information on both output content that was imported and output content created using the API.

outputContentExists( String contentName )

Returns true if the specified output content exists in the content store for the request. This returns information on output content that was imported and output content created using the API.

deleteOutputContent( List<String> contentNames )

Deletes the specified output content from the content store for the request. Can delete output content that was imported and output content created using the API.


Use the oracle.as.scheduler.request.OutputContentHelper.CommitSemantics enum to specify what should happen if errors occur while importing content to the content store.

Table 17-10 CommitSemantics Enum Members to Express Commit Semantics

Field Description

StopOnFirstError

Stop the operation for all files when there is an error on a file. If the handle is internal, it will be committed.

IgnoreErrors

Attempt the operation on all files regardless of errors. If the handle is internal, it will be committed.

Transactional

Stop the operation for all files when any file has an error. This is not valid with a user-provided handle.


17.2.4.2 Example

The following example illustrates how to create an output file in the request output directory. Remember that the job must define the SYS_EXT_supportOutputFiles system property as "output". This example is appropriate for a Java job, an asynchronous Java job, a pre-processor, or a post-processor.

Example 17-5 Creating an Output File

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
    }
}

The following example shows how to manually export and import output files. This would be useful if you need to create content from files during update. Be aware that you can export only files that have been imported and not files that were created using the API.

The example illustrates the scenario that a file that may have been created previously needs to be updated and imported.

Example 17-6 Manual Export and Import of Request Output

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 = 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
    }
}

17.2.5 Creating Request Output from a PL/SQL Job

To create request output from PL/SQL, your code can use the ESS_JOB PL/SQL package to create output content directly in the content store.

Using functions and procedures in the package, the job can create text or binary output content.

17.2.5.1 PL/SQL Package Support for Creating Output

Table 17-11 ESS_JOB Procedures and Functions for Request Output

Method Description

open_text_output_content( p_content_name in varchar2 ) return varchar2

open_binary_output_content( p_content_name in varchar2 ) return varchar2

Returns a handle from opening the specified output content for the request associated with the current session.

These are convenience functions that call open_output_content with the appropriate content type constant. See open_output_content for additional details.

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

Returns an opaque handle from opening the output content p_content_name for the request associated with the current session.

This creates a new output content entry if one does not already exist for the given name. If one already exists, then the specified content type must match that already established for that name.

p_content_type represents content type with one of the content type constants:

CONTENT_TYPE_TEXT (value: 1) for text content.

CONTENT_TYPE_BINARY (value: 2) for binary content.

This returns an opaque handle that is passed to subsequent procedures that operate on that output content.

The content entry is locked on successful return from this function. It may or may not be locked if this procedure fails. A commit or rollback releases the lock. The write_text_content or write_ntext_content procedures must be used to write data for text content, while the write_binary_content procedure must be used to write data for binary content.

You should call close_content to free any resources associated with the handle returned by this method. The close should be done prior to transaction commit or rollback.

NOTE: The content output support has DML semantics. The caller is responsible for the commit/rollback.

write_ntext_content( p_content_handle in varchar2, p_data in nvarchar2 )

write_text_content( p_content_handle in varchar2, p_data in varchar2 );

Writes data as p_data to the output content associated with the given handle. These operations are supported only for CONTENT_TYPE_TEXT content type.

p_content_handle is the output handle from a prior open_output_content call.

NOTE: The content output support has DML semantics. The caller is responsible for the commit/rollback.

write_binary_content( p_content_handle in varchar2, p_data in raw );

Writes binary data as p_data to the output content associated with the given handle. This operation is supported only for CONTENT_TYPE_BINARY content type.

p_content_handle is the output handle from a prior open_output_content call.

NOTE: The content output support has DML semantics. The caller is responsible for the commit/rollback.

close_content( p_content_handle in varchar2 );

Closes the output content handle. This releases resources associated with the given handle and it is no longer valid. Call this method before transaction commit or rollback.

p_content_handle is the output handle from a prior open_output_content call.

NOTE: The content output support has DML semantics. The caller is responsible for the commit/rollback. This method does not automatically perform a commit or rollback

output_content_exists( p_content_name in varchar2 ) return boolean;

Returns true if an output content entry having the specified name already exists for the request associated with the current session.

p_content_name is the name of the output content entity.

delete_output_content( p_content_name in varchar2 );

Deletes the specified output content entry for the request associated with the current session.

p_content_name is the name of the output content entity.


17.2.5.2 PL/SQL Output Creation Examples

Example 17-7 illustrates how to write text content into output, as well as how to write log entries along the way.

Example 17-7 PL/SQL Request Text Output

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;
/

Example 17-8 illustrates how to write binary content for output.

Example 17-8 PLSQL Request Binary Output Example

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 will be 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;
/

17.2.6 Creating Request Output from a Process Job

You create output from a process job logic by writing the content to the location specified by the ESS_OUTPUT_WORK_DIR environment variable that is available for all process jobs. As with other jobs, ensure that the SYS_EXT_supportOutputFiles system property is set to "output" so that the environment variable will be defined for the job.

After your process code writes the file, Oracle Enterprise Scheduler will automatically import output files in the directory into the content store as binary content.