Configuring the enterprise JavaBeans timer service for persistent timers

You can configure the EJB timer service to control the persistent timer data source, failover enablement, missed timer actions, polling intervals, and the number of and interval between timeout callback retries.

About this task

When the ejbPersistentTimer feature is enabled, a data source must be configured to persist the timers or any attempt to use persistent timers fails. The EJB timer service uses the configured DefaultDataSource data source unless another data source is configured for use by the EJB timer service.

The EJB timer service retries failed calls to the timeout callback method for persistent timers every 5 minutes until the timeout callback method completes successfully.

Use the following options to configure persistent timers:

EJB Persistent Timers Scheduled Executor

Specifies a reference to a persistent executor that controls the behavior of persistent timers. A default instance, defaultEJBPersistentTimerExecutor, is provided which uses the DefaultDataSource as the persistent store. The EJB persistent timers scheduled executor reference might be changed to a custom configuration, or the default instance might be overridden to change specific values. The following options are available for the persistent executor:

Missed task threshold
Enables failover of persistent EJB timers by defining the maximum amount of time to allow for successful completion of a timer execution attempt on a server. If this time elapses without a successful completion, another server is allowed to take over and run the timer instead. Before a timer runs, the server that runs it writes a claim into the database for an amount of time equal to the missed task threshold. If this time elapses without successful execution of the timer, or if the timer rolls back and relinquishes the remaining time, then another server can attempt to run the timer. This cycle continues until a server is able to successfully run the timer in the specified amount of time or until the retry limit is reached. The default value of -1 indicates that failover is not enabled. When multiple servers are pointing at the same database tables for EJB persistent timers, failover must be configured in the same way for all servers. It is possible to switch existing timers from disabled to enabled. However, do not switch existing timers from enabled to disabled because servers that do not enable failover are unable to run those timers.
Poll interval
Specifies the interval at which to check the database for timers to run. When failover is disabled, polling is often unnecessary, and is disabled by default. When failover is enabled, polling is automatically computed by default so that the server can use the database to coordinate with other servers that are participating in failover. The default algorithm can result in some missed polls, especially when the number of servers that are participating in failover changes. If you prefer to have more control over polling, you can explicitly configure the poll interval to establish a poll interval for each server. For example, you can manually tune the poll interval based on the number of servers that are participating in failover. With more servers, you might desire less frequent polling per server. A value of -1 explicitly disables polling by a server.
Retry limit

Specifies the maximum number of times that the failing timeout callback method might be retried. If the timeout callback method is successful upon retry, the server stops attempting to run it. If a retry fails, the server continues to attempt retries until the timeout callback method succeeds, or the retry limit is reached. After the retry limit is reached, the server does not attempt to run the timeout callback method, even if prior attempts did not succeed. The default value of -1 indicates unlimited retries. A value of 0 indicates no retries, and is not compliant with the EJB specification. A value of 1 or greater indicates the specific number of retries.

Changing the number of times a timeout callback method is retried can be useful for applications that do not require non-persistent timers to complete at each of the scheduled times. For example, configuring a non-persistent interval timer to run every 5 minutes with zero retries causes the timer to run once every 5 minutes, regardless of whether it succeeds or fails.

Retry interval

Specifies the interval between retry attempts on the same server for a failed timeout callback method. Retry interval is only valid when failover is disabled. When failover is disabled, the first retry always occurs immediately, regardless of the interval that is configured for this value. All additional retries wait for the interval that is specified for this value. A value of 0 indicates that all retries are immediate. A value of 1 or greater indicates that retries must wait for that specific number of seconds. When failover is disabled, the default is 300 seconds. When failover is enabled, retry interval is not valid because retries happen naturally as servers reach their next poll.

Configuring a different time interval between retries for non-persistent timers is useful for applications where it is important for the timeout callback method to complete before the scheduled time. This approach is also applicable to delay the timer completion to enable the timeout callback method and give the application a better chance to run successfully.

Persistent Task Store

Specifies which data source is used. A default instance is provided called, defaultDatabaseStore, which uses the DefaultDataSource data source as the persistent store.

Missed persistent timer action
Specifies the action to take when the expiration of an interval or schedule-based persistent timer is missed. One or more expirations of a persistent timer are classified as missed if the current expiration is scheduled before application server start or the next expiration is scheduled before the current time. The configurable actions are:
ALL
The timeout method is invoked immediately for all missed expirations. When multiple expirations are missed for the same timer, each invocation occurs synchronously until all missed expirations are processed, then the timer resumes with the next future expiration.
ONCE
The timeout method is invoked once immediately. All other missed expirations are skipped and the timer resumes with the next future expiration.

For example, if a persistent timer is scheduled to expire every 30 seconds, and the server is down for 20 minutes, then 40 expirations are missed during those 20 minutes. When the ALL action is configured, the timer runs 40 times immediately on server start to catch up on all the missed expirations and then continues at the next 30-second interval. When the ONCE action is configured, the timer runs once on server start to catch up on all the missed expirations and then resumes at the next scheduled 30-second interval.

When failover of persistent timers is enabled, the default action is ONCE. If failover is not enabled, the default action is ALL.

