All Products
Search
Document Center

SchedulerX:Integrate Spring jobs with SchedulerX

Last Updated:Jun 21, 2026

Spring's built-in scheduler offers a convenient way to run timed tasks in Java, but it has limitations in enterprise environments. Integrating your Spring jobs with SchedulerX enhances them with enterprise-grade features such as monitoring, advanced scheduling, and high availability.

Prerequisites

Procedure

Step 1: Add the dependency

In a Spring Boot application, add the SchedulerX dependency to your pom.xml file.

Use the latest agent version for schedulerx2.version. For more information, see Agent Release Notes.

<dependency>
  <groupId>com.aliyun.schedulerx</groupId>
  <artifactId>schedulerx2-spring-boot-starter</artifactId>
  <version>${schedulerx2.version}</version>
  <!-- If you use Logback, you must exclude Log4j and Log4j2. -->
  <exclusions>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Whether you are new to Spring jobs or have existing ones, you must keep the @EnableScheduling annotation in your main class to enable scheduling.

@SpringBootApplication
@EnableScheduling /** Enable Spring scheduled jobs. */
public class SchedulerXWorkerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SchedulerXWorkerApplication.class, args);
    }
}
/** A native Spring scheduled job class. */
@Service
public class SpringScheduledProcessor {
    @Scheduled(cron = "0/2 * * * * ?")
    public void hello() {
        logger.info(DateUtil.now() + " hello world. start");
        logger.info(DateUtil.now() + " hello world. end");
    }
}

By default, after you add the dependency, SchedulerX does not manage your existing Spring jobs. The jobs continue to be scheduled by the Spring container, and their execution is unaffected.

Step 2: Add configuration parameters

To allow SchedulerX to manage your Spring jobs, add the following configuration to your application.properties file.

# 1. Application access configuration
spring.schedulerx2.endpoint=${endpoint}
spring.schedulerx2.namespace=${namespace}
spring.schedulerx2.groupId=${groupId}
spring.schedulerx2.appKey=${appKey}

# 2. Enable SchedulerX to manage Spring jobs
spring.schedulerx2.task.scheduling.scheduler=schedulerx

# 3. Optional: Enable automatic synchronization for existing Spring jobs
#spring.schedulerx2.task.scheduling.sync=true
#spring.schedulerx2.regionId=Specify the region ID for job synchronization.
#spring.schedulerx2.aliyunAccessKey=XXXXXXXXX
#spring.schedulerx2.aliyunSecretKey=XXXXXXXXX

Parameter descriptions:

  • Application access configuration: Log in to the SchedulerX console. In the left-side navigation pane, click Application Management. Find your application, and in the Actions column, click Access Configuration to get your credentials. If this is your first time connecting, you must create an application group.

  • Auto-sync configuration: If you have a large number of existing Spring jobs, you can enable automatic synchronization to avoid manually creating tasks as described in Step 3. For a list of region IDs, see Endpoints.

Important

To maintain consistency with the rules for running native Spring jobs in a cluster environment, jobs that are automatically synchronized to the SchedulerX platform use the broadcast run execution mode by default. This means that each machine in the cluster executes the job at the scheduled time. If your business requires that only one machine in the cluster runs the job, you can edit the job's execution mode to stand-alone operation in the console. For more information about the parameters, see Step 3.

Step 3 (Optional): Manually create a task

Note

