Schedulers & Timers
EJBs have had support for programmatic timers since version 2.1. This was made possible by use of a combination of javax.ejb.TimerService
interface along with the @Timeout
annotation (which will be covered later). The @Schedule
and @Schedules
annotations were added in EJB 3.1. Let's look at how these annotations have made working with timers much more easier.
@Schedule
@Schedule
This annotation is used to designate a method as a target for a timed call back i.e. the EJB container invokes this method as per configuration/metadata provided in this annotation.
package ejbap.schedule;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.ejb.Timer;
@Stateless
public class ScheduledReportingService {
@Schedule
public void generateAuditReport(){
System.out.println("Generating audit report....");
}
/**
* A Timer instance is injected
* automatically by the container
*/
@Schedule
public void generateSalesReport(Timer timer){
System.out.println("Generating Sales report....");
System.out.println("Next execution on - "+ timer.getNextTimeout());
}
}
Please note that, in the above example, the
@Schedule
annotation is not configured with the schedule frequency. In such a scenario, the EJB container invokes (by default) the annotated method on a daily basis (at midnight)
@Schedule
exposes a powerful cron-like syntax which provides a number of permutations and combinations are available as far the scheduling configurations are concerned. The syntax is so rich that it is not possible to enumerate all the possible combinations. Here are a few selective examples
package ejbap.schedule;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
@Stateless
public class SchedulerConfigurationExamples {
//Jan 1 (year on year)
@Schedule(second="0", minute="0", hour="0",
dayOfMonth="1", month="Jan", dayOfWeek="*",
year="*")
public void sendNewYearGreetings(){
//logic
}
//every 10 minutes
@Schedule(minute="*/10", hour="*")
public void dbHealthCheck(){
//logic
}
//every friday (midnight)
@Schedule(dayOfWeek="Fri")
public void timesheetReport(){
//logic
}
}
@Schedules
@Schedules
This annotation is to be used when you want to impose/declare multiple timers scheduling options to single method. All it does it accept multiple (an array) of @Schedule
annotations
package ejbap.schedule;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Stateless;
@Stateless
public class MultipleSchedules {
@Schedules({
//1 AM on Monday
@Schedule(hour="1", dayOfWeek="Mon"),
//2:30 AM on Friday
@Schedule(hour="2", minute = "30", dayOfWeek="Fri")
})
public void generateAuditReport(){
System.out.println("Generating audit report....");
}
}
This is useful if you do not want to declare different methods for different timer configurations (although it's perfectly legal to do so)
Timer persistence
Timers are persistent by default i.e. their state is persisted in case the application terminates. One can toggle this using the persistent property in the
@Schedule
annotation
@Timeout
@Timeout
This annotation is useful when you want to adopt a programmatic way of working with timers rather than configuring them in declarative fashion using the annotations mentioned above. @Timeout
is used a marker for the EJB container to be able to determine the trigger point which can be invoked when the timer expires. The method annotated with @Timeout
contains the actual logic which you want to execute as part of your scheduled operation
If you compare this with @Schedule
, the major difference you would notice is that @Timeout
does not allow declarative configuration via annotation elements
package ejbap.schedule;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
@Stateless
public class SimpleProgrammaticTimer {
@Resource
private TimerService ejbTimerSvc;
public void trigger(Event event){
TimerConfig configuration = new TimerConfig(event.detail, true);
Timer timer = ejbTimerSvc.createSingleActionTimer(10000, configuration);
System.out.println("Single action timer " + timer.toString() +" created");
}
@Timeout
public void onTimeout(Timer timer){
System.out.println("Event details: "+ timer.getInfo());
}
private static class Event {
private String detail;
public Event(String detail) {
this.detail = detail;
}
}
}
Since this annotation does not allow timer/scheduler configuration, it is used in conjunction with the javax.ejb.TimerService
API which helps you create timers on the fly. It's helper method let you specify the timers in terms of duration, exact trigger date etc. as well as ad-hoc schedules (similar to what @Schedule
offers) using the javax.ejb.ScheduleExpression
class
package ejbap.schedule;
import javax.annotation.Resource;
import javax.ejb.ScheduleExpression;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
@Stateless
public class CalendarBasedProgrammaticTimer {
@Resource
private TimerService ejbTimerService;
public void trigger() {
ScheduleExpression schedule = new ScheduleExpression();
schedule.dayOfMonth("1");//fist day of every month
Timer timer = ejbTimerService.createCalendarTimer(schedule);
System.out.println("Calendar based programmatic timer "
+ timer.toString() + " created");
}
@Timeout
public void onTimeout(Timer timer) {
System.out.println("Timer schedule: " + timer.getSchedule());
}
}
What's next ??
Next, we'll look at EJBs in their Web Service avatar !
Last updated
Was this helpful?