Procedure

  1. Configure the application server to include an EJB feature that supports persistent timers in the server.xml file:
     <featureManager>
             <feature>ejbPersistentTimer-3.2</feature>
        </featureManager>
  2. Enable failover for EJB persistent timers in the server.xml file.
    For example, use the following configuration to specify that persistent timers take at most 5 minutes to run, after which they are considered missed and eligible for another server to take over:
    <persistentExecutor id="defaultEJBPersistentTimerExecutor" missedTaskThreshold="5m"
              pollInterval="20m"/>

    With this configuration, the timeout callback method for a timer takes at most 5 minutes. After that point, the timer is considered missed and another server can try to run it. The poll interval of 20 minutes indicates that this server checks the database every 20 minutes for timers to run. If two other servers also configure a 20-minute poll interval for this database, then the database is polled around three times total in a given 20-minute period.

  3. Configure the EJB timer service to use a specific maximum number of retry values and retry interval values for persistent timers in the server.xml file.
    For example, use the following configuration to specify that the persistent timers retry up to three times, with 10 seconds between retries:
    <persistentExecutor id="defaultEJBPersistentTimerExecutor" retryInterval="10s"
              retryLimit="3"/>

    With this configuration, the timeout callback method for a timer can be called up to four times. The first call occurs at the scheduled time. If the first call fails, then the first retry occurs immediately after the failure. If the timeout callback method continues to fail, then the second and third retries occur 10 and 20 seconds later.

    In the following example, a failed timeout callback method is only retried one time. The callback interval is irrelevant because the first retry is always started immediately when failover is disabled.

    <persistentExecutor id="defaultEJBPersistentTimerExecutor" retryLimit="1"/>
  4. Configure the EJB timer service to use a specific data source for persistent timers in the server.xml file.
    For example, use the following configuration to specify that the persistent timers must be stored by using the jdbc/timerDataSource:
    <dataSource id="timerDataSource" jndiName="jdbc/timerDataSource">
    </dataSource>
    <databaseStore id="EJBTimerDatabaseStore" tablePrefix="EJBTimer_" dataSourceRef="timerDataSource"/>
    <persistentExecutor id="defaultEJBPersistentTimerExecutor"
              taskStoreRef="EJBTimerDatabaseStore"/>
  5. Configure the missed timer action for the EJB timer service in the server.xml file.
    For example, use the following configuration to specify that, for multiple missed expirations, the timeout method is invoked only once immediately at server start and the timer resumes with the next future expiration:
    <ejbContainer>
    <timerService missedPersistentTimerAction="ONCE"/>
    </ejbContainer>

    With this configuration, if a persistent timer is scheduled to expire every 30 seconds, and the server is down for 20 minutes, then 40 expirations are missed during those 20 minutes. However, the timer runs just once on server start to catch up on all the missed expirations and then resumes at the next scheduled 30-second interval.

  6. Optional: Control table creation.
    1. Configure the databaseStore element that is associated with the EJB persistent timer so that it does not create the necessary tables automatically.
      The following example shows the default databaseStore element:
      <databaseStore id="defaultDatabaseStore" createTables="false"></databaseStore>

      You can also control the table prefix or schema by setting these attributes on the databaseStore element.

    2. Export the Data Definition Language (DDL) for the EJBPersistentTimer tables with the ddlGen command-line utility as shown in the following example:
      ddlGen generate server
    3. Using a user account with proper permissions, import the DDL into your database.
      The DDL resembles the following example:
      CREATE TABLE WLPPART (ID BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, EXECUTOR VARCHAR(100) NOT NULL, EXPIRY BIGINT NOT NULL, HOSTNAME VARCHAR(100) NOT NULL, LSERVER VARCHAR(100) NOT NULL, STATES BIGINT NOT NULL, USERDIR VARCHAR(254) NOT NULL, PRIMARY KEY (ID)) CREATE TABLE WLPTASK (ID BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, INAME VARCHAR(254) NOT NULL, LOADER VARCHAR(254) NOT NULL, MBITS SMALLINT NOT NULL, NEXTEXEC BIGINT NOT NULL, ORIGSUBMT BIGINT NOT NULL, OWNR VARCHAR(120) NOT NULL, PARTN BIGINT NOT NULL, PREVSCHED BIGINT, PREVSTART BIGINT, PREVSTOP BIGINT, RESLT BLOB(2147483647), RFAILS SMALLINT NOT NULL, STATES SMALLINT NOT NULL, TASKB BLOB(2147483647), TASKINFO BLOB(2147483647) NOT NULL, TRIG BLOB(2147483647), TXTIMEOUT INTEGER NOT NULL, VERSION INTEGER NOT NULL, PRIMARY KEY (ID)) CREATE TABLE WLPPROP (ID VARCHAR(254) NOT NULL, VAL VARCHAR(254) NOT NULL, PRIMARY KEY (ID)) ALTER TABLE WLPPART ADD CONSTRAINT UNQ_WLPPART_0 UNIQUE (EXECUTOR, HOSTNAME, LSERVER, USERDIR)