14 Using the Runtime Service

This chapter describes how to use the Oracle Enterprise Scheduler runtime service APIs for submitting and managing job requests and for querying job request information from the job request history.

This chapter includes the following sections:

14.1 Introduction to the Runtime Service

Oracle Enterprise Scheduler lets you define and run different job types including: Java classes, PL/SQL procedures, and process job types (forked processes). To run these job types you need to submit a job definition.

You can use the runtime service to perform different types of operations, including:

  • Submit: These operations let you supply a job definition to Oracle Enterprise Scheduler to create job requests.

  • Manage: These operations allow you to change the state of job requests and to update job requests.

  • Query: These operations let you find the status of job requests and report job request history.

14.2 Accessing the Runtime Service

Like the metadata service, Oracle Enterprise Scheduler provides a runtime MBean proxy interface.

The runtime service open() method begins each Oracle Enterprise Scheduler runtime service user transaction. In an Oracle Enterprise Scheduler application client you obtain a RuntimeServiceHandle reference that is created by open() and you pass the reference to runtime service methods. The RuntimeServiceHandle reference provides a connection to the runtime service for the client application. In the client application you must explicitly close the runtime service by calling close(). This ends the transaction and causes the transaction to be committed or rolled back (undone). The close() not only controls the transactional behavior within the runtime service, but it also allows Oracle Enterprise Scheduler to release the resources associated with the RuntimeServiceHandle.

14.2.1 How to Access the Runtime Service and Obtain a Runtime Service Handle

Oracle Enterprise Scheduler exposes the runtime service to your application program as a Stateless Session Enterprise Java Bean (EJB). You can use JNDI to locate the Oracle Enterprise Scheduler runtime service Stateless Session EJB.

Example 14-1 shows a lookup for the Oracle Enterprise Scheduler runtime service using the RuntimeServiceLocalHome object.

Example 14-1 JNDI Lookup to Access Oracle Enterprise Scheduler Runtime Service

import oracle.as.scheduler.core.JndiUtil;
// Demonstration of how to lookup runtime service from a
// Java EE application component
    
    RuntimeService runtime = JndiUtil.getRuntimeServiceEJB();
    RuntimeServiceHandle rHandle = null;
    .
    .
    .
    try
    {
         ...
         rHandle = runtime.open();
         ...
    }
    finally
    {
        if (rHandle != null)
        {
            runtime.close(rHandle);
        }
    }

Note:

When you access the runtime service:

  • JndiUtil.getRuntimeServiceEJB() assumes that the RuntimeService EJB has been mapped to the local JNDI location "ess/runtime". This happens automatically in the hosted application's message-driven bean (MDB).

  • The open() call provides a RuntimeServiceHandle reference. You use this reference with the methods that access the runtime service in your application program.

  • When you finish using the runtime service you must call close() to release the resources associated with the RuntimeServiceHandle.

14.3 Submitting Job Requests

When you submit a job definition you create a new job request. You can submit a job request using a job definition that is persisted to a metadata repository, or you can create a job request in an ad hoc manner where the job definition or the schedule is not stored in the metadata repository (for information about ad hoc requests, see Section 14.6, "Submitting Ad Hoc Job Requests").

14.3.1 How to Submit a Request to the Runtime Service

You create a job request by calling submitRequest(). Depending on your needs, you can create a job request with one of the following formats:

  • Create a new job request using a job definition stored in the metadata repository, to run once at a specific time.

  • Create a new job request using a job definition and a schedule, each stored in the metadata repository.

Example 14-2 shows the submitRequest() method that creates a new job request with a job definition that resides in the metadata repository. You can also submit an ad hoc job request where the job definition and schedule are not stored in the metadata repository. For more information, see Section 14.6, "Submitting Ad Hoc Job Requests". You can also submit a sub-request. For more information, see Chapter 15, "Using Subrequests".

Example 14-2 Creating a Job Request with submitRequest()

long requestID = 0L;
MetadataObjectId jobDefnId;
 
RequestParameters p = new RequestParameters();
 
p.add(SystemProperty.CLASS_NAME, "demo.jobs.Job");
 
Calendar start = Calendar.getInstance();
start.add(Calendar.SECOND, startsIn);
 
