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.
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.
Important: 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 Java Database Connectivity (JDBC) datasource
that is configured for the scheduler, any Java Messaging Service (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 administrative console. See the Last participant support extension
settings topic for details.
All unexpected exceptions are logged to the activity log and all
events participating in the task global transaction are rolled back. This
includes changes to the task 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.