skip to content

How do you schedule a recurring background task in Spring, and what two things are required to make it run?

level: juniorimportance: must knowfreq 75%

answer

  1. @EnableScheduling turns it on
  2. @Scheduled marks the method
  3. void + no-args required
  4. ScheduledAnnotationBeanPostProcessor scans
  5. must be a Spring bean

basics

~10 s

Add @EnableScheduling to a @Configuration class to turn scheduling on, then put @Scheduled (with fixedRate, fixedDelay, or cron) on a no-argument, void method of a Spring bean. Spring calls it automatically on a timer.

solid answer

~40 s

Two pieces are required. First, @EnableScheduling on a @Configuration (or @SpringBootApplication) class; it registers the infrastructure (a ScheduledAnnotationBeanPostProcessor) that scans beans for scheduled methods. Second, an @Scheduled annotation on a method of a Spring-managed bean, giving a trigger: fixedRate, fixedDelay, or a cron expression. The method must be void and take no arguments, since Spring invokes it reflectively with no way to pass parameters or use a return value. Without @EnableScheduling nothing runs even if @Scheduled is present. In Spring Boot the scheduling classes are on the classpath, but you still add @EnableScheduling yourself; it is not on by default. The target must be a real Spring bean (@Component, @Service, etc.) so the post-processor can detect it.

code

java · 17 lines
java
@SpringBootApplication
@EnableScheduling
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

@Component
public class CleanupJob {

    // void, no args, one timing strategy
    @Scheduled(fixedRate = 60_000)
    public void purgeExpired() {
        // ... runs every 60 seconds
    }
}

go deeper

for a junior

Must know the two annotations and that the method is void/no-args.

for a middle

Should explain the post-processor scan and the silent no-op when @EnableScheduling is missing.

for a senior

Should mention multi-instance duplication and that it is not a distributed scheduler.

for a principal

Frames @Scheduled as in-process only; reaches for ShedLock/leader election for cluster-wide single execution.

**What scheduling means here.** Spring's task-scheduling support lets you run a method automatically on a timer without writing your own `Thread`, `Timer`, or `ScheduledExecutorService`. You annotate a method and Spring invokes it for you on a background thread. **The two required parts:** 1. **`@EnableScheduling`** — placed on a `@Configuration` class (or your `@SpringBootApplication`, which is itself a configuration). It imports the scheduling infrastructure, most importantly the `ScheduledAnnotationBeanPostProcessor`. A *bean post-processor* is a Spring hook that inspects every bean as it is created; this one scans each bean's methods for `@Scheduled` and registers the ones it finds with a `TaskScheduler`. If you forget `@EnableScheduling`, your `@Scheduled` methods are silently ignored — no error, they just never fire. This is the single most common beginner mistake. 2. **`@Scheduled`** — on a method of a Spring-managed bean. You must give it exactly one timing strategy: `fixedRate`, `fixedDelay`, or `cron` (optionally with `initialDelay`). **Constraints on the method.** The method must (a) return `void` and (b) take **no arguments**. Spring calls it by reflection with nothing to pass in and ignores any return value, so a non-void or parameterized method is rejected at startup with an `IllegalStateException`. The method may be `public` or not — Spring can invoke non-public methods, though `public` is conventional. **The bean must be managed by Spring.** `@Scheduled` on a plain `new`-ed object does nothing; only beans that pass through the container are scanned. Also note that if the bean is proxied (e.g. it also has `@Transactional`), scheduling still works because the post-processor operates on the bean instance. **Spring Boot specifics.** The starter puts `spring-context` (which contains scheduling) on the classpath, but Boot does **not** auto-enable scheduling. You add `@EnableScheduling` explicitly, typically on the main application class. **Where the thread comes from.** By default Spring creates a single-threaded scheduler if you don't define your own `TaskScheduler`/`ThreadPoolTaskScheduler` bean — important once you have more than one scheduled task (covered in the pool-sizing question). **When to use it.** Good for periodic in-process jobs: cache eviction, cleanup, polling, metrics flushing, sending digest emails. It is **not** a distributed scheduler — in a multi-instance deployment every instance runs the job, so you need a lock (e.g. ShedLock) or leader election if the job must run once cluster-wide.

  • You added @Scheduled but the method never runs and there is no error. What is the first thing you check?
    That @EnableScheduling is present on a @Configuration/@SpringBootApplication class. Without it the ScheduledAnnotationBeanPostProcessor is never registered, so @Scheduled methods are silently ignored. Also confirm the class is an actual Spring bean.
  • Can a @Scheduled method take parameters or return a value?
    No. It must be void and take no arguments. Spring invokes it reflectively with nothing to pass and no consumer for a return value; a non-void or parameterized method fails at startup with an IllegalStateException.

saying these in an interview costs you the question

  • Thinking Spring Boot enables scheduling automatically without @EnableScheduling
  • Putting @Scheduled on a non-bean (new-ed object) and expecting it to run
  • Claiming the method can accept arguments or return a result
  • Believing a missing @EnableScheduling produces a startup error rather than silent no-op

context