You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于JSR-352的WildFly批处理作业:上次结束后延迟调度实现

Implementing Fixed-Delay, Single-Instance Batch Scheduling on WildFly (JSR-352)

Great question! Your requirement breaks down into two core goals:

  1. Ensure only one job instance runs at a time (no concurrent executions)
  2. Trigger the next run after a fixed delay from the end of the previous execution (not rigid fixed intervals regardless of runtime)

Here are two reliable approaches using JBeret (WildFly's built-in JSR-352 implementation):


Approach 1: Container-Level Configuration (Simplest)

WildFly's Batch JBeret subsystem supports native scheduling that matches your needs perfectly. This requires no custom code—just straightforward configuration.

Step 1: Block Concurrent Job Runs

First, update your job XML to prevent overlapping executions using a JBeret extension property:

<job id="yourBatchJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <!-- Your job steps go here -->
    <properties>
        <!-- Block new runs if an instance is already active -->
        <property name="allow-start-if-running" value="false"/>
    </properties>
</job>

Step 2: Define a Fixed-Delay Schedule

Edit your WildFly configuration file (standalone.xml or domain.xml) to add a job schedule with fixed-delay (wait time after previous run ends) and concurrent="false" (double insurance against concurrency):

<subsystem xmlns="urn:jboss:domain:batch-jberet:1.0">
    <job-schedules>
        <job-schedule name="yourJobSchedule" job-name="yourBatchJob">
            <trigger>
                <!-- fixed-delay = milliseconds to wait after previous run completes -->
                <!-- concurrent="false" skips scheduled runs if the job is already running -->
                <simple start-time="now" fixed-delay="300000" concurrent="false"/>
            </trigger>
        </job-schedule>
    </job-schedules>
    <!-- Rest of your batch subsystem configuration -->
</subsystem>
  • fixed-delay="300000" translates to a 5-minute delay after the previous job finishes
  • This setup ensures the scheduler only triggers a new run once the prior one has ended and the delay window passes

Approach 2: Programmatic Control (Flexible)

If you need dynamic behavior (e.g., adjusting delay based on job results, conditional scheduling), use an EJB Singleton + Job Listener combo.

Step 1: Implement a Job Completion Listener

This listener triggers the next scheduled run once the current job finishes:

import javax.batch.api.listener.JobListener;
import javax.batch.runtime.BatchRuntime;
import javax.batch.runtime.JobExecution;
import javax.batch.runtime.JobOperator;
import javax.naming.InitialContext;

public class PostJobSchedulerListener implements JobListener {

    @Override
    public void beforeJob() {}

    @Override
    public void afterJob() {
        JobOperator jobOperator = BatchRuntime.getJobOperator();
        long currentExecutionId = javax.batch.runtime.context.JobContext.getCurrentJobExecutionId();
        JobExecution execution = jobOperator.getJobExecution(currentExecutionId);

        // Only schedule next run if current job completed successfully (adjust logic as needed)
        if (execution.getBatchStatus() == javax.batch.runtime.BatchStatus.COMPLETED) {
            try {
                MyJobScheduler scheduler = InitialContext.doLookup("java:module/MyJobScheduler");
                scheduler.scheduleNextRun();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Register this listener in your job XML:

<job id="yourBatchJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <listeners>
        <listener ref="postJobSchedulerListener"/>
    </listeners>
    <!-- Your job steps and allow-start-if-running property -->
</job>

Step 2: Create a Singleton EJB for Scheduling

This EJB manages the delay timer and ensures only one scheduler instance exists in the application:

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.batch.runtime.BatchRuntime;
import javax.batch.runtime.JobOperator;
import java.util.List;

@Singleton
@Startup // Remove this if you don't want the job to start automatically on app deployment
public class MyJobScheduler {
    @Resource
    private TimerService timerService;
    private static final long DELAY_MS = 5 * 60 * 1000; // 5-minute delay
    private static final String JOB_NAME = "yourBatchJob";

    @PostConstruct
    public void init() {
        // Start the first job run when the application deploys
        startJobIfNotRunning();
    }

    public void scheduleNextRun() {
        // Cancel existing timers to avoid duplicate schedules
        for (Timer timer : timerService.getTimers()) {
            timer.cancel();
        }
        // Create a new timer to trigger the next run after the delay
        timerService.createTimer(DELAY_MS, null);
    }

    @Timeout
    public void onTimer(Timer timer) {
        startJobIfNotRunning();
    }

    private void startJobIfNotRunning() {
        JobOperator jobOperator = BatchRuntime.getJobOperator();
        List<Long> runningExecutions = jobOperator.getRunningExecutions(JOB_NAME);
        
        if (runningExecutions.isEmpty()) {
            jobOperator.start(JOB_NAME, new java.util.Properties());
        }
    }
}

Key Notes

  • Concurrency Safety: Both approaches use allow-start-if-running="false" plus either scheduler-level concurrent="false" or runtime checks to eliminate overlapping jobs.
  • Failure Handling: Adjust the Job Listener logic to handle failed jobs (e.g., retry immediately, extend the delay, or skip scheduling entirely).
  • WildFly Version: Ensure you're using WildFly 10+ (JBeret 1.3+) to access the fixed-delay scheduler feature in the batch subsystem.

内容的提问来源于stack exchange,提问作者mohammad_1m2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:47:57