In a single server environment, it is clear which server instance
should invoke the ejbTimeout() method on a given bean. In a multi-server
clustered environment there are two possibilities.
- Separate timer service database per server process or cluster member.
This is the default configuration. Only the server instance or cluster member
that created the Timer can access the Timer and run the ejbTimeout() method.
If the server instance is unavailable, the Timer does not run at the specified
time, and does not run until the server is restarted. Also, if an enterprise
bean calls the findTimers() method, only those timers created on the
server instance are found. This can cause unexpected behavior if the enterprise
bean attempts to cancel all timers associated with it; for example, when the
enterprise bean is removed. This configuration is NOT recommended for production
level systems.
- Shared or common timer service database for the cluster. Timers can be
created and accessed on any server process or cluster member. Timers created
in one server process are found by the findTimers() method on other
server processes in the cluster. When an entity bean is removed, all timers,
no matter where created, are cancelled. However, all timers are executed on
a single server in the cluster, that is, the ejbTimeout() method is
run for all timers on a single server. Which server executes the timers varies
depending on which server process obtains a lock on the common database tables.
If the server executing timers becomes unavailable, then another server or
cluster member takes over and begins executing all timers at their scheduled
time. This is the recommended configuration for all production level systems.
- A note about deadlock and access intent: When using the EJB Timer
service in an application using multi-threaded database access, application
flow can introduce deadlock problems. To avoid this, use the wsPessimisticUpdate access intent. This
access intent causes the finder method in your application to run a select
for update statement instead of a generic select. This in turn prevents
the lock escalation deadlock when multiple threads try to escalate their locks
to perform an update.
See Configuring a Timer Service
for
information on how to configure the data source (database) to be used for
each server process timer service. Note that once the data source for the
timer service is changed to point to a different database, the server process
automatically attempts to create the required tables in that database on the
next server start. If the userid associated with the start of the server process
is not authorized to create database tables in the configured timer service
database, then the tables must be created manually. For more information,
see Creating scheduler tables
using DDL files.