ManagedScheduledExecutorService 无法运行计划任务,因为容器已暂停

时间:2021-02-26 15:26:29

标签: wildfly

我将 ManagedScheduledExecutorService 传递给我的 WAR 应用程序中的外部库。我在@ApplicationScoped CDI bean 中初始化上下文时调用的方法中执行此操作:

public void init( @Observes @Initialized( ApplicationScoped.class ) Object aInit )
{
   //pass ManagedScheduledExecutorService to library
   //initialize library
}

我收到以下异常:

13:08:23,639 ERROR [org.jboss.as.ee] (EE-ManagedScheduledExecutorService-default-Thread-2) WFLYEE0110: Failed to run scheduled task: java.lang.IllegalStateException: WFLYEE0111: Cannot run scheduled task org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl$ActualScheduledPinger@4cb08cda as container is suspended
        at org.jboss.as.ee@21.0.1-2-PSI//org.jboss.as.ee.concurrent.ControlPointUtils$ControlledScheduledRunnable.run(ControlPointUtils.java:184)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
        at org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.access$201(ManagedScheduledThreadPoolExecutor.java:360)
        at org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.run(ManagedScheduledThreadPoolExecutor.java:511)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:227)

我看到了 How to delay ManagedScheduledExecutorService until container is not suspended? 个问题,但我对答案不满意。我使用外部库(artemis 客户端)并且我无法直接控制它何时安排第一个任务。我不想修改这个库。我不能为它使用 javax.ejb.TimerService,我只能将 ScheduledExecutorService 传递给它。我可以延迟这个库的初始化,但我不想猜测什么延迟是足够和安全的。如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

我不确定我是否正确理解了 How to delay ManagedScheduledExecutorService until container is not suspended? 问题的答案。我理解这个答案,而不是直接使用 ManagedScheduledExecutorService 我应该使用 javax.ejb.TimerService 但我只将 ManagedScheduledExecutorService 传递给外部库所以我不能使用 javax.ejb.TimerServicejavax.ejb.Schedule 注释在这个外部库中。 我通过使用 javax.ejb.TimerService 初始化外部库解决了我的问题。 我是这样做的:

@Singleton
@Startup
public class AppEJB
{
    @Resource
    private TimerService timerSvc;

    @Resource( name = "DefaultManagedScheduledExecutorService" )
    private ManagedScheduledExecutorService scheduledExecutorService;

    @PostConstruct
    private void postConstruct( )
    {
        final ScheduledFuture< Integer > schedule =
                scheduledExecutorService.schedule( () -> 1, 1, TimeUnit.MILLISECONDS );
        try
        {
            schedule.get();
        }
        catch( Exception aE )
        {
            log.warn("Container is not ready to start my library. It will be started later.");
            timerService.createSingleActionTimer( 1, new TimerConfig() );
            return;
        }
        startLib();
    }

    @Timeout
    private void startLibAfterTimeout()
    {
        startLib();
    }

    private void startLib()
    {
        //pass ManagedScheduledExecutorService to library
        //initialize library
    }
}

这个解决方案有一些缺点。如果应用程序部署在启动的 Wildfly 上,则在部署期间初始化库。不幸的是,如果 Wildfly 在 wildfly 重启后启动,则在部署后(在 Wildfly 完成启动后)执行初始化。这意味着在重新启动 Wildfly 后,我仍然需要等待我的外部库初始化。它会对集成测试产生影响。 Arquillian 部署在已启动的 Wildfly 上,因此检查预定的执行程序服务是否可用可以避免在 Arquillian 集成测试中出现睡眠等问题。

我尝试了以下解决方案,但它不起作用。部署应用程序永无止境,因为 while 循环永无止境。

@ApplicationScoped
public class AppBean
{

    @Resource( name = "DefaultManagedScheduledExecutorService" )
    private ManagedScheduledExecutorService scheduledExecutorService;

    public void init( @Observes @Initialized( ApplicationScoped.class ) Object aInit )
    {
        //IT NOT WORK!!!
        System.out.println( "init" );

        while( true )
        {
            try
            {
                final ScheduledFuture< Integer > schedule =
                    scheduledExecutorService.schedule( () -> { return 1; }, 0, TimeUnit.MILLISECONDS );
                final Integer integer = schedule.get();
                break;
            }
            catch( InterruptedException aE )
            {
                System.out.println( "interrupted" );
            }
            catch( ExecutionException aE )
            {
                System.out.println( "exception, sleep" );
                try
                {
                    Thread.sleep( 2000 );
                }
                catch( InterruptedException aInterruptedException )
                {
                    aInterruptedException.printStackTrace();
                }
            }
        }

       //pass ManagedScheduledExecutorService to library
       //initialize library

    }
相关问题