OracleAS Job Scheduler User's Guide

Date: 02/25/2004

Table of Contents

  1. Introduction
  2. Job Implementation
  3. Example 1: Backup Job
  4. Example 2: Cancellable Backup Job
    1. Job Implementation Best Practices
  5. Schedule-Driven Jobs
    1. Single-Action Schedules
    2. Example 3: Backup Job and Single-Action Schedule
    3. Repeating Schedules
      1. Fixed Interval Schedules
      2. Example 4: Backup Job and Fixed Interval Schedule
      3. Cron Interval Schedule
      4. iCalendar Schedule Expressions
  6. Trigger-Driven Jobs
    1. Triggers and Notifications
    2. Not Operator Caveats
  7. Logging
    1. Job Execution Logging
    2. Job Implementation Logging
    3. Example 5: Backup Job With Logging
  8. Auditing


1. Introduction

The OracleAS Job Scheduler provides scheduled asynchronous processing to J2EE applications. By using the OracleAS Job Scheduler J2EE applications can:

This guide focuses on how to design, develop, and implement job's using the OracleAS Job Scheduler.


2. Job Implementation

This section is intended as an in-depth discussion designing and implementing jobs. A job provides an implementation of the oracle.ias.scheduler.Executable interface. This interface is defined as follows:

    public interface Executable {

        public void execute (JobContext context) throws JobExecutionException, JobCancellationException;
    }

The execute method is invoked by the scheduler when the associated job trigger fires. The input parameter of type oracle.ias.scheduler.JobContext provides a context for job execution. With this context a job can examine and evaluate all associated metadata related to the job definition as well as providing access to the logging subsystem.

The oracle.ias.scheduler.JobContext object provides the following methods:

Method Description
getLogger() Returns a JDK 1.4-compliant logger object of type java.util.logging.Logger that references the application's log.
getJob() Returns the job data object of type oracle.ias.scheduler.Job. This object is used to access the job's configuration information.

The exceptions that may be thrown by the execute method, and associated usage, are as follows:

oracle.ias.scheduler.JobExecutionException
If an error occurs during execution the underlying implementation should throw this exception, e.g. to wrap an exception generated during execution.
oracle.ias.scheduler.JobCancellationException
If the job likewise implements the interface oracle.ias.scheduler.Cancellable this exception is thrown to signify successful cancellation.

In order for a job to be executed it must first be submitted. This is done using the Scheduler's addJob() API. As part of the submission input parameters may be specified as name/value pairs using a java.util.Properties object. To improve reusabilty job parameters should be used whenever possible.


Example 1: Backup Job Implementation

A legacy application has been migrated to the J2EE environment, part of which includes data that is stored in the filesystem. As part of the J2EE application a job is required to backup the data on a regular basis. The job requires two input parameters as follows:

  1. source directory: the directory where the files will be copied
  2. destination directory: destination directory where the files will be copied

This information could have been hard-coded into the job implementation itself. However, by specifying these as parameters to the job properties the job can be reused later without modification. Refer to listing 2 for an example of how properties are specified.

Listing 1: Job Implementation

    import java.io.File;
    import java.io.IOException;
    import oracle.ias.scheduler.Job;
    import oracle.ias.scheduler.Executable;
    import oracle.ias.scheduler.JobContext;
    import oracle.ias.scheduler.JobExecutionException;


    public class BackupJob implements Executable {

        public void execute(JobContext context) throws JobExecutionException {

            // retrieve the source/destination directories
            Job job = context.getJob();
            String source = job.getProperties().getProperty("SourceDirectory");
            String destination = job.getProperties().getProperty("DestinationDirectory");

            // get the list of files to copy
            File directory = new File(source);
            File[] files = directory.listFiles();
        
            // copy the files
            Runtime runtime = Runtime.getRuntime();
            Process process;
            for (int x = 0; x < files.length; x++) {
                try {
                    process = runtime.exec("/bin/cp " + files[x].toString() +
                                           " " + destination);
                    process.waitFor();
                } catch(IOException e) {               
                    throw new RuntimeException("copy failed: "+files[x],e);
                } catch(InterruptedException e) {
                    throw new RuntimeException("copy failed: "+files[x],e);
                }
            }
        }
    }

