Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
314 views
in Technique[技术] by (71.8m points)

wildfly - Run Java EE CDI task with interval

I need to run a task with interval once my application (WAR) starts, I am using WildFly 21. The task should be initialized at startup and perform some work at some interval.

the class is below

@ApplicationScoped
@ActivateRequestContext
public class TaskRunner {

 
  @Resource private ManagedScheduledExecutorService scheduler;

  @Inject private ScheduledFuture<?> TaskRunnerScheduler;

  private boolean initialized = false;

  private void init(@Observes @Initialized(ApplicationScoped.class) Object init) {

    if (initialized) return;

   
    initialized = true;
    try {
      // Execute at startup
      TaskRunner = scheduler.schedule(this::runSchedule, getSchedule());
    } catch (Throwable throwable) {

    }
  }

  private void runSchedule() {
//do some work
  }

  private Trigger getSchedule() {
    return new Trigger() {
      @Override
      public Date getNextRunTime(LastExecution lastExecutionInfo, Date taskScheduledTime) {
        return Date.from(
            ZonedDateTime.now().withSecond(0).withNano(0).plusHours("4").toInstant());
      }

      @Override
      public boolean skipRun(LastExecution lastExecutionInfo, Date scheduledRunTime) 
       {return false;}};
  }

}

When trying to deploy the application, I am getting the following error

 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-6) MSC000001: Failed to start service jboss.deployment.unit."task-web.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."task-web.war".WeldStartService: Failed to start service
    at [email protected]//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1731)
    at [email protected]//org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
    at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
    at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
    at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ScheduledFuture<?> with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private TaskRunner.TaskRunnerScheduler
  at TaskRunner.TaskRunnerScheduler(TaskRunner.java:0)

    at [email protected]//org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:378)
    at [email protected]//org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:290)
    at [email protected]//org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:143)
    at [email protected]//org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:164)
    at [email protected]//org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:526)
    at [email protected]//org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:64)
    at [email protected]//org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:62)
    at [email protected]//org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62)
    at [email protected]//org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    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 [email protected]//org.jboss.threads.JBossThread.run(JBossThread.java:513)

Any ideas what is the cause of this error?

question from:https://stackoverflow.com/questions/65649181/run-java-ee-cdi-task-with-interval

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It looks like you want to run every 4 hours or so. Can I suggest a bit cleaner implementation?

@Startup
@Singleton
public class MyScheduler {
    @PostConstruct
    private void runAtStartup() {
        // whatever makes sense here
    }

    @Schedule(hour = "*/4", persistent = false )
    private void runSomething() {
        // something here
    }
}

This sets up an EJB to run at startup (@Startup), saying that there is only one instance of it (@Singleton). It then runs the runSomething() method every 4 hours. You can take a look at the Schedule Javadocs as there are many other ways to run this too. You may or may not need the @PostConstruct method if it previously only existed to setup the timer.

The persistent parameter tells Wildfly to remember when the last run was and, if restarted, continue to run on that schedule. If you don't care if your method runs again on restart then leave this false.

My only warning is that this mechanism doesn't handle overlaps. If you use this and a new schedule method is run before the last one finishes (in this example, 4 hours later) it can lead to errors in at least your log and the schedule not running the way you expect it to.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...