Using the Timer Service

Applications that model business work flows often rely on timed notifications. The timer service of the enterprise bean container enables you to schedule timed notifications for all types of enterprise beans except for stateful session beans. You can schedule a timed notification to occur at a specific time, after a duration of time, or at timed intervals. For example, you could set timers to go off at 10:30 AM on May 23, in 30 days, or every 12 hours.

When a timer expires (goes off), the container calls the ejbTimeout method of the bean's implementation class. The ejbTimeout method contains the business logic that handles the timed event. Because ejbTimeout is defined by the javax.ejb.TimedObject interface, the bean class must implement TimedObject.

There are four interfaces in the javax.ejb package that are related to timers:

Creating Timers

To create a timer, the bean invokes one of the createTimer methods of the TimerService interface. (For details on the method signatures, see the TimerService API documentation.) When the bean invokes createTimer, the timer service begins to count down the timer duration.

The bean described in The TimerSessionBean Example creates a timer as follows:

TimerService timerService = context.getTimerService();
Timer timer = timerService.createTimer(intervalDuration,
  "created timer"); 

In the TimerSessionBean example, createTimer is invoked in a business method, which is called by a client. An entity bean can also create a timer in a business method. If you want to create a timer for each instance of an entity bean, you can code the createTimer call in the bean's ejbCreate method.

Timers are persistent. If the server is shut down (or even crashes), timers are saved and will become active again when the server is restarted. If a timer expires while the server is down, the container will call ejbTimeout when the server is restarted.

A timer for an entity bean is associated with the bean's identity--that is, with a particular instance of the bean. If an entity bean sets a timer in ejbCreate, for example, each bean instance will have its own timer. In contrast, stateless session and message-driven beans do not have unique timers for each instance.

The Date and long parameters of the createTimer methods represent time with the resolution of milliseconds. However, because the timer service is not intended for real-time applications, a callback to ejbTimeout might not occur with millisecond precision. The timer service is for business applications, which typically measure time in hours, days, or longer durations.

Canceling and Saving Timers

Timers can be canceled by the following events:

If a method is invoked on a canceled timer, the container throws the javax.ejb.NoSuchObjectLocalException.

To save a Timer object for future reference, invoke its getHandle method and store the TimerHandle object in a database. (A TimerHandle object is serializable.) To reinstantiate the Timer object, retrieve the handle from the database and invoke getTimer on the handle. A TimerHandle object cannot be passed as an argument of a method defined in a remote or web service interface. In other words, remote clients and web service clients cannot access a bean's TimerHandle object. Local clients, however, do not have this restriction.

Getting Timer Information

In addition to defining the cancel and getHandle methods, the Timer interface defines methods for obtaining information about timers:

public long getTimeRemaining();
public java.util.Date getNextTimeout();
public java.io.Serializable getInfo(); 

The getInfo method returns the object that was the last parameter of the createTimer invocation. For example, in the createTimer code snippet of the preceding section, this information parameter is a String object with the value created timer.

To retrieve all of a bean's active timers, call the getTimers method of the TimerService interface. The getTimers method returns a collection of Timer objects.

Transactions and Timers

An enterprise bean usually creates a timer within a transaction. If this transaction is rolled back, the timer creation is also rolled back. Similarly, if a bean cancels a timer within a transaction that gets rolled back, the timer cancellation is rolled back. In this case, the timer's duration is reset as if the cancellation had never occurred.

In beans that use container-managed transactions, the ejbTimeout method usually has the RequiresNew transaction attribute to preserve transaction integrity. With this attribute, the EJB container begins the new transaction before calling ejbTimeout. If the transaction is rolled back, the container will try to call ejbTimeout at least one more time.

The TimerSessionBean Example

The source code for this example is in the <INSTALL>/j2eetutorial14/examples/ejb/timersession/src/ directory.

TimerSessionBean is a stateless session bean that shows how to set a timer. The implementation class for TimerSessionBean is called TimerSessionBean. In the source code listing of TimerSessionBean that follows, note the myCreateTimer and ejbTimeout methods. Because it's a business method, myCreateTimer is defined in the bean's remote interface (TimerSession) and can be invoked by the client. In this example, the client invokes myCreateTimer with an interval duration of 30,000 milliseconds. The myCreateTimer method fetches a TimerService object from the bean's SessionContext. Then it creates a new timer by invoking the createTimer method of TimerService. Now that the timer is set, the EJB container will invoke the ejbTimer method of TimerSessionBean when the timer expires--in about 30 seconds. Here's the source code for the TimerSessionBean class:

import javax.ejb.*;