Notice the implementation provides a single method execute(). Implementation of this method fulfills the contract for implementing the oracle.ias.scheduler.Executable interface. This method is invoked every time the job is executed.

Once a job has been created it must be submitted to the scheduler for execution. A job is submitted using the add method provided by the scheduler. The following code fragment demonstrates how the job is submitted with properties.

Listing 2: Submitting A Job With Properties

    // setup the properties
    java.util.Properties properties = new Properties();
    properties.put("SourceDirectory","/mnt/data");
    properties.put("DestinationDirectory","/mnt/backup");

    // submit the job
    scheduler.add("file backup job, runs every week",
                  new BackupJob().getClass().getName(),
                  new Schedule(),
                  properties);

Notice that the job properties and schedule are specified when the job is submitted to the scheduler.

The Scheduler supports the notion of non-destructive cancellation. This involves notifying the job implementation, through a pre-defined interface, that an administrator wishes to cancel the job's execution (e.g., in order to shutdown the container). This provides the job with the opportunity to perform any house cleaning (e.g., release resources, etc..) prior to aborting execution. In order to participate in cancellation a job must provide an implementation of the oracle.ias.scheduler.Cancellable.


Example 2: Cancellable Backup Job Implementation

During testing the developer realized the job may run for long periods of time. Realizing this it became apparent there may be need for cancelling the job.

The following is the modified implementation that provides an implementation of both oracle.ias.scheduler.Executable and oracle.ias.scheduler.Cancellable. By providing an implementation of this interface the job is eligible to be cancelled during execution.

Listing 3: Cancellable Job Implementation

    import java.io.File;
    import java.io.IOException;
    import oracle.ias.scheduler.Job;
    import oracle.ias.scheduler.Executable;
    import oracle.ias.scheduler.Cancellable;
    import oracle.ias.scheduler.JobContext;
    import oracle.ias.scheduler.JobCancellationException;
    import oracle.ias.scheduler.JobExecutionException;


    public class CancellableBackupJob implements Executable, Cancellable {

        boolean m_cancelled = false;


        public void cancel() {

            m_cancelled = true;
        }


        public void execute(JobContext context) throws
            JobExecutionException, JobCancellationException {

            // retrieve the source/destination directories
            Job job = context.getJob();
            String source = job.getProperties().getProperty("SourceDirectory");
            String destination = job.getProperties().getProperty("DestinationDirectory");

            // get the list of files to copy
            File directory = new File(source);
            File[] files = directory.listFiles();
        
            // copy the files
            Runtime runtime = Runtime.getRuntime();
            Process process;
            for (int x = 0; x < files.length; x++) {

                // cancelled?
                if (m_cancelled) {
                    throw new JobCancellationException();
                }

                try {
                    process = runtime.exec("/bin/cp " + files[x].toString() +
                                           " " + destination);
                    process.waitFor();
                } catch(IOException e) {               
                    throw new RuntimeException("copy failed: "+files[x],e);
                } catch(InterruptedException e) {
                    throw new RuntimeException("copy failed: "+files[x],e);
                }
            }
        }
    }

The following modifications have been made to the implementation:

  1. The class now implements the oracle.ias.scheduler.Cancellable interface
  2. A member variable has been added to signify the job cancellation to the execute method
  3. The cancel() method sets the m_cancelled method when it is invoked
  4. The for() loop exits when the member is set to a value of true
  5. The appropriate exception is thrown to signify the cancellation to the scheduler.

This method of cancellation is intentionally passive. Thus it is the application programmer's responsibility to react to the cancellation appropriately. At a minimum this means the following:

  1. The implementation must implement the oracle.ias.scheduler.Cancellable interface

  2. In order for the job to be cancelled invocation of the cancel() method must conclude with throwing the oracle.ias.scheduler.JobCancellationException

  3. It may not always be possible to immediately process invocation of the cancel() method so program accordingly


2.1 Job Implementation Best Practices

When designing and implementing a job keep the following in mind:

1. All job metadata is avaiable at execution time
Just use the provided oracle.ias.scheduler.Job object to get to it.

