+

Search Tips   |   Advanced Search

Create timers using the EJB timer service for enterprise beans

Use enterprise beans to take advantage of the EJB timer service to schedule time-based events.

In support of the EJB 3.1 specification, we can create non-persistent EJB timers. This product also supports the expanded TimerService API for programmatic timer creation. In addition, you can configure the EJB container to automatically create a timer when the application starts.

WebSphere Application Server implements the Enterprise JavaBeans(EJB) timer service. Based on the business needs, we can use persistent timers or non-persistent timers. Persistent timers are helpful if we are creating a timer for a time-based event that requires assurance of timer existence beyond the life cycle of the server. Previously started persistent timers automatically start when the server starts and persist through server shutdowns and restarts. For example, you can use persistent timers to start a system application or send a status notification on the expiration of a timer. Non-persistent timers are helpful in non-critical situations where the timer actions are skipped or redone without negative business impacts, such as polling a temperature.

Create timers programmatically. We can also create timers automatically using the @Schedule annotation in the bean class, or using the timer element in the ejb-jar.xml deployment descriptor. By automatically creating timers, we can schedule a timer without relying on your enterprise bean invocation to programmatically start an EJB timer service creation method.

Persistent timers

Persistent timers are implemented as a scheduler service task. By default, an internal or pre-configured scheduler instance is used to manage those tasks, and they persist in an Apache Derby database associated with the server process.

We can perform basic customizations to the internal scheduler instance. For information about customizing the scheduler instance, see the configuring a timer service information.

The creation and cancellation of Timers is transactional and persistent. If a Timer is created within a transaction and that transaction is later rolled back, the creation of the Timer is rolled back as well. Similar rules apply to the cancellation of a Timer. Previously started Timers are maintained across application server shutdowns and restarts.

Non-persistent timers

EJB 3.1 augments the EJB timer service to enable non-persistent EJB timers in addition to the persistent timers. Non-persistent timers have many of the same semantics and behavior as persistent timers, but without the overhead of a data store. Non-persistent timers have a different life cycle than persistent timers. Where persistent timers are maintained across application server shutdowns and restarts, non-persistent timers are active only while the application server is active. Unlike persistent timers, there are no commands to find or cancel non-persistent timers. Non-persistent timers are canceled when the application server is stopped or fails to remain in an active state.

As with persistent timers, the creation and cancellation of non-persistent timers is transactional. If a timer is created within a transaction and that transaction is later rolled back, the creation of the timer is rolled back as well. Similar rules apply to the cancellation of a timer.

We can configure non-persistent timers to share a thread pool with persistent timers, or to have a unique thread pool that is not shared with persistent timers.

Programmatically created timers

A programmatically created persistent timer is maintained across application server shutdowns and restarts, unless it is canceled. It is the responsibility of application code or system administrator to delete a programmatically created timer which is no longer wanted.

To programmatically create a timer associated with your enterprise bean, the bean calls the getTimerService() method on the applicable context instance to get a reference to the TimerService object. The bean also calls one of the TimerService methods, such as createTimer, to specify the timer for the bean. This Timer instance is now associated with your bean. The TimerService methods are described in the EJB 3.1 specification. We can now pass the Timer instance to other Java code as a local object. After the Java code obtains the Timer instance, the code can use any of the methods defined by the javax.ejb.Timer interface, such as the cancel() or getTimeRemaining() methods.

In a clustered environment, a programmatically created persistent timer can run in any cluster member, but a programmatically created non-persistent timer runs only in the same JVM in which it was created.

Automatically created timers

The EJB 3.1 specification augments the EJB timer service to enable the automatic creation of a timer when the application starts without relying on a bean invocation to programmatically start one of the timer service timer creation methods. Use the @Schedule annotation or the timeout-method deployment descriptor element to automatically create timers. Automatically created timers are created by the container as a result of application deployment.

The CancelEJBTimers command also cancels automatically created timers. When automatically created timers are canceled, the only way to recreate them is to uninstall the application and reinstall it again.

Timers in a clustered environment

In a clustered environment, a persistent timer runs only in one cluster member which might not necessarily be the same cluster member it was created in. A non-persistent timer runs in each cluster member that it was created in - automatic non-persistent timers run in each cluster member containing the EJB.

