LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2422 min read

Scheduling & Batch Processing Dependencies

Learn the built-in @Scheduled annotation, spring-boot-starter-quartz for advanced job scheduling, and spring-boot-starter-batch for large-scale batch processing.

Introduction

Applications frequently need to do things on a schedule — clean up expired sessions at midnight, generate a daily report, or process a nightly batch of orders. Spring offers three tiers for this, each with a different amount of power (and a different amount of setup): built-in @Scheduled, Quartz for advanced clustered scheduling, and Spring Batch for large-scale data processing.

What You Will Learn
  • How to schedule simple recurring tasks with @Scheduled — and why it needs no extra dependency.
  • How to use spring-boot-starter-quartz for persistent, clustered, cron-driven jobs.
  • How to use spring-boot-starter-batch for large-scale, step-based batch processing.
  • How to decide which of the three fits a given job.

Simple Scheduling: @Scheduled (No Extra Dependency)

This is the one exception in this entire course: @Scheduled and @EnableScheduling live in spring-context, which is already part of Spring Boot's core. You do not need to add anything to pom.xml to use them — just enable scheduling on a configuration class.

SchedulingConfig.java
@Configuration
@EnableScheduling
public class SchedulingConfig {
}
CleanupTask.java
@Component
public class CleanupTask {
@Scheduled(cron = "0 0 0 * * *") // every day at midnight
public void purgeExpiredSessions() {
System.out.println("Purging expired sessions...");
}
}
Use Case

@Scheduled is ideal for simple, single-instance, in-memory recurring tasks: cache eviction, periodic health checks, small housekeeping jobs. It has no persistence and no clustering awareness — if your app runs on multiple instances, every instance runs the job independently, which is often not what you want.

Advanced Scheduling: spring-boot-starter-quartz

Use case: you need jobs that survive an application restart, that run exactly once across a cluster of instances (not once per instance), or that need dynamic scheduling changed at runtime rather than hardcoded at compile time. Quartz is a mature, persistent job scheduler that solves all three.

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

Define the job logic, then wire up a JobDetail and a Trigger as beans.

ReportJob.java
public class ReportJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
System.out.println("Generating daily report...");
}
}
QuartzConfig.java
@Configuration
public class QuartzConfig {
@Bean
public JobDetail reportJobDetail() {
return JobBuilder.newJob(ReportJob.class)
.withIdentity("reportJob")
.storeDurably()
.build();
}
@Bean
public Trigger reportJobTrigger(JobDetail reportJobDetail) {
return TriggerBuilder.newTrigger()
.forJob(reportJobDetail)
.withIdentity("reportJobTrigger")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 6 * * *")) // 6 AM daily
.build();
}
}
Result

Click Run to see what this code prints.

Batch Processing: spring-boot-starter-batch

Use case: processing large volumes of data in discrete steps — reading thousands of rows from a database or file, transforming them, and writing the results elsewhere (a classic ETL job). Spring Batch provides structured Job and Step abstractions, chunk-based processing, and restart/retry support for failures partway through.

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
ExportJobConfig.java
@Configuration
public class ExportJobConfig {
@Bean
public Step exportStep(JobRepository jobRepository,
PlatformTransactionManager txManager,
ItemReader<Order> reader,
ItemProcessor<Order, OrderSummary> processor,
ItemWriter<OrderSummary> writer) {
return new StepBuilder("exportStep", jobRepository)
.<Order, OrderSummary>chunk(100, txManager)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
@Bean
public Job exportJob(JobRepository jobRepository, Step exportStep) {
return new JobBuilder("exportJob", jobRepository)
.start(exportStep)
.build();
}
}
Result

Click Run to see what this code prints.

Which One Should You Use?

NeedUse
Simple recurring task, single instance, no persistence needed@Scheduled (built-in)
Cron-like jobs that must survive restarts or run once across a clusterspring-boot-starter-quartz
Large-volume, step-based data processing (ETL, nightly imports/exports)spring-boot-starter-batch

Common Mistakes

Avoid These Mistakes
  • Using @Scheduled for jobs that must run exactly once across multiple clustered instances — every instance will run it independently.
  • Reaching for Spring Batch for a simple task that @Scheduled could handle in a few lines.
  • Forgetting to configure a persistent JobStore (JDBC) for Quartz in production, leaving jobs to reset on every restart.
  • Not sizing chunk() appropriately in Spring Batch, causing excessive memory use or too many small transactions.

Best Practices

  • Start with @Scheduled and only reach for Quartz or Spring Batch once you hit its real limits.
  • Use cron expressions (not fixedRate/fixedDelay) for anything that needs to run at a specific wall-clock time.
  • Configure Quartz with a JDBC job store in any multi-instance deployment.
  • Log Spring Batch job/step completion status so failures are visible in monitoring, not just in job repository tables.

Frequently Asked Questions

Yes, there is no conflict — use @Scheduled for simple in-process tasks and Quartz only for the specific jobs that need persistence or clustering.

Yes, in production it needs a JobRepository backed by a real database to track job/step execution state; an in-memory repository is available for quick testing only.

Often, yes. Most applications never need it — reach for it specifically when @Scheduled's per-instance, non-persistent behavior becomes a real problem.

Summary

@Scheduled handles simple recurring tasks with zero extra dependencies, spring-boot-starter-quartz adds persistent and clustered job scheduling, and spring-boot-starter-batch provides structured, chunk-based processing for large data volumes.

Lesson 24 Completed
  • You scheduled a simple task with @Scheduled and no extra dependency.
  • You configured a persistent job with spring-boot-starter-quartz.
  • You built a minimal Job/Step with spring-boot-starter-batch.
  • You can decide which of the three fits a given scheduling need.
Next Lesson →

Managing Dependency Versions & Conflicts