2. Improve job reuse through input parameters
During implementation identify inputs and parameterize as necessary.

3. A job that needs to be cancelled must implement the oracle.ias.scheduler.Cancellable interface.
Attempting to cancel a job that does not implement this interface will result in an exception.

4. When a job is cancelled it must signal to the scheduler that it has been cancelled.
The associated execute record will not reflect the cancellation. Likewise execution retry will not occur (if applicable).

5. Implementation of the execute method must eventually return control to the caller.
If the job's execution depends on application state consider using a trigger and have the application send one or more notifications the condition(s) have been satisfied.


3. Schedule-Driven Jobs

A schedule-driven job is a job that is associated with a schedule. Moreover, this indicates the job's execution is largely time-based. In contrast a job associated with a trigger is largely event-based and typically driven by events initiated by the application.


3.1 Single-Action Schedules

A single-action schedule refers to the class of schedules that have a single expiration. This kind of schedule should be used when a job requires a single timeout.

The class oracle.ias.scheduler.Schedule is used to specify this kind of schedule. This schedule provides the following attributes:

Attribute Description
expiration The initial expiration of the schedule


Example 3: Backup Job and Single-Action Schedule

During testing the developer and administrator realized the need to execute the backup job on an as-needed basis. To do this a single-action schedule will be used. The following code fragment demonstrates how the job is submitted with a single-action schedule.

Listing 4: Submitting A Job To Execute At A Specific Time

    // setup the properties
    java.util.Properties properties = new Properties();
    properties.put("SourceDirectory","/mnt/data");
    properties.put("DestinationDirectory","/mnt/backup");

    // setup the schedule, single-action at midnight
    Schedule schedule = new Schedule();
    Calendar midnight = Calendar.getInstance();
    midnight.set(Calendar.HOUR_OF_DAY,24);
    midnight.set(Calendar.MINUTE,0);
    midnight.set(Calendar.SECOND,0);
    schedule.setExpiration(midnight);

    // submit the job
    scheduler.add("file backup job, runs at midnight",
                  new BackupJob().getClass().getName(),
                  schedule,
                  properties);


3.2 Repeating Schedules

A repeating schedule refers to the class of schedules that are associated with multiple expirations. This kind of schedule should be used when a job requires repeating timeouts.


3.2.1 Fixed Interval Schedule

The class oracle.ias.scheduler.IntervalSchedule is used to specify this kind of schedule. This schedule provides the following attributes:
Attribute Description
expiration The initial expiration of the schedule
interval The interval (specified in milliseconds) between expirations
end date The date and time at which the schedule ends


Example 4: Backup Job and Fixed Interval Schedule

During testing the developer and administrator realized the need to execute the backup job on a weekly basis. To do this a repeating schedule will be used. The following code fragment demonstrates how the job is submitted with this kind of schedule.

Listing 5: Submitting A Repeating Job

    // setup the properties
    java.util.Properties properties = new Properties();
    properties.put("SourceDirectory","/mnt/data");
    properties.put("DestinationDirectory","/mnt/backup");

    // setup the schedule, repeats every week
    IntervalSchedule schedule = new IntervalSchedule();
    schedule.setInterval(IntervalSchedule.EVERY_WEEK);

    // submit the job
    scheduler.add("file backup job, runs at midnight",
                  new BackupJob().getClass().getName(),
                  schedule,
                  properties);


3.2.2 Cron Interval Schedule

Functionality not available in this release.


3.2.3 iCalendar Schedule Expressions

Functionality not available in this release.


4. Trigger-Driven Jobs

This section introduces two new concepts: trigger and notification. Notifications are messages sent from one object to another notifying the recipient something interesting has happened. The recipient of a notification is always a trigger. A trigger describes a condition based on the receipt of one or more notifications which, when evaluates to true, causes a job to execute. Triggers are described by a logical expression where the operands are job notification assertions. Notifications may be generated in either of the following ways:

Likewise notifications may either be sent to a specific trigger or to a specified set of triggers. On receipt, however, triggers in turn do not generate notifications. By employing the use of triggers job's can be enabled to respond to application conditions. For example triggering a job's execution based on revenue exceeding a threshold.


4.1 Triggers and Notifications