requestID =
    runtime.submitRequest(r,
        "My Java job",
        jobDefnId,
        start,
        p);

Note:

When you submit a job request using the runtime service:

  • You obtain the runtime service handle as shown in Example 14-1.

  • The runtime service internally uses the metadata service to obtain job definition metadata with the supplied MetadataObjectId, jobDefnId.

14.3.2 What You Should Know About Default System Properties When You Submit a Request

When you create a job request Oracle Enterprise Scheduler resolves and stores the properties associated with the job request. Oracle Enterprise Scheduler requires that certain system properties are associated with a job request. If you do not set these required properties anywhere in the properties hierarchy when a job request is submitted, then Oracle Enterprise Scheduler provides default values.

Table 14-1 shows the runtime service field names and the corresponding system properties for the required job request properties.

Table 14-1 Runtime Service Default Value Fields and Corresponding System Properties

Value Runtime Service Default Value Field Corresponding System Property Description

0

DEFAULT_REQUEST_EXPIRATION

REQUEST_EXPIRATION

The default expiration time, in minutes, for a request. The default value is 0 which means the request will never expire.

4

DEFAULT_PRIORITY

PRIORITY

The default system priority associated with a request.

5

DEFAULT_REPROCESS_DELAY

REPROCESS_DELAY

The default period, in minutes, in which processing must be postponed by a callout handler that returns Action.DELAY.

0

DEFAULT_RETRIES

RETRIES

The default number of times a failed request will be retried. The default value is 0 which means a failed request is not retried.


14.3.3 What You Should Know About Metadata When You Submit a Request

All Oracle Enterprise Scheduler Metadata associated with a job request is persisted in the runtime store at the time of request submission. Persisted metadata objects include job definition, job type, job set, schedule, incompatibility definitions, and exclusion definition. Metadata is stored in the context of a top level request, and each metadata object is uniquely identified by the absolute parent request id and its metadata id. Each unique metadata object is stored only once for a top-level request, even if the definition is used multiple times in the request. This ensures that every child request uses the same definition.

When a request is submitted, all known metadata for the request is persisted. For subrequests, the metadata is not know until the subrequest is submitted, so subrequest metadata is persisted when the subrequest is submitted, after first checking that the metadata object is not already persisted in the runtime store.

Metadata persisted in the runtime store is removed when the absolute parent request is deleted.

14.4 Managing Job Requests

After you submit a job request, using the requestID you can do the following:

  • Get request information

  • Change the state of the request

  • Update request parameters

  • Purge a request

14.4.1 How to Get Job Request Information with getRequestDetail

Using the runtime service, with a requestID, you can obtain information about a job request that is in the system. Table 14-2 shows the runtime service methods that allow you to obtain job request information.

Table 14-2 Runtime Service Get Request Methods

Runtime Service Method Description

getRequestDetail()

Retrieves complete runtime details for the specified request

getRequestDetailBasic()

Retrieves basic runtime details of the specified request. The RequestDetail returned by this method includes most of the information as getRequestDetail(), but certain less commonly used information is omitted to improve performance.

getRequestParameter()

Retrieves the value of a request parameter.

getRequests()

Retrieves an enumeration of immediate child request identifiers associated with the specified request. This will include IDs for requests that did not complete, such as when the request transaction is rolled back or an error occurs.

getRequestState()

Retrieves the current state of the specified request


Example 14-3 shows code that determines if there is any immediate child request in the HOLD state.

