jakarta-eeschedulerwildfly-11

How to delay ManagedScheduledExecutorService until container is not suspended?


I am investigating the use of javax.enterprise.concurrent.ManagedScheduledExecutorService on WildFly Full 11.0.0.Final (WildFly Core 3.0.8.Final).

My Startup EJB resembles

import java.time.LocalTime;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.concurrent.ManagedScheduledExecutorService;

@Startup
@Singleton
public class Scheduler {

    static final long INITIAL_DELAY = 0L;
    static final long PERIOD = 2L;

    @Resource
    ManagedScheduledExecutorService scheduler;

    @PostConstruct
    public void init() {
        this.scheduler.scheduleAtFixedRate(this::invokePeriodically, INITIAL_DELAY, PERIOD, TimeUnit.SECONDS);
    }

    public void invokePeriodically() {
        System.out.println("@@@@@@@@@@ - Don't use sout in prod " + LocalTime.now());
    }

}

On Server Startup I see these messages:-

10:15:26,022 ERROR [org.jboss.as.ee] (EE-ManagedScheduledExecutorService-default-Thread-1) WFLYEE0110: 
Failed to run scheduled task: java.lang.IllegalStateException: 
WFLYEE0111: Cannot run scheduled task com.research.Scheduler$$Lambda$932/1222053658@1b50d7a0 as container is suspended
    at org.jboss.as.ee.concurrent.ControlPointUtils$ControlledScheduledRunnable.run(ControlPointUtils.java:164)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
    at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.access$201(ManagedScheduledThreadPoolExecutor.java:383)
    at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.run(ManagedScheduledThreadPoolExecutor.java:534)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:250)
    at org.jboss.as.ee.concurrent.service.ElytronManagedThreadFactory$ElytronManagedThread.run(ElytronManagedThreadFactory.java:78)

When I increase the initial delay

static final long INITIAL_DELAY = 60L;

The server startup is "clean".

Are there any available mechanisms/techniques I can use (other than guessing how long my initial delay should be) to always get a clean server startup and schedule my EJB as soon as possible?


Solution

  • You may be better off using an EJB timer for this purpose. The server is guaranteed not to fire timer methods until the EJB is in service.

    You can verify the API for creating timers at javax.ejb.TimerService.

    Note that if you create persistent timers then the server will try to "catch up" with missed firings when you restart the server.

    If it's just a periodic task then don't create persistent timers.