When a job is defined a trigger is associated with the definition. A trigger determines when the job will execute. When a job's definition does not include a trigger definition a default trigger is provided. This default trigger fires when the associated schedule expires.

A trigger is used to specify the conditions by which the associated job is executed. A condition is expressed as a logical combination of operands. The following logical operators are supported:

Precedence may be specified using the parentheses characters ‘(‘ and ‘)’. Example expressions:

The operand in a condition is the name associated with the notifications sent using the Scheduler notify() method.

For example to send the notification DataHasArrived to all triggers the application would use the following code fragment:

    Scheduler.notify(new Notification(“DataHasArrived”)); 

The scheduler evaluates triggers when the notification is sent. The result of a trigger evaluation is boolean. When the evaluation of the trigger is true the trigger fires resulting in the execution of the associated job. Once the trigger fires it is immediately reset before the job is executed. When a trigger is reset the record of all previously received notifications by the trigger are erased. If the trigger does not fire the notification is recorded by the trigger for later use.

For example a trigger has the following condition:

    N1 && N2

Assume the trigger receives notification N1. Using the notification the trigger evaluates to false and the notification is recorded. Next the trigger receives notification N2. Using the notification the trigger evaluates to true and the trigger fires and the job is executed. After the job completes execution the trigger is reset.

Jobs may be associated with a schedule, trigger, or both a schedule and trigger. When a job is associated with a schedule only, an implicit trigger is associated with the job.

When the schedule expires a timeout notification is always sent to the associated trigger for processing. In the implicit case this results in the trigger firing, execution of the job, and finally the trigger is reset. More generally the timeout notification may also be used in a trigger expression along with other notifications.

Example expressions using the timeout notification:

The timeout notification may only be used in cases where the job is associated with both a schedule and a trigger. The notification name timeout is likewise reserved and may not be used or sent by an application to the scheduler. Additionally the timeout notification must be referenced in the condition expression of the trigger.


4.2 Not Operator Caveats

When employing the use of the not operator in trigger expressions the following guidelines should be followed.

  1. Not expressions should include atleast two operators - If not the trigger will fire when any other notification is received. Consider the expression !N; this should be interpreted as "fire the trigger whenever any notification is received unless the notification is N".

  2. Should not be used with a schedule that repeats indefinitely - This may result in a permanently hung trigger. Recall that triggers retain all notifications that have been received until the trigger fires. If trigger receives a notification that satisfies the not condition the trigger will never fire.


5. Logging

The job scheduler provides several kinds of logging semantics. They are as follows:

  1. Runtime logging - Logging that is performed on behalf of the schedule subsystem, e.g. a warning message as a result of misconfiguration.

  2. Execution logging - Logging that is related to the execution the level of which is specified as part of the job's definition, e.g. when the job execution completes.

  3. Job implementation logging - Logging that is performed by the job implementation.


5.1 Execution Logging

Execution logging is specified as part of the job's definition. Because the scheduler uses the Java logging APIs log levels are specified using the log levels provided by the class java.util.logging.Level.

If the logging level is set to a value of Level.WARNING, log entries are written under the following conditions:

If the logging level is set to a value of Level.FINE the following additional information is written to the log:

If the log level is set to a value of Level.FINER the following additional information is written to the log:

If the log level is set to a value of Level.FINEST the following additional information is written to the log:


5.2 Job Implementation Logging

The same logging facilities used by execution logging is also available to the job implementation when it is executed. The logging context is available via the context that is passed to the job when it is executed via the JobContext object:

    public interface JobContext extends Serializable {


        public Job getJob();

        public java.util.logging.Logger getLogger();

        public java.util.logging.Logger getLogger(String resourceBundleName);
    }

Either of the getLogger() methods can be used, the latter of which allows a resource bundle to be specified.


Example 5: Backup Job With Logging

Our developer has decided to add logging capabilities to her job. In this example a message is logged for every file backed up.

Continuing from Example 4 an information log entry is written before every file is copied. This is done by retrieving the logger from the passed in job context and writing an informational log message prior to performing the copy command.

