Stop @Schedule EJB gracefully when shutting down application server

Viewed 51

I have a stateless EJB with a method that should executed periodically. This works well so far. However, I want the stop the method gracefully when it is running while shutting down application server. Therefore, I have implemented a stop() method annotated with @PreDestroy.

However, the stop() method does not work as expected. When stopping my application server while schedule() is running, the application server waits until schedule() terminates and calls stop() only afterwards.

@Stateless
public class TestService {

    private static final Logger logger = Logger.getLogger(TestService.class);

    private volatile boolean shutdown = false;

    @Schedule(hour = "*", minute = "*", second = "*/15", persistent = false)
    public void schedule() throws InterruptedException {
        logger.info("Start execution");
        for (int i = 0; !shutdown && i < 10; ++i) {
            logger.info("Step " + i);
            Thread.sleep(1000);
        }
        logger.info("Stopped execution");
    }

    @PreDestroy
    public void stop() {
        logger.info("Trigger stop");
        shutdown = false;
    }

}

Here, I have posted only a minimal example EJB for reproducing my issue. In my real EJB, it is even worse. When executing any transaction after triggering the server shutdown, the application server (JBoss EAP 7.1 with WildFly 11) throws a ComponentIsStoppedException. So, I have no chance to gracefully shutdown my EJB.

1 Answers

An alternative solution could be to use the EJB TimerService ?

Something like this:

@Startup
public class TestService {

    @Resource
    private TimerService ejbTimerService;

    private Timer timer = null;

    @PostConstruct
    public void setup() {
        ScheduleExpression schedule = new ScheduleExpression().hour("*").minute("*").second("15");
        timer = ejbTimerService.createCalendarTimer(schedule);
        System.out.println("Timer " + timer.toString() + " created");
    }

    @Timeout
    public void onTimeout(Timer timer) {
        System.out.println("Timer schedule: " + timer.getSchedule());
    }

    @PreDestroy
    public void tearDown() {
        logger.info("Trigger stop");        
    }

    // Method to call when stopping application server
    public void smoothShutdown() {
       if (timer!=null) timer.cancel();
    }
}
Related