A Spring Boot Batch application that demonstrates YAML-based job configuration and dynamic job scheduling. This project enables defining batch jobs declaratively in YAML files, making batch job configuration flexible and maintainable without code changes.
- YAML-based Job Configuration: Define batch jobs using simple YAML files
- Automatic Job Scheduling: Built-in cron-based scheduling support
- Dynamic Job Loading: Jobs are loaded and scheduled automatically at startup
- Multiple Step Types: Support for both chunk-oriented and tasklet-based steps
- Registry Pattern: Extensible registries for readers, writers, processors, tasklets, and row mappers
- JDBC Support: Built-in JDBC reader with named parameters
- MS SQL Server Integration: Configured for Microsoft SQL Server database
- Java: 21
- Spring Boot: 4.0.2
- Spring Batch: Batch processing framework
- MS SQL Server: Database for batch metadata and data
- Jackson YAML: YAML parsing
- Lombok: Reducing boilerplate code
- Maven: Build and dependency management
src/main/java/test/demoyamlspringbatch/
├── DemoYamlSpringBatchApplication.java # Main application entry point
└── batch/
├── engine/ # Core batch engine
│ ├── BatchScheduler.java # Schedules and executes jobs
│ ├── SchedulerConfig.java # Scheduler configuration
│ ├── YamlJobFactory.java # Creates Job instances from definitions
│ └── YamlJobLoader.java # Loads job definitions from YAML
├── factory/
│ └── ReaderFactory.java # Factory for creating readers
├── impl/ # Component implementations
│ ├── processor/ # Item processors
│ │ ├── InputProcessor.java
│ │ ├── LowerCaseProcessor.java
│ │ └── UpperCaseProcessor.java
│ ├── reader/ # Item readers
│ │ ├── NamedParameterJdbcItemReader.java
│ │ └── SimpleStringReader.java
│ ├── rowmapper/
│ │ └── InputDataRowMapper.java
│ ├── tasklet/
│ │ └── CleanTempFileTasklet.java
│ └── writer/
│ └── ConsoleWriter.java
├── model/ # Data models and definitions
│ ├── ChunkStepDefinition.java
│ ├── JobDefinition.java
│ ├── RefDefinition.java
│ ├── ScheduleDefinition.java
│ ├── StepDefinition.java
│ ├── StepType.java
│ ├── TaskletStepDefinition.java
│ ├── entites/
│ │ ├── InputData.java
│ │ └── OutputData.java
│ └── reader/
│ ├── BeanReaderDefinition.java
│ ├── JdbcReaderDefinition.java
│ └── ReaderDefinition.java
└── registry/ # Component registries
├── ProcessorRegistry.java
├── ReaderRegistry.java
├── RowMapperRegistry.java
├── TaskletRegistry.java
└── WriterRegistry.java
- Java 21 or higher
- Maven 3.6+
- MS SQL Server instance running on
localhost:1433 - Database named
batchdb
- Create a SQL Server database named
batchdb - Update credentials in
application.ymlif needed (default: sa/12345) - Spring Batch will automatically create required metadata tables on startup
The application configuration is in src/main/resources/application.yml:
spring:
datasource:
url: jdbc:sqlserver://localhost:1433;databaseName=batchdb;encrypt=false
username: sa
password: 12345
batch:
jdbc:
initialize-schema: always
job:
enabled: false # Important: prevents auto-run on startupmvn clean installmvn spring-boot:runOr run the JAR file:
java -jar target/DemoYAMLSpringBatch-0.0.1-SNAPSHOT.jarJobs are defined in src/main/resources/batch-jobs/demo-job.yml. The application supports multiple jobs in a single YAML file.
jobs:
- name: jobA
parameters:
inputFile: classpath:data/input.txt
schedule:
type: cron
expression: "0 */1 * * * *" # Every minute
steps:
- name: step1
type: chunk
chunkSize: 2
reader:
type: bean
bean: simpleStringReader
processor:
bean: upperCaseProcessor
writer:
bean: consoleWriter
- name: step2
type: chunk
chunkSize: 2
reader:
type: jdbc
sql: select id, name, status from input_data where status = :status
params:
status: NEW
rowMapper: inputDataRowMapper
processor:
bean: inputProcessor
writer:
bean: consoleWriter
- name: jobB
schedule:
type: cron
expression: "30 */1 * * * *" # Every minute at 30 seconds
steps:
- name: step1
type: tasklet
tasklet: cleanTempFileTasklet
params:
path: /tmpProcess items in chunks for better performance:
- name: chunkStep
type: chunk
chunkSize: 10
reader:
type: bean
bean: myReader
processor:
bean: myProcessor
writer:
bean: myWriterExecute single-task operations:
- name: taskletStep
type: tasklet
tasklet: myTasklet
params:
key1: value1Use a Spring bean as a reader:
reader:
type: bean
bean: simpleStringReaderRead from database with named parameters:
reader:
type: jdbc
sql: select * from table where status = :status
params:
status: ACTIVE
rowMapper: myRowMapper- Create a new processor class:
@Component
@StepScope
public class MyProcessor implements ItemProcessor<Input, Output> {
@Override
public Output process(Input item) {
// Transform logic
return transformedItem;
}
}- Reference it in your YAML:
processor:
bean: myProcessor- Create a new reader class:
@Component
@StepScope
public class MyReader implements ItemReader<MyData> {
@Override
public MyData read() {
// Reading logic
return data;
}
}- Use it in your YAML:
reader:
type: bean
bean: myReader- Create a new tasklet class:
@Component
public class MyTasklet implements Tasklet {
@Override
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) {
// Task logic
return RepeatStatus.FINISHED;
}
}- Register and use it:
steps:
- name: myTask
type: tasklet
tasklet: myTaskletThe application uses registry components to manage batch processing components:
- ReaderRegistry: Manages ItemReader beans
- WriterRegistry: Manages ItemWriter beans
- ProcessorRegistry: Manages ItemProcessor beans
- TaskletRegistry: Manages Tasklet beans
- RowMapperRegistry: Manages RowMapper beans
This pattern enables:
- Loose coupling between configuration and implementation
- Easy component registration and lookup
- Dynamic component resolution at runtime
- Startup:
BatchSchedulerinitializes - Load:
YamlJobLoaderreads YAML files frombatch-jobs/directory - Build:
YamlJobFactorycreates Spring Batch Job instances - Schedule: Jobs are scheduled based on cron expressions
- Execute: Jobs run automatically according to their schedules
"0 */1 * * * *" # Every minute
"0 0 */2 * * *" # Every 2 hours
"0 0 0 * * *" # Daily at midnight
"0 0 9 * * MON-FRI" # Weekdays at 9 AM
- Check that
spring.batch.job.enabled=falsein application.yml - Verify cron expressions are valid
- Check logs for scheduling errors
- Ensure SQL Server is running on localhost:1433
- Verify database
batchdbexists - Check username/password in application.yml
- Ensure SQL Server accepts TCP/IP connections
- Validate YAML syntax
- Ensure all required fields are present
- Check that bean names match Spring component names
This project is a demonstration/learning project.
Feel free to submit issues and enhancement requests!
For questions or issues, please create an issue in the repository.