I am working on an application which runs in a clustered Java EE environment on IBM WebSphere Application Server. We have a startup singleton bean which creates a persistent EJB timer and we have the EJB Timer Service configured so that each cluster node uses the same DB tables. How can I make sure that 2 nodes don't both create the persistent timer at startup? I know how to make sure that only one node actually runs the timeout method, but not how to make sure the timer isn't created twice.
We are currently cancelling and recreating all timers with the same "name" on startup, which means (if I understand correctly), that as long as the cluster nodes do not initialize this bean simultaneously, then the last node to startup will clear any existing timers and recreate a single timer instance. However, how do I ensure that we avoid the rare case of 2 nodes both exiting the cancelTimer() method at the same time and both running the TimerService.createTimer() method, creating 2 identical timers for the cluster?
Here is some example code:
@Startup
@Singleton
public class Timer{
String timerName = "myTimer";
@Resource
private SessionContext sessionCtx;
@PostConstruct
public void start() {
cancelTimer();
TimerService ts = sessionCtx.getTimerService();
ts.createTimer(new Date(), 60000, timerName);
}
@PreDestroy
public void stop() {
cancelTimer();
}
public void cancelTimer() {
TimerService ts = sessionCtx.getTimerService();
Collection<Timer> timers = ts.getTimers();
for(Timer timer : timers){
if (timer.getInfo().equals(timerName)) {
timer.cancel();
}
}
}
@Timeout
public void timeout() {
System.out.println("timeout!");
}
}