Listing 6: Job Implementation With Logging

    import java.io.File;
    import java.io.IOException;
    import java.util.logging.Logger;
    import oracle.ias.scheduler.Job;
    import oracle.ias.scheduler.Executable;
    import oracle.ias.scheduler.Cancellable;
    import oracle.ias.scheduler.JobContext;
    import oracle.ias.scheduler.JobCancellationException;
    import oracle.ias.scheduler.JobExecutionException;


    public class CancellableBackupJobLogged implements Executable, Cancellable {

        boolean m_cancelled = false;


        public void cancel() {

            m_cancelled = true;
        }


        public void execute(JobContext context) throws JobExecutionException, JobCancellationException {

            // retrieve the source/destination directories
            Job job = context.getJob();
            Logger log = context.getLogger();
            String source = job.getProperties().getProperty("SourceDirectory");
            String destination = job.getProperties().getProperty("DestinationDirectory");

            // get the list of files to copy
            File directory = new File(source);
            File[] files = directory.listFiles();
        
            // copy the files
            Runtime runtime = Runtime.getRuntime();
            Process process;
            for (int x = 0; x < files.length; x++) {

                // cancelled?
                if (m_cancelled) {
                    throw new JobCancellationException();
                }

                log.info("copying file "+files[x]);
                try {
                    process = runtime.exec("/bin/cp " + files[x].toString() +
                                           " " + destination);
                    process.waitFor();
                } catch(IOException e) {               
                    throw new RuntimeException("copy failed: "+files[x],e);
                } catch(InterruptedException e) {
                    throw new RuntimeException("copy failed: "+files[x],e);
                }
            }
        }
    }


6. Auditing

Execution audit records provide audit information for the execution of every submitted job. This information can be used to determine, for example, when the job execution occurred. An execution audit record, as defined by the class oracle.ias.scheduler.ExecuteRecord provides the following information:

Attribute Java Type Description
Execution Start Time java.util.Calendar Time at which job execution started.
Execution End Time java.util.Calendar Time at which job execution ended. This value is null until the job execution has completed, signified by a status value of EXECUTION_INCOMPLETE.
Execution Type int The type associated with this job execution, one of TRIGGER_TYPE, REPLAY_TYPE, RETRY_TYPE as defined in the class oracle.ias.scheduler.ExecuteRecord.
Execution Status int Status of the job execution, one of EXECUTION_INCOMPLETE, EXECUTION_SUCCEEDED, EXECUTION_FAILED, EXECUTION_CANCELLED, EXECUTION_BLACKOUT, EXECUTION_THRESHOLD_EXCEEDED as defined in the class oracle.ias.scheduler.ExecuteRecord.
Exeception java.lang.Throwable If the status is EXECUTION_FAILED the associated exception which was the cause of the failure.


Typically a job executes as a result of the associated trigger firing either due to the associated schedule expiring or as a result of a notification. The reason for execution is summarized by the execution type field in the execute audit record. The following table details the difference between the types of job execution:

Execution Type Description
TRIGGER_TYPE Execution occurred as a result of the trigger firing either through a) the associated schedule expiring or b) via a notification.
REPLAY_TYPE A previously paused job was resumed with the replay flag set to true. Execution will result only if the trigger fired during the time the job was paused.
RETRY_TYPE Execution occurred as a result of the immediately prior execution failing. Retry will occur if a non-zero retry value was specified when the job was submitted.


The following table summarizes the difference between the status types for a job execution:

Status Type Description
EXECUTION_INCOMPLETE Execution has started but not yet completed.
EXECUTION_SUCCEEDED Execution has completed and the result was success.
EXECUTION_FAILED Execution has completed and resulted in a failure.
EXECUTION_CANCELLED Execution had started and, prior to completing, was cancelled.
EXECUTION_BLACKOUT Execution was supressed due to an active blackout window when execution was attempted.
EXECUTION_THRESHOLD_EXCEEDED The time at which execution occurred exceeded the threshold specified when the job was submitted.


As previously mentioned an audit record is created every time a job executes and audit records are always stored in the job store. The following Scheduler methods are used to manage audit records:

Method Name Description
getAuditRecords Returns a collection view of all audit records for the job specified.
removeAuditRecords Removes all audit records for the job specified.