Spring Batch Tutorial: Processing Records with Scheduled Jobs
Learn how to implement a Spring Batch application that processes records every 5 minutes using an in-memory H2 database.
🎯 Project Overview
In this tutorial, we'll build a Spring Batch application that:
- Uses an in-memory H2 database for storing transactions
- Processes pending transactions every 5 minutes
- Implements a complete batch processing pipeline
- Generates sample data for testing
🛠️ Project Setup
First, let's set up our project with the required dependencies in pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
📦 Domain Model
We'll create a simple Transaction entity to represent our data:
@Entity
@Data
@NoArgsConstructor
public class Transaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String accountId;
private BigDecimal amount;
private String type;
private LocalDateTime timestamp;
private String status;
}
⚙️ Batch Configuration
The batch job configuration is the heart of our application:
@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class BatchConfig {
@Bean
public ItemReader reader() {
RepositoryItemReader reader = new RepositoryItemReader<>();
reader.setRepository(transactionRepository);
reader.setMethodName("findByStatus");
reader.setArguments(java.util.Arrays.asList("PENDING"));
return reader;
}
@Bean
public ItemProcessor processor() {
return transaction -> {
transaction.setStatus("PROCESSED");
return transaction;
};
}
@Bean
public Job processTransactionsJob() {
return jobBuilderFactory.get("processTransactionsJob")
.incrementer(new RunIdIncrementer())
.flow(processTransactionsStep())
.end()
.build();
}
}
⏰ Job Scheduler
The scheduler runs our batch job every 5 minutes:
@Component
@EnableScheduling
@RequiredArgsConstructor
@Slf4j
public class BatchJobScheduler {
@Scheduled(fixedRate = 300000) // Run every 5 minutes
public void runBatchJob() {
JobParameters jobParameters = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(processTransactionsJob, jobParameters);
}
}
🔄 Sample Data Generation
We generate sample transactions on application startup:
@Service
@RequiredArgsConstructor
public class TransactionService {
public void generateSampleTransactions() {
for (int i = 0; i < 50; i++) {
Transaction transaction = new Transaction();
transaction.setAccountId(UUID.randomUUID().toString());
transaction.setAmount(BigDecimal.valueOf(Math.random() * 1000));
transaction.setType(Math.random() > 0.5 ? "CREDIT" : "DEBIT");
transaction.setTimestamp(LocalDateTime.now());
transaction.setStatus("PENDING");
transactionRepository.save(transaction);
}
}
}
💡 Key Features
- Chunk-based processing (10 items per chunk)
- Automatic job parameter incrementation
- Error handling and logging
- Scheduled execution every 5 minutes
- In-memory H2 database for easy testing
🚀 Running the Application
- Clone the repository
- Run
mvn clean install - Start the application
- Access H2 console at
http://localhost:8080/h2-console - Watch the logs for batch job execution every 5 minutes
🔍 Monitoring
You can monitor the batch jobs through:
- Application logs
- H2 console for database inspection
- Spring Batch tables (BATCH_JOB_EXECUTION, BATCH_STEP_EXECUTION)