Example 14-3 Determining Whether Any Immediate Child Job Requests Are on Hold

        h = s_runtime.open();
        try {
 
            s_runtime.holdRequest(h,reqid);
 
            Enumeration  e = s_runtime.getRequests(h, reqid);
 
            boolean foundHold = false;
            while (e.hasMoreElements()) {
 
                long childid = ((Long)e.nextElement()).longValue();
                State state = s_runtime.getRequestState(h,childid);
                if (state == State.HOLD) {
                    foundHold = true;
                    break;
                }
            }

14.4.2 How to Change Job Request State

Using the runtime service, with a requestID, you can change the state of a job request. Table 14-3 shows the runtime service job request state change methods. The job request management methods allow you to change the state of a request, depending on the state of the job request. For example, you cannot cancel a request with cancelRequest() if the request is in the COMPLETED state.

Table 14-3 Runtime Service Job Request State Methods

Runtime Service Method Description

cancelRequest()

Cancels the processing of a request that is not in a terminal state.

deleteRequest()

Marks a request in a terminal state for deletion.

holdRequest()

Withholds further processing of a request that is in WAIT or READY state.

releaseRequest()

Releases a request from the HOLD state.


Example 14-4 shows a submitRequest() with methods that control the state of the job request. The holdRequest() holds the processing of the job request. The corresponding releaseRequest() releases the request. This example does not show the conditions that require the hold for the request.

Example 14-4 Runtime Service releaseRequest() Usage

rHandle = s_runtime.open();
try {
            s_runtime.holdRequest(rHandle,reqid);
            Enumeration  e = s_runtime.getRequests(rHandle, reqid);
            while (e.hasMoreElements()) {
 
                long childid = ((Long)e.nextElement()).longValue();
                State state = s_runtime.getRequestState(rHandle,childid);
                if (state == State.HOLD) {
                    foundHold = true;
                    break;
                }
            }
.
.
.
            s_runtime.releaseRequest(rHandle, reqid);
.
.
.

Note:

Note the following in Example 14-4:

  • You obtain the runtime service handle, rHandle, as shown in Example 14-1.

  • The holdRequest() places the request in the HOLD state.

  • You may do some required processing while the request is in the HOLD state.

  • The releaseRequest() releases the request from the HOLD state.

14.4.3 How to Update Job Request Priority and Job Request Parameters

Using the runtime service you can update job request system properties or request parameters. Table 14-4 shows the runtime service methods that allow you to lock and update up a job request.

Table 14-4 Runtime Service Update Methods

Runtime Service Method Description

lockRequest()

Acquires a lock for the given request. The lock is released when close() operation is subsequently invoked or the encompassing transaction is committed. If an application tries to invoke this operation while the lock is being held by another thread, this method will block until the lock is released. Use this method to ensure data consistency when updating request parameters or system properties.

updateRequestParameter()

Updates the property value of the specified request subject to the property read-only constraints.


Example 14-5 shows code that updates a job request parameter. This code would be wrapped in a try/finally block as shown in Example 14-1.

Example 14-5 Sample Runtime Service Parameter Update

...
  s_runtime.lockRequest(rhandle, reqid);
  s_runtime.updateRequestParameter(rhandle, reqId, paramName, "yy");
...

Example 14-5 shows the following:

  • Obtain the runtime service handle, rhandle, as shown in Example 14-1.

  • Acquire a lock for either the request using lockRequest()

  • Perform the update operation with updateRequestParameter()

  • Use close() to cause the transaction to be committed or rolled back (undone). The close() not only controls the transactional behavior within the runtime service, but it also allows Oracle Enterprise Scheduler to release the resources associated with the RuntimeServiceHandle.

14.5 Querying Job Requests

Using the runtime service you can query job request information. This involves the following steps:

  • Query for request identifiers and limit results with a filter.

  • Get request details to provide additional information for each request ID that the query returns.

There is only one query method; the runtime service queryRequests() method returns an enumeration of request IDs that match the query. The queryRequests() method includes a filter argument that contains field, comparator, and value combinations that help select query results. Note that the return value will include IDs for requests that did not complete, such as when the request transaction is rolled back or an error occurs. For more information on filters, see Section 6.4.1, "How to Create a Filter".

When you create a filter for a query, you can use any of the field names shown in Table 14-5 when querying the runtime store.

Table 14-5 Query Filter Fields For Querying the Runtime (Defined in Enum RuntimeService.QueryField)

Name Description

ABSPARENTID

The absolute parent request ID of a request.

APPLICATION

The application name.

ASYNCHRONOUS

Indicates if the job is asynchronous, synchronous or unknown. The value of the field is not set until the request is processed. The field data type is java.lang.Boolean. The value may be NULL if the nature of the job has not yet been determined.

CLASSNAME

The name of the executable class that processed the request

COMPLETED_TIME

The date and time that Oracle Enterprise Scheduler finished processing the request. This field represents the time the process phase was set to COMPLETED.

DEFINITION

The job definition ID (Metadata Object ID).

ELAPSEDTIME

The amount of time, in milliseconds, that elapsed while the request was running.

ENTERPRISE_ID

The enterprise ID.

ERROR_TYPE

The request error type.

EXTERNAL_ID

The identifier for an external portion of an Oracle Enterprise Scheduler asynchronous Java job.

INSTANCEPARENTID

The request ID of the instance parent request.

JOB_TYPE

The job type ID (Metadata Object ID).

NAME

The request description.

PARENTREQUESTID

The parent request ID.

PRIORITY

The priority of the request.

PROCESS_PHASE

The process phase of the request.

PROCESSEND

The date and time that the process ended. The PROCESSSTART is set only when a request transitions from READY to RUNNING. This implies that (PROCESSEND - PROCESSSTART) encompasses the entire span of execution: from the time the state becomes RUNNING to the time it transitions to a terminal state.

PROCESSOR

The name of the instance that processed the request.

PROCESSSTART

The date and time that the process started. The PROCESSSTART is set only when a request transitions from READY to RUNNING. This implies that (PROCESSEND - PROCESSSTART) encompasses the entire span of execution: from the time the state becomes RUNNING to the time it transitions to a terminal state.

PRODUCT

The product name.

READYWAIT_TIME

The amount of time, in milliseconds, a request has been waiting to run since it became READY.

REQUEST_CATEGORY

The request category specified for the request.

REQUESTEDEND

The requested end time.

REQUESTEDSTART

The requested start time.

REQUESTID

The request ID of a submitted request.

REQUESTTYPE

The type of request (that is, an element of RequestType)

RESULTINDEX

Controls the starting and ending index of the returned results. This field allows users to express result constraints such as "return only results 10 through 20".

RETRIED_COUNT

The retried count associated with a job. This field represents the number of times the job was retried.

SCHEDULE

The schedule ID (Metadata Object ID).

SCHEDULED

The time when the request is scheduled to be executed.

STATE

The job request state.

SUBMISSION

The submission time of the request.

SUBMITTER

The submitter of the request.

SUBMITTERGUID

The submitter GUID of the request.

TIMED_OUT

Indicates whether the job has timed out.

TYPE

The execution type of the request.

USERNAME

The name of the user who submitted the request.

WAITTIME

The amount of time, in milliseconds, a request has been waiting to run.

WORKASSIGNMENT

The name of the work assignment that was active when the request was processed.


Table 14-6 shows the runtime service method for querying job requests and Example 14-6 shows the use of this method.

Table 14-6 Runtime Service Query Methods

Runtime Query Method Description

queryRequests()

Gets a summary of requests.


Example 14-6 Using queryRequest() Method

           Filter filter =
                new Filter(RuntimeService.QueryField.DEFINITION.fieldName(),
                           Filter.Comparator.EQUALS,
                           m_myJavaSucJobDef.toString())
                .and(RuntimeService.QueryField.STATE.fieldName(),
                     Filter.Comparator.EQUALS,
                     new Integer(12) );
 
            // 
            Enumeration requests =
                s_runtime.queryRequests(h,
                                        filter,
                                        RuntimeService.QueryField.REQUESTID,
                                        false);

14.6 Submitting Ad Hoc Job Requests

To use an ad hoc request you supply request parameters, a job definition, and optionally a schedule that you create and define without saving it to a metadata repository. An ad hoc request does not require you define the details of a job request in a metadata repository. Thus, ad hoc requests support an abbreviated job request submission process that can occur without using a connection to the metadata repository.

Note:

Ad hoc requests have the following limitation: job sets are not supported with ad hoc requests.

14.6.1 How to Create an Ad Hoc Request

To create an ad hoc request you use the ad hoc version of submitRequest(). For the job definition, instead of supplying a job definition MetadataObjectId, you can define the job definition object and use a system property that corresponds to the job type, as shown in Table 14-7.

Table 14-7 Ad Hoc Request Job Definition System Properties for Job Types

System Property Description

CLASS_NAME

Specifies the Java class to execute (for a Java job type).

PROCEDURE_NAME

Specifies the PL/SQL stored procedure to execute (for an SQL job type).

CMDLINE

Specifies the command line used to invoke an external program for a process job request.


With one signature of the ad hoc version of submitRequest() you do not need to supply MetadataObjectIds, you can provide the Schedule object as an argument as object instances directly to submitRequest(). Other ad hoc submitRequest() signatures allow you to submit a job request using a job definition from metadata and an instance for the Schedule object.

Example 14-7 shows sample code for an ad hoc request submission that uses a schedule.

Example 14-7 Creating Request Parameters and a Schedule for an Ad Hoc Request

            RequestParameters p = new RequestParameters();
            String propName = "testProp";
            String propValue = "testValue";
            p.add(propName, propValue);
            p.add(SystemProperty.REQUEST_EXPIRATION, new Integer(10));
            p.add(SystemProperty.LISTENER, "test.listener.TestListener");
            p.add(SystemProperty.EXECUTE_PAST, "TRUE");
            p.add("application", getApplication());
            p.add(SystemProperty.CLASS_NAME, "test.job.HelloWorld");
 
            Calendar start = Calendar.getInstance();
            start.add(Calendar.SECOND, 5);
            Calendar end = (Calendar) start.clone();
            end.add(Calendar.SECOND, 5);
 
            Recurrence recur = new Recurrence(RecurrenceFields.FREQUENCY.SECONDLY,
                                              2,
                                              start,
                                              end);
 
            Schedule schedule = new Schedule("mySchedule",
                                     "Run every 2 sec for 3 times.",
                                      recur);
 
            // adhoc submission, no metadata definitions passed
            reqId = s_runtime.submitRequest(h,
                                    "testAdhocJavaWithSchedule",
                                    JobType.ExecutionType.JAVA_TYPE,
                                    schedule,
                                    null,
                                    Calendar.getInstance(),
                                    null,
                                    p);

In this example, note the following ad hoc specific details for the request submission:

  • The CLASS name is set to define the Java class that runs when Oracle Enterprise Scheduler executes the job request: p.add(SystemProperty.CLASS_NAME, "test.job.HelloWorld");

  • The submitRequest() includes an argument that specifies the job type: JobType.ExecutionType.JAVA_TYPE.

  • Specify the Java class, the procedure name, or the command line program to execute when the ad hoc Request is processed by setting one of the system properties shown in Table 14-7.

  • Call the ad hoc version of submitRequest() specifying the type argument to correspond with the system property you set to define the request. The type you supply must be one of JAVA_TYPE, SQL_TYPE, or PROCESS_TYPE.

  • As with any job request, set the appropriate system properties to be associated with the job request.

14.6.2 What Happens When You Create an Ad Hoc Request

The ad hoc submitRequest() returns the request identifier for the request. You can use this request identifier with runtime calls such as updateRequestParameter() or getRequestDetail() as you would with any other job request.

There is only one submitRequest signature that will create a request with an ad hoc job definition. The job definition ID, obtained from RequestDetail.getJobDefn(), is null in this case. Without an ad hoc job definition, a request cannot be considered ad hoc.

14.6.3 What You Need to Know About Ad Hoc Requests

If you want to define a schedule to use with an ad hoc request and you want to specify exclusion dates, you need to exclude the dates using the addExclusionDate() method for the schedule. For ad hoc requests, you cannot use a schedule that specifies exclusion dates using addExclusion() method for the schedule.

Currently, if the schedule is ad hoc, a check of ExclusionDefinition is skipped. Thus, if you use a schedule and use addExclusion() and submit an ad hoc job request, then Oracle Enterprise Scheduler does not use the ExclusionsDefinition IDs with the job request.

14.7 Implementing Pre-Process and Post-Process Handlers

Along with the core logic of your job, you can include code that executes before and after the job's main execution code. With code that executes before, known as a pre-process handler, you can do such things as set up certain conditions for the job executable. With code that executes after, known as a post-process handler, you can do such things as processing the results of the job executable, perhaps by printing reports or sending notifications.

You provide pre- and post-process handlers by implementing specific interfaces, then connecting your implementations to the service through a system property that indicates which of your classes to use.

14.7.1 Implementing a Pre-Process Handler

With a pre-process handler, your code can do things to create an environment for your job to execute. This could include creating connections to resources that your job requires, for example.

The pre-processor is instantiated and invoked at the start of request execution when the request transitions to RUNNING state. This is done each time the request is executed, including when a failed request is retried or a paused request is resumed after its sub-requests have completed.

You create a pre-process handler by implementing the oracle.as.scheduler.PreProcessHandler interface. With your pre-process handler class in hand, you specify that it should be used by setting the SYS_preProcess system property to the fully-qualified name of your handler class. You can define the property on job metadata or include it in the request submission parameters.

14.7.1.1 Implementing the PreProcessHandler Interface

Your PreProcessHandler implementation should do the pre-process actions your job requires, then return an oracle.as.scheduler.HandlerAction instance from the interface's one method, preProcess. (Your class may also implement the Cancellable interface if you want the job to support cancellation. It must also provide an empty constructor.)

The HandlerAction instance your preProcess implementation returns should give status about whether, and under what conditions, the job should proceed. When constructing the HandlerAction class, you pass it a HandlerStatus instance that indicates the status of pre-processing for the request.

Supported HandlerStatus values and actions are listed below. An unsupported status will cause the request to transition to an error state and be subject to retries if configured.

  • PROCEED informs Oracle Enterprise Scheduler that request processing should commence. The request will remain in RUNNING state.

  • WARN informs Oracle Enterprise Scheduler that request processing should commence but that a warning should be logged. The request will remain in RUNNING state.

  • CANCEL informs Oracle Enterprise Scheduler that request pre-processing has been cancelled. The request will transition to CANCELLED state.

  • DELAY informs Oracle Enterprise Scheduler to postpone request processing by the quantum of time specified by the SYS_reprocessDelay system property. The request remains in RUNNING state during the delay.

  • SYSTEM_ERROR informs Oracle Enterprise Scheduler that the handler has experienced an error. The request will transition to an error state and is subject to retries if configured.

  • BIZ_ERROR informs Oracle Enterprise Scheduler that the handler has experienced a business error. The request will transition to an error state not subject to retries.

14.7.2 Implementing a Post-Process Handler

With a post-process handler, your code can do things that should take place after your job has executed. This could include releasing connections to resources that your job required, for example, or generating a report based on request-specific data or status.

The post-processor is instantiated and invoked after job execution, when the request transitions to COMPLETED state. The post-processor is invoked only once for a request, in contrast to the pre-processor.

You create a post-process handler by implementing the oracle.as.scheduler.PostProcessHandler interface. With your post-process handler class in hand, you specify that it should be used by setting the SYS_postProcess system property to the fully-qualified name of your handler class. You can define the property on job metadata or include it in the request submission parameters.

14.7.2.1 Implementing the PostProcessHandler Interface

Your PostProcessHandler implementation should do the post-process actions your job requires, then return an oracle.as.scheduler.HandlerAction instance from the interface's one method, postProcess. (Your class may also implement the Cancellable interface if you want the job to support cancellation. It must also provide an empty constructor.)

The HandlerAction instance your postProcess implementation returns should give status about whether, and under what conditions, the job should conclude. When constructing the HandlerAction class, you pass it a HandlerStatus instance that indicates the status of post-processing for the request.

Supported HandlerStatus values and actions are listed below. An unsupported status will cause the request to transition to WARNING state.

  • PROCEED to inform Oracle Enterprise Scheduler that request post-processing completed successfully. The request will transition to SUCCEEDED state or WARNING state depending on the status of the request prior to invoking the post-processor.

  • WARN to inform Oracle Enterprise Scheduler that request post-processing resulted in a warning. The request will transition to WARNING state.

  • CANCEL informs Oracle Enterprise Scheduler that request post-processing has been cancelled. The request will transition to WARNING state.

  • DELAY to inform Oracle Enterprise Scheduler to postpone request processing by the quantum of time specified by the SYS_reprocessDelay system property. The request remains in COMPLETED state during the delay.

  • SYSTEM_ERROR to inform Oracle Enterprise Scheduler that the handler has experienced an error. The request will transition WARNING state.

  • BIZ_ERROR to inform Oracle Enterprise Scheduler that the handler has experienced a business error. The request will transition to WARNING state.