5

In my Java EE 7 application I have created a persistent Schedule task that runs every hour. I have used @Schedule annotation.

When this job is called I want to perform some actions on events that have happened from the last hour until NOW. To obtain NOW I use "new Date()".

This @Schedule has the default persistent attribute to "true", which is great because if the server stops during hours I want to perform these tasks when it restarts.

The problem is that, if the server has been stopped during 5 hours, the job will be launched 5 times, but in all of the executions "new Date()" will be executed, and the result will be the same.

Is there any way to retrieve the date when the @Schedule job should have been launched???

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
marcoslop
  • 106
  • 7

2 Answers2

3

Is there any way to retrieve the date when the @Schedule job should have been launched???

I think the answer is no, there isn't.

The specification defines three interfaces that must be implemented by the Container. These interface are: TimerService, Timer and TimerHandle. As you can see, no one of them (specially Timer) exposes the method that you need. Therefore, a Java EE compliant server is not forced to implement this behavior.

Probably you should implement by yourself a solution that provides this requirement. For example, you could store the timestamp when the last callback method was executed and use this timestamp for determining the period of time (instead of subtract 1 hour to the current date)

...if the server has been stopped during 5 hours, the job will be launched 5 times...

Note that you cannot rely on this

18.4.3 Timer Expiration and Timeout Callback Method ...Any interval persistent timers or schedule based persistent timers that have expired during the intervening time must cause the corresponding timeout callback method to be invoked at least once upon restart.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Gabriel Aramburu
  • 2,951
  • 2
  • 16
  • 20
1

You can reconstruct the time your timer should be actually run by using javax.ejb.Timer:

@Timeout
public void timeout(Timer timer) {
    // get next time
    Date nextTime = timer.getNextTimeout();
    // substract 1 hour
    Calendar c = Calendar.getInstance();
    c.setTime(timer.getNextTimeout());
    c.add(Calendar.HOUR_OF_DAY, -1);
    Date actualTimerDate = c.getTime();
}
Magic Wand
  • 1,572
  • 10
  • 9
  • I imagine that using TimerService directly this could be achieved somehow, but I wanted to use from a @Schedule annotated method. – marcoslop Sep 19 '14 at 15:49
  • This method does not work when using persistent timers, as when the server is down and started back up, in JBoss it will run all the missed timers with the same next timeout value. – Iain Feb 08 '15 at 22:07