public class TimerSessionBean implements SessionBean,
    TimedObject {

    private SessionContext context;

    public TimerHandle myCreateTimer(long intervalDuration) {

        System.out.println
            ("TimerSessionBean: start createTimer ");
        TimerService timerService = 
            context.getTimerService();
        Timer timer = 
            timerService.createTimer(intervalDuration, 
          "created timer");
}

    public void ejbTimeout(Timer timer) {
  
        System.out.println("TimerSessionBean: ejbTimeout ");
    }

    public void setSessionContext(SessionContext sc) {
        System.out.println("TimerSessionBean:
            setSessionContext");
        context = sc;
     }

     public void ejbCreate() {
        System.out.println("TimerSessionBean: ejbCreate");
     }

     public TimerSessionBean() {}
     public void ejbRemove() {}
     public void ejbActivate() {}
     public void ejbPassivate() {}

}  

Building TimerSessionBean

In a terminal window, go to the <INSTALL>/j2eetutorial14/examples/ejb/timersession/ directory. To build TimerSessionBean, type the following command:

asant build 

Use deploytool to package and deploy this example.

Creating the Application

In this section, you'll create a J2EE application named TimerSessionApp, storing it in the file TimerSessionApp.ear.

  1. In deploytool, select FileRight ArrowNewRight ArrowApplication.
  2. Click Browse.
  3. In the file chooser, navigate to <INSTALL>/j2eetutorial14/examples/ejb/timersession/.
  4. In the File Name field, enter TimerSessionApp.ear.
  5. Click New Application.
  6. Click OK.
  7. Verify that the TimerSessonApp.ear file resides in <INSTALL>/j2eetutorial14/examples/ejb/timersession/.

Packaging the Enterprise Bean

Start the Edit Enterprise Bean wizard by selecting FileRight ArrowNewRight ArrowEnterprise JavaBean. The wizard displays the following dialog boxes.

  1. In the Introduction dialog box:
    1. Read the explanatory text for an overview of the wizard's features.
    2. Click Next.
  2. In the EJB JAR dialog box:
    1. Select the button labeled Create New JAR Module in Application.
    2. In the combo box below this button, select TimerSessionApp.
    3. In the JAR Display Name field, enter TimerSessionJAR.
    4. Click Edit Contents.
    5. In the tree under Available Files, locate the <INSTALL>/j2eetutorial14/examples/ejb/timersession/build/ directory.
    6. Select these classes: TimerSession.class, TimerSessionBean.class, and TimerSessionHome.class.
    7. Click Add.
    8. Click OK.
    9. Click Next.
  3. In the General dialog box:
    1. In the Enterprise Bean Class combo box, select TimerSessionBean.
    2. In the Enterprise Bean Name field, enter TimerSessionBean.
    3. Under Bean Type, select Stateless Session.
    4. In the Remote Interfaces section, select TimerSessionHome for the Remote Home Interface, and TimerSession for the Remote Interface.
    5. Click Next.
  4. In the Expose as Web Service Endpoint dialog box:
    1. Select No for Expose Bean as Web Service Endpoint.
    2. Click Next.
  5. Click Finish.

Compiling the Application Client

The application client files are compiled at the same time as the enterprise bean files.

Packaging the Application Client

To package an application client component, you run the New Application Client wizard of deploytool. During this process the wizard performs the following tasks.

To start the New Application Client wizard, select FileRight ArrowNewRight ArrowApplication Client. The wizard displays the following dialog boxes.

  1. Introduction dialog box
    1. Read the explanatory text for an overview of the wizard's features.
    2. Click Next.
  2. JAR File Contents dialog box
    1. Select the button labeled Create New AppClient Module in Application.
    2. In the combo box below this button, select TimerSessionApp.
    3. In the AppClient Display Name field, enter TimerSessionClient.
    4. Click Edit Contents.
    5. In the tree under Available Files, locate the <INSTALL>/j2eetutorial14/examples/ejb/timersession/build directory.
    6. Select the TimerSessionClient.class file.
    7. Click Add.
    8. Click OK.
    9. Click Next.
  3. General dialog box
    1. In the Main Class combo box, select TimerSessionClient.
    2. Click Next.
    3. Click Finish.

Specifying the Application Client's Enterprise Bean Reference

When it invokes the lookup method, the TimerSessionClient refers to the home of an enterprise bean:

Object objref =
  initial.lookup("java:comp/env/ejb/SimpleTimerSession"); 

You specify this reference as follows.

  1. In the tree, select TimerSessionClient.
  2. Select the EJB Ref's tab.
  3. Click Add.
  4. In the Coded Name field, enter ejb/SimpleTimerSession.
  5. In the EJB Type field, select Session.
  6. In the Interfaces field, select Remote.
  7. In the Home Interface field, enter TimerSessionHome.
  8. In the Local/Remote Interface field, enter TimerSession.
  9. In the JNDI Name field, select TimerSessionBean.
  10. Click OK.

Deploying the Enterprise Application

Now that the J2EE application contains the components, it is ready for deployment.

  1. Select TimerSessionApp.
  2. Select ToolsRight ArrowDeploy.
  3. Under Connection Settings, enter the user name and password for the Application Server.
  4. Under Application Client Stub Directory, check Return Client Jar.
  5. In the field below the checkbox, enter <INSTALL>/j2eetutorial14/examples/ejb/timersession/.
  6. Click OK.
  7. In the Distribute Module dialog box, click Close when the deployment completes.
  8. Verify the deployment.
    1. In the tree, expand the Servers node and select the host that is running the Application Server.
    2. In the Deployed Objects table, make sure that TimerSessionApp is listed and that its status is Running.
    3. Verify that TimerSessionAppClient.jar is in <INSTALL>/j2eetutorial14/examples/ejb/timersession/.

Running the Application Client

To run the application client, perform the following steps.

  1. In a terminal window, go to the <INSTALL>/j2eetutorial14/
    examples/ejb/timersession/
    directory.
  2. Type the following command:
  3. appclient -client TimerSessionAppClient.jar

  4. In the terminal window, the client displays these lines:
  5. Creating a timer with an interval duration of 30000 ms.

The output from the timer is sent to the server.log file located in the <J2EE_HOME>/domains/domain1/server/logs/ directory.

View the output in the Admin Console:

  1. Open the Admin Console by opening a web browser window to
  2. http://localhost:4848/asadmin/admingui

  3. Click the Logging tab.
  4. Click Open Log Viewer.
  5. At the top of the page, you'll see these four lines in the Message column:
  6. ejbTimeout
    start createTimer
    ejbCreate
    setSessionContext

Alternatively, you can look at the log file directly. After about 30 seconds, open server.log in a text editor and you will see the following lines:

TimerSessionBean: setSessionContext
TimerSessionBean: ejbCreate
TimerSessionBean: start createTimer
TimerSessionBean: ejbTimeout