Automatic persistent timers are removed from their persistent store when their containing module or application is uninstalled. Therefore, do not update applications that use automatic persistent timers with the Rollout Update feature. Doing so uninstalls and reinstalls the application while the cluster is still operational, which might cause failure in the following cases:

  • If a timer running in another cluster member activates after the database entry is removed and before the database entry is recreated, then the timer fails. In this case, a com.ibm.websphere.scheduler.TaskPending exception is written to the First Failure Data Capture (FFDC), along with the SCHD0057W message, indicating that the task information in the database has been changed or canceled.

  • If the timer activates on a cluster member with not been updated after the timer data in the database has been updated, then the timer might fail or cause other failures if the new timer information is not compatible with the old application code still running in the cluster member.

When we use the proxy server in the product, do not define a scheduler at the cell level if that scheduler is configured as the one to use for the EJB timer service. Doing so prevents persistent timers from running. This can happen if the proxy server gets the scheduler lease. Since no applications run in the proxy server, there is no application code to handle the timer events sent by the scheduler.

Retries and missed timeouts

If we use EJB timers, we must understand the concepts of failure, retry, and missed timeouts.

  • A failure is a timeout execution that is attempted, but does not succeed.
  • A retry is an additional attempt to successfully execute a timeout that was previously attempted, but failed.
  • A missed execution is a timeout that must have been attempted, but was not, because the server was unavailable or busy retrying a previously failed timeout.

The retry behavior reflects:

  • Number of additional times that the server retries the failed timeout
  • Interval between these server retries

The missed timeout behavior reflects:

  • Whether the server eventually attempts missed timeouts, or not

  • If missed timeouts are eventually attempted, when those attempts occur
  • Interval between the missed timeout attempts

Characteristic Default behavior Configurable
Number of retry attempts As many as it takes to succeed.

Persistent timers are temporarily deactivated if their scheduler failure threshold is reached in a server. See topic about stopping tasks that are failing.

Yes, for non-persistent timers
Interval between retry attempts First retry attempt is immediate.

Subsequent retry attempts occur on the configured scheduler poll interval for persistent timers, and on the configured retry interval for non-persistent timers.

Yes
Missed timeout recovery All missed timeouts are recovered. No
When missed timeouts are recovered Both persistent and non-persistent timers recover missed timeouts when the blocking retry attempts stop. Additionally, persistent timers recover timeouts when an unavailable server restarts. No
Next timeout, after retry attempts are successful and missed timeouts are recovered At the next originally scheduled time. No

The configurable characteristics are configured on the scheduler instance for persistent timers and on the non-persistent timer configuration for non-persistent timers.

The following scenarios illustrate how the retry and missed timeout behavior influences the timeouts for both persistent and non-persistent timers.

Persistent timer scenario:

A persistent timer is created and configured to run for the first time at 10:00 am, and then run every hour after that. The scheduler supporting the timer is configured with a 30 second poll interval.

The timer runs at 10:00 am and fails because a database is unavailable. The timer is immediately retried, and retried again every 30 seconds when the scheduler is polled, and keeps failing, until 12:30 pm. At that moment, a retry attempt succeeds because the database is now back online, and therefore the server stops retrying the previously failed attempt.

Now, the server begins to work through the missed timeouts. First, it attempts the timeout that must have run at 11:00 am, which succeeds at 12:31 pm. When the scheduler is polled again 30 seconds later, it attempts the timeout that must have run at 12:00 pm, which succeeds at 12:32 pm. The server is now current, and the next timeout occurs at its originally scheduled time of 1:00 pm, as opposed to an hour after the last success, which would have been 1:32 pm. Going forward, the original schedule is maintained. The schedule is not updated based on the time of the last successful timeout.

Non-persistent timer scenario:

A non-persistent timer is created and configured to run for the first time at 10:00 am, and then run every hour after that. This non-persistent timer is configured to have a retry count of 5, and a retry interval of 30 minutes.

The timer runs at 10:00 am and fails because a database is not available. The timer is immediately retried, and fails again. Now, having executed the initial immediate retry, the server waits for the configured retry interval of 30 minutes between the next retry attempt. Retry attempts occur at 10:30 am and 11:00 am, and both fail. Finally, the fourth retry occurs at 11:30 am, and succeeds because the database is now back online.

