Most non-trivial applications require at least some asynchronous processing but direct use of the thread library is not allowed in a JEE container environment. To get around this limitation EJB 2.1 introduced a timer service which, although functional, wasn’t very feature rich. This has finally been fixed in EJB 3.1 which brings a new, annotation driven, timer service to allow asynchronous processing. The new EJB 3.1 timer service takes it’s inspiration from the familiar Unix cron service so it should be familiar to a large number of people.
The EJB timer service is fully managed by the container and simply requires that EJBs that want a callback register themselves with the service. Callbacks can be requested based on a calendar, at a specific time, after a given duration or at a recurring interval. Timers are designed for use on long-lived business processes and so by default they are persisted by the container at shutdown. When the container restarts the timers are fired as if the container had been running the whole time. Alternatively it’s possible to make non-persistent timers if needed. Timers can either be created automatically by the container at deployment, via annotation, or programmatically at runtime also by annotation.
Worlds Simplest Timer
This is the simplest (and most pointless) possible timer that can work:
package example.simpleproject.timerservice; import java.util.Date; import javax.ejb.Schedule; import javax.ejb.Singleton; @Singleton public class SimplestTimer { @Schedule( minute="*", hour="*" ) public void doWork() { System.out.println( "Beep " + new Date() ); } }
While not interesting from the point of view of what it does it is does show everything that is needed to get a timer running. The only modification that was required to convert this simple singleton bean into a timer was the @Schedule annotation. In this case the annotation tells the timer service to call the doWork method every minute of every hour. Since we haven’t said otherwise this is a persistent schedule so stopping the server, waiting a short while and then restarting it will result in the timer firing immediately. If you watch the output you’ll notice that the timer fires as soon as possible after the expiry of the timer.
Although this timer is fully self contained there is no requirement for that to be the case. Since this is an EJB it can make use of all the facilities available to any other EJB such as resource injection which allows for more complex asynchronous processing. Timers also don’t have to be singletons they can also be stateless beans – they can not, however, be stateful beans.
The scheduling annotation shown in the above example is about as simple as it gets but it can be much more complex. It is perfectly possible to schedule the method to be called every 7th and 31st second of the 4 hour of the third day of each month for example. If that doesn’t provide enough flexibility on it’s own you can combine multiple @Schedule annotations in an @Schedules annotation.
The table below shows the various attributes available to use in @Schedule annotation and their default value if not explicitly specified.
Attribute | Description | Default Value | Allowable Values and Examples |
---|---|---|---|
second | One or more seconds within a minute | 0 | 0 to 59. For example: second="30". |
minute | One or more minutes within an hour | 0 | 0 to 59. For example: minute="15". |
hour | One or more hours within a day | 0 | 0 to 23. For example: hour="13". |
dayOfWeek | One or more days within a week | * | 0 to 7 (both 0 and 7 refer to Sunday). For example: dayOfWeek="3".
Sun, Mon, Tue, Wed, Thu, Fri, Sat. For example: dayOfWeek="Mon". |
dayOfMonth | One or more days within a month | * | 1 to 31. For example: dayOfMonth="15".
–7 to –1 (a negative number means the nth day or days before the end of the month). For example: dayOfMonth="–3". Last. For example: dayOfMonth="Last". [1st, 2nd, 3rd, 4th, 5th, Last] [Sun, Mon, Tue, Wed, Thu, Fri, Sat]. For example: dayOfMonth="2nd Fri". |
month | One or more months within a year | * | 1 to 12. For example: month="7".
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec. For example: month="July". |
year | A particular calendar year | * | A four–digit calendar year. For example: year="2011". |
Programmatic Timers
Programmatic timers are, as the name suggests, created programmatically at runtime. In order to create a progremmatic timer the EJB needs access to the javax.ejb.TimerService through either injection, and EJBContext call or via JNDI lookup (injection is by far the simplest method).