Transactions and schedulers
The scheduler runs a task in a single global transaction, by default. You can use the QOS_ONLYONCE or QOS_ATLEASTONCE quality of service to specify whether the task runs as a single unit of work once or as independent transactions.
Transaction behavior when running a task
Because the scheduler runs a task in a single global transaction, by default, the transaction is open until the task completes or fails. The resources involved in that transaction are subject to various timeouts and the thread of the task could be identified as hung if the task runs for a long period of time that can span many minutes or hours.
The TaskInfo.setQOS method allows reducing the quality of service for the task to run at-least-once. When you set the task to TaskInfo.QOS_ATLEASTONCE, the task does not keep a transaction open for the duration of the running task. Because this quality of service is no longer transactional, the task may fire more than one time if the scheduler fails to update the result of the task. This quality of service is ideal for batch jobs. Use QOS_ATLEASTONCE with check points in the business logic, so if the task needs to recover, the business logic can continue at the next check point. See the com.ibm.websphere.scheduler.TaskInfo API documentation for more details.
QOS_ONLYONCE
Scheduled tasks execute only one time successfully when using the QOS_ONLYONCE quality of service. This action is accomplished by grouping all of the work done in the task as a single unit of work. When each task fires, the following events occur in a single global transactional context:
- The context of the application that created the task is applied to the thread.
- A global transactional context is started.
- The next fire time and start-by time are calculated using the UserCalendar bean or the DefaultUserCalendar.
If using the TaskInfo.setTaskExcecutionOptions method with the TaskInfo.EXECUTION_DELAYEDUPDATE option, this step will occur after the record is updated.
- The task database task record is updated in the database with the state of the next task or deleted if the task is complete and the task's auto-purge setting is true.
- The task database record is updated in the database with the state of the next task or deleted if the task is complete and the task's auto-purge setting is true. If the EXECUTION_DELAYEDUPDATE option is used, the database will not reflect the next state of the task, but the current state with the TaskStatus.RUNNING state set.
- If the NotificationSink bean is set, a FIRING notification is fired.
- The BeanTaskInfo or MessageTaskInfo object starts.
- If the task fails and the NotificationSink bean is set, a FIRE_FAILED notification is fired on a separate transaction.
- If the task's NotificationSink bean is set, then the various notifications are fired as required.
- If the EXECUTION_DELAYEDUPDATE option is used for the task, the database will be updated a second time with the next state of the task.
- The global transaction is committed.
Because all events belonging to a task are executed in a single global transactional context, consider the following points in order to avoid transaction-related errors:
- Each resource participating in the task transaction must be two-phase XA capable.
This includes the JDBC datasource configured for the scheduler, any JMS services used by the MessageTaskInfo objects, and any resources used within any of the UserCalendar, TaskHandler, or NotificationSink beans that have a transaction setting of "Required".
- One resource can be single-phase, if last participant support is enabled for the application that created the transaction. Enable last participant support using an assembly tool. You can also enable last participant support through the console. See the topic, "Last participant support extension settings" for details.
All unexpected exceptions are logged to the activity.log and all events participating in the task's global transaction are rolled back. This includes changes to the task's database record, which force the task to be executed again when the scheduler daemon polls the database during the next poll cycle. The UserCalendar, TaskHandler, and NotificationSink beans can choose not to participate in the global transaction by configuring the bean transaction setting to "Requires new".
QOS_ATLEASTONCE
Scheduled tasks that use the QOS_ATLEASTONCE quality of service do not have a single transactional context. In this case, each calendar calculation, event notification and database update occurs in an independent transaction:
- The context of the application that created the task is applied to the thread.
- The task’s database record is updated with the RUNNING state of the task.
- UserCalendar, NotificationSink beans are called.
- The BeanTaskInfo or MessageTaskInfo is started.
- Result notifications are sent.
- The database is updated with the next state of the task, if the task has not been changed since the RUNNING state was written.
If a failure happens after the RUNNING state is written to the database and before the result is written, then the task may run more than one time.
When using QOS_ATLEASTONCE, all NotificationSink, UserCalendar and TaskHandler beans must not mandate a transaction (TX_MANDATORY), since there is no global transaction available when the task runs. The EJB components use "Required" or "Requires new" container managed transaction or a bean managed transaction.
Transaction behavior when using the Scheduler API methods or WASScheduler MBean operations
All Scheduler interface methods participate in a single global transactional context. If a global transactional context is already present on the thread when the create(), suspend(), resume(), cancel(), and purge() methods are executed, then the existing global transaction is used. Otherwise, a new global transaction begins.
If the method participates in the global transaction of the caller and an unexpected error occurs, then the transaction is marked to roll back. If the exception is a declared exception, then the exception is resubmitted to the caller, and the transaction is left alone for the caller to commit or roll back.
If the method starts its own global transaction and any exception occurs, then the transaction is rolled back, and the exception is resubmitted to the caller.
Related tasks
Submitting a task to a scheduler