Now, the server begins to work through the missed timeouts. The timeout that was originally scheduled for 11:00 am is immediately run, and succeeds at 11:31 am. The server is now current, and the next timeout occurs at its originally scheduled time of 12:00 pm (as opposed to an hour after the last success, which would be 12:32 pm).

Behavior of the getNextTimeout and getTimeRemaining methods

For both persistent and non-persistent timers, the Timer.getNextTimeout method returns a java.util.Date object that indicates the next time the timer is scheduled to execute. When you call the getNextTimeout method from a timeout callback method for an interval or calendar-based timer, the method returns the next scheduled time; for calendar-based timers with no future timeouts, the method throws the NoMoreTimeoutsException exception as required by the EJB 3.1 specification. When we call the getNextTimeout method from a timeout callback method for a single-action timer, the method returns the originally scheduled time. If a timeout callback method fails and retries are being attempted, the getNextTimeout method continues to return the originally scheduled time as if the failed execution had not occurred. In all cases, the Timer.getTimeRemaining method returns the difference in milliseconds between the getNextTimeout returned value and the current system time, which could result in a negative number, if the scheduled execution time was in the past.

Inheritance behavior of automatically created timers

Automatic timer methods in a hierarchy of bean classes cause multiple timers to be created. The number of timers associated with a timer method is not determined by the number of occurrences of the method in the source code. Instead, the number of timers associated with a timer method is determined by the number of beans with visibility to that method. For example:

@Stateless
public class Abean {

   @Schedule(hour="1")
   public void timerMethod1()


@Stateless
public class Bbean extends Abean {

   @Schedule(hour="2")
   public void timerMethod2()


@Stateless
public class Cbean extends Bbean {

   @Schedule(hour="2")
   public void timerMethod2()

In the previous bean class hierarchy, three automatic timers with callback method Abean.timerMethod1 are created, one for each bean instance with visibility to that method. One timer with callback method Bbean.timerMethod2 is created, and since that method is overridden by bean Cbean, only one timer with callback method Cbean.timerMethod2 is created.

In the previous example, when bean Abean is processed by the container, a single automatic timer is created, with callback method Abean.timerMethod1.

When the bean Bbean is processed by the container, an automatic timer is created with callback method Bbean.timerMethod2, and another automatic timer is created with callback method Abean.timerMethod1.

When the bean Cbean is processed by the container, an automatic timer is created with callback method CBean.timerMethod2. Another automatic timer is created with callback method Abean.timerMethod1. A timer for Bbean.timerMethod2 is not created when processing the bean Cbean. Bbean.timerMethod2 is not visible in the class hierarchy of Cbean because it is overridden by method Cbean.timerMethod2.

Consider another example like the previous one, if the @Stateless annotation were removed from classes Abean and Bbean, so that class Cbean is the only EJB. In that case, the only automatic timers created would be those visible to Cbean - one with callback method Abean.timerMethod1, one with callback method Cbean.timerMethod2.

Although beans can share identical code in an inherited bean callback method, the runtime behavior might be polymorphic. For example:

public class Employee {

   @Schedule(hour="1", dayOfMonth="-1", info = "payroll timer")
   public void getSalaryIncrease() {
      printChecks(salary * rate());
   }

   protected float rate() {
      return (float)1.01;
   }

}

public class Manager extends Employee {

   protected float rate() {
      return (float)1.15;
   }

}

public class Executive extends Manager {

   protected float rate() {
      return (float)1.30;
   }

}

In the previous example, each bean instance has an automatic timer with callback method getSalaryIncrease(). Although the same callback code is shared by each timer, note that the rate used in calculating the salary increase by each bean is different, due to polymorphism. That is, timer callback methods might be polymorphic in the same way any Java methods might be.


Tasks

We have programmatically or automatically configured an EJB timer that is either persistent or non-persistent.


Subtopics

  • Configure a timer service
  • Deploy EJB modules
  • Use schedulers
  • Stopping tasks that are failing
  • Configure the timer service using scripting
  • CancelEJBTimers command example
  • EJB metadata annotations
  • Example: Using the Timer Service with the TimedObject interface
  • EJB command group
  • EJB timer service settings