Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you make sure that an EJB timer is only created once in a Java EE clustered environment?

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!");
    }
}
like image 228
Jaawn Avatar asked Mar 21 '18 20:03

Jaawn


People also ask

How does EJB timer work?

The EJB timer service provides a reliable and transactional notification service for timed events. Timer notifications may be scheduled to occur at a specific time, after a specific elapsed duration, or at specific recurring intervals. You can define callback methods on your EJB to receive these time-based events.

What is timer service in j2ee?

The timer service of the enterprise bean container enables you to schedule timed notifications for all types of enterprise beans except for stateful session beans. You can schedule a timed notification to occur according to a calendar schedule, at a specific time, after a duration of time, or at timed intervals.

Which of the following are valid ways to create non persistent timers?

Nonpersistent programmatic timers are created by calling TimerConfig. setPersistent(false) and passing the TimerConfig object to one of the timer-creation methods.


1 Answers

In WebSphere Application Server traditional, if you switch to automatic persistent timers (for example, by using the @Schedule annotation) and all of the cluster members have EJB Container configuration that points to the same cluster scoped Scheduler, then the application server will take care of ensuring that exactly one instance of the automatic timer is scheduled across the whole cluster. If you are unable to switch to automatic persistent timers and need to continue with the approach of manually creating them, one common solution would be to use the database as a synchronization point (which is essentially what the application server does). For example, your start method can attempt to make a particular update to a database entry indicating that it has reserved the right to schedule the timer, and only if it succeeds in doing so, proceeds to schedule the timer.

like image 199
njr Avatar answered Oct 16 '22 05:10

njr