If you enabled automatic synchronization in Step 2, you can skip this step.

  1. Log on to the SchedulerX console.

  2. In the left-side navigation pane, click task management.

  3. On the task management page, click Create Task. Select SpringSchedule as the task type and configure the class and method name.

    Parameter

    Description

    Name

    A unique name to identify the task.

    Description

    An optional description to help you search for and manage the task.

    Application ID

    The application group that the task belongs to. Select an option from the drop-down list.

    Job Type

    The processor type for the task. Valid values: Java, Shell, Python, Go, HTTP, Node.js, SpringSchedule, XXL-JOB, and DataWorks. If you select Shell, Python, or Go, a script editor appears.

    For this tutorial, select SpringSchedule.

    Spring Schedule Configuration

    The fully qualified class name and method name of the task.

    Execution Mode

    Specifies how the task is executed across multiple instances. The following modes are supported:

    • Stand-alone operation: Runs the task on a randomly selected instance.

    • Broadcast run: Runs the task on all instances simultaneously.

    Note

    The advanced settings change based on the selected execution mode.

    Priority

    If multiple tasks within the same application are ready to run on the same instance, the task with the higher priority runs first. SchedulerX uses a preemptible priority queue to ensure high-priority tasks are executed first, even across different instances. For more information, see Application-level Throttling with a Priority Queue.

    Job Parameters

    A custom string that can be retrieved from the job context at runtime.

  4. Configure the schedule.

    Note

    The schedule configured in the console overrides the schedule specified in the @Scheduled annotation in your code. However, you must keep the annotation in your code.

    The following table describes the time-based parameters.

    Parameter

    Description

    Time Type

    • none: The task is not scheduled and is typically triggered by a workflow.

    • cron: The task is scheduled using a cron expression.

    • api: The task is triggered by an API call.

    • fixed_rate: The task is triggered at a fixed frequency.

    • second_delay: The task is triggered after a fixed delay in seconds.

    • one_time: The task runs only once.

    Cron Expression (for cron time type only)

    Enter a standard cron expression. You can also use the built-in tool to generate and validate the expression.

    Fixed frequency (for fixed_rate time type only)

    Enter the interval in seconds. The value must be greater than or equal to 60. For example, a value of 200 means the task runs every 200 seconds.

    Fixed delay (for second_delay time type only)

    Enter the delay in seconds. The value must be from 1 to 60. For example, a value of 5 means the task is triggered 5 seconds after the scheduled time.

    The following table describes the advanced configuration parameters.

    Parameter

    Description

    Data Timestamp Offset

    The offset between the data timestamp and the schedule time. You can retrieve this value from the job context at runtime.

    Time Zone

    Select a time zone based on your business requirements. Both regional and standard GMT time zones are supported.

    Calendar

    You can select a calendar, such as a workday or financial day calendar, to restrict task execution to specific days.

  5. Set alert rules and notification channels. For more information, see Manage Notification Contacts.

    After you complete these steps, SchedulerX manages your Spring jobs and provides enterprise-grade capabilities, such as visual monitoring, log queries, execution tracing, and alerting.

Step 4: Verify the integration

  1. Start your Spring application. After it starts, log in to the SchedulerX console and click Application Management in the left-side navigation pane. Verify that your application's instances appear in the list.

In the Instances column, confirm that the number is greater than 0. You can also click View Instances in the Actions column to see the details of connected instances.

  1. In the left-side navigation pane, click task management. Find the task for your application and click Run Once in the Actions column. A successful run confirms the integration.

FAQ

Why does the original Spring timer still run after SchedulerX takes over?

If a custom scheduler is specified in your application, SchedulerX overwrites the custom scheduler. This conflict typically occurs when a class implements org.springframework.scheduling.annotation.SchedulingConfigurer and calls the setScheduler method of ScheduledTaskRegistrar, which overwrites the default scheduler.

To resolve this issue:

  1. Search your project for any class that implements SchedulingConfigurer.

  2. Check whether the setScheduler method of ScheduledTaskRegistrar is called.

  3. If either condition is true, comment out the custom scheduler code.

How do I get the job context in a Spring job?

Call ContainerFactory.getContainerPool().getContext() to get the current JobContext:

// Get the SchedulerX job context inside a @Scheduled method
JobContext jobContext = ContainerFactory.getContainerPool().getContext();

Can a Spring job return a processing result?

This feature requires SchedulerX agent version later than 1.10.11. Versions 1.10.11 and earlier do not support return values from Spring jobs.

The processing results are returned based on the specified scheduling methods. Spring jobs support two return types:

Return typeUse case
ProcessResultReturn a success/failure status with a result message
StringReturn a result message only

Both examples below use the @Scheduled annotation with a cron expression.

Return a ProcessResult

Use ProcessResult to indicate success or failure along with a result message:

@Scheduled(cron = "0/5 * * * * ?")
public ProcessResult helloStandalone1() {
    try {
        logger.info(DateUtil.now() + " " + Thread.currentThread().getName() + " hello world. start");
        TimeUnit.SECONDS.sleep(2L);
        logger.info(DateUtil.now() + " " + Thread.currentThread().getName() + " hello world. end");
    } catch (Exception e) {
        e.printStackTrace();
        logger.info(DateUtil.now() + " " + Thread.currentThread().getName() + " hello world. exception end..");
    }
    // First argument: true for success, false for failure
    // Second argument: result message
    return new ProcessResult(true, "Processing result");
}

Return a String

Return a String directly when you do not need an explicit success/failure flag:

@Scheduled(cron = "0/5 * * * * ?")
public String helloStandalone2() {
    try {
        logger.info(DateUtil.now() + " " + Thread.currentThread().getName() + " hello world. start");
        TimeUnit.SECONDS.sleep(2L);
        logger.info(DateUtil.now() + " " + Thread.currentThread().getName() + " hello world. end");
    } catch (Exception e) {
        e.printStackTrace();
        logger.info(DateUtil.now() + " " + Thread.currentThread().getName() + " hello world. exception end..");
    }
    return "Processing result";
}