Introduction
Timer service is a JEE utility that can be used to schedule notifications in enterprise applications. In other words, In case you need to run an action on a specific time in future (i.e. 10/10/2015 – assuming current date is 10/10/2014), or you need to repeat an action every specific amount of time (i.e. every 10 minutes) then the timer service is the utility that you need.
JEE7 provides 2 types of timers, programmatic timers and automatic timers.
Programmatic Timers
Programmatic timers are the timers that are initiated by the application code itself on a specific action, in other words, you have to code some lines to start the timer when you need to (i.e. when the user clicks the start timer button, the timer should start immediately).
package com.ejb3.timer; import javax.annotation.Resource; import javax.ejb.ScheduleExpression; import javax.ejb.Singleton; import javax.ejb.Timeout; import javax.ejb.TimerService; @Singleton public class ProgTimer { @Resource private TimerService timerService; @Timeout public void timeOut() { System.out.println("Method Invoked"); } public void initTimer() { System.out.println("INIT-CALLED"); ScheduleExpression exp = new ScheduleExpression(); exp.hour("*").minute("*").second("*/4"); timerService.createCalendarTimer(exp); } }
The above example creates a timer bean that when initialized, the timeOut method will be invoked every 4 seconds. The method initTimer can be invoked from a Servlet or another EJB object. You can also make the timer start automatically using the @Startup and @PostConstruct annotations, the @Startup for the bean and @PostConstruct for the initTimer method, like the following:
package com.ejb3.timer; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.ejb.ScheduleExpression; import javax.ejb.Singleton; import javax.ejb.Startup; import javax.ejb.Timeout; import javax.ejb.TimerService; @Singleton @Startup public class ProgTimer { @Resource private TimerService timerService; @Timeout public void timeOut() { System.out.println("Method Invoked"); } @PostConstruct public void initTimer() { System.out.println("INIT-CALLED"); ScheduleExpression exp = new ScheduleExpression(); exp.hour("*").minute("*").second("*/4"); timerService.createCalendarTimer(exp); } }
Automatic Timers
Automatic timers are the timers that are initiated by the EJB container due to the deployment of beans that are marked with @Schedule/@Schedules annotations. The above example can be converted to automatic timer as shown below:
package com.ejb3.timer; import javax.ejb.Schedule; import javax.ejb.Singleton; @Singleton public class AutoTimer { @Schedule(hour="*", minute="*", second="*/4") public void timeOut() { System.out.println("Method Invoked"); } }
This will give the same effect of invoking the method timerOut every 4 seconds. Just a note - when trying to deploy timers on JBOSS, sometimes you may face issues due to caching old timers. To handle this, you will need to stop JBOSS, delete the tmp and data directory, then start JBOSS again.
Timers Scheduling Expressions
Scheduling expressions are the expressions used to configure the timer running intervals (i.e. every minute, every 10 seconds, day number 5 in each month…etc.), the expression syntax is similar to the UNIX Cron utility
The available attributes in the expressions are second, minute, hour, dayOfWeek, dayOfMonth, month, year
The expression attributes can be fixed values (i.e. 1, 20, 30), range (i.e. 9-7, 1-7, 40-50), multiple values (i.e. “10, 20-30, 50”), interval (i.e. minute=”30/2”, this means every 2 seconds in the second half of the minute) or wildcard expression (i.e. minute=”*”, this will mean every minute, second=”*/4”, this will mean every 4 seconds)
Examples:
- Second=”*”, minute=”*”, Hour=”*”, execute the timer every second
- Second=”*/10”, minute=”*”, Hour=”*”, execute the timer every 10 second
- Second=”30/10”, minute=”*”, Hour=”*”, execute the timer every 10 second from the 2nd half of the minute
- dayOfMonth=”1”, month=”*”, execute the timer on the first day of every month
- dayOfWeek=”Fri”, execute the timer every friday
Canceling Timers
Canceling a timer can be done using 2 ways, calling the cancel method on a Timer object that is passed to a timeout (@Schedule) method, or calling the getTimers method of a TimerService object and then calling the cancel method.
package com.ejb3.timer; import javax.annotation.Resource; import javax.ejb.Schedule; import javax.ejb.Singleton; import javax.ejb.Timer; import javax.ejb.TimerService; @Singleton public class AutoTimer { @Resource private TimerService timerService; @Schedule(hour="*", minute="*", second="*/4") public void timeOut(Timer timer) { System.out.println("Method Invoked"); stopTimers(); // or just timer.cancel(); } public void stopTimers() { for(Timer timer : timerService.getTimers()) timer.cancel(); } }
Transaction Rollback Effect
Creating a Timer inside a transaction causes the timer creation to rollback in case the transaction is rolled back, and also the timer canceling will be rolled back in case the transaction that the cancel method is called inside, is rolled back.
@Timeout annotation has the same effect of using the transaction attribute value of Required or RequiresNew when using container managed transactions. This means that a transaction will always exist during the execution of the timer timeout method. In case of errors and that transaction should rollback, the container will cause the timeout method to be fired one more time.