2
votes

JSR-000318 spec defines the TimerService (chapter 18).

Given an EJB, you can create an automatic timer or a programmatic timer.

An automatic timer looks like this

@Schedules(
{
  @Schedule(hour=”12”, dayOfWeek=”Mon-Thu”),
  @Schedule(hour=”11”, dayOfWeek=”Fri”)
})
public void sendLunchNotification() { ... }

While a programmatic timer looks like this

@Resource
private TimerService timerService;

void someMethod(){
   ScheduleExpression exp = new ScheduleExpression();
   (... set exp ...)
   TimerConfig config = new TimerConfig();
   (... set config ...)
   Timer created = timerService.createCalendarTimer(exp,config);
}

When a programmatic timer is created, the task to be triggered by the timer is that one annotated with @Timeout

My question, since I could not find it clearly stated in the JSR, if a create 2 programmatic timers for the same EJB using the same ScheduleExpression, the container must call the @Timeout method twice or once?

To make my question clearer.

Let's suppose I've created 2 programmatic timers. Each one has a different metadata (stored in the serializable timer INFO attribute). Then, I'd like to have two different timers, and when the @Timeout method executes, it would get this INFO attribute to choose what to do.

If the answer of my question is twice, than I can do it. If the answer of my question is once, then I cannot.

Notice that if the answer is once, it makes some sense from the performance point of view, because you don't actually need to notify the EJB more than once for a given moment, even if you have several triggers for it, but if you are planning to deal with these triggers independently (because each one has a different INFO), then someone is just ignoring the attempt to create a timer when there's already one persisted.

2

2 Answers

2
votes

Do something like this:

@Singleton
@Startup
public class TestBean {

    // should be in a separate class
    public enum TTimer {
        FOO,
        BAR
    }

    @Resource
    TimerService timerService;

    @PostConstruct
    private void initSingleTimer() {
        removeRunningTimers();
        startInitialTimer();
    }

    private void removeRunningTimers() {
        for (Timer t : timerService.getTimers()) {
            if ( t.getInfo().equals(TTimer.FOO)) {
                t.cancel();
                log.trace("LogWatcher: Running timer canceled");                    
            }
        }
    }

    private void startInitialTimer() {
        ....
        timerService.createTimer(startDate, interval, TTimer.FOO);
    }
1
votes

Timers are distinct, so if you create two, then the @Timeout method will be invoked for both timers regardless of whether the scheduling information is the same.