Robust Error Handling in Spring Batch Using SkipPolicy
In real-world batch processing, data inconsistencies and malformed records are common. Spring Batch provides a robust mechanism to handle such scenarios gracefully using SkipPolicy
. This tutorial explains how to skip faulty records during processing and log them for later review.
๐ What is SkipPolicy?
SkipPolicy is a Spring Batch interface that determines whether a particular exception should cause the step to skip the current item and continue processing or fail the job. This allows you to define custom logic for what should be considered skippable.
๐ง Maven 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>
⚙️ application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.batch.job.enabled=false
๐งฑ Employee Entity
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// Getters and Setters
}
๐ Sample CSV File (employees.csv)
name,email
John,john@example.com
InvalidUser,invalid-email
Jane,jane@example.com
๐ง Custom SkipPolicy
public class EmailValidationSkipPolicy implements SkipPolicy {
@Override
public boolean shouldSkip(Throwable t, int skipCount) {
return t instanceof IllegalArgumentException && skipCount < 5;
}
}
๐ ItemProcessor with Validation
public class EmployeeItemProcessor implements ItemProcessor<Employee, Employee> {
@Override
public Employee process(Employee employee) throws Exception {
if (employee.getEmail() == null || !employee.getEmail().contains("@")) {
throw new IllegalArgumentException("Invalid email: " + employee.getEmail());
}
return employee;
}
}
⚙️ Spring Batch Configuration
@Configuration
public class BatchConfig {
@Autowired private JobRepository jobRepository;
@Autowired private PlatformTransactionManager transactionManager;
@Autowired private EntityManagerFactory entityManagerFactory;
@Bean
public Job job() {
return new JobBuilder("employee-import-job", jobRepository)
.start(step())
.incrementer(new RunIdIncrementer())
.build();
}
@Bean
public Step step() {
return new StepBuilder("import-step", jobRepository)
.<Employee, Employee>chunk(5, transactionManager)
.reader(reader())
.processor(new EmployeeItemProcessor())
.writer(writer())
.faultTolerant()
.skipPolicy(new EmailValidationSkipPolicy())
.build();
}
@Bean
public FlatFileItemReader<Employee> reader() {
return new FlatFileItemReaderBuilder<Employee>()
.name("employee-reader")
.linesToSkip(1)
.resource(new ClassPathResource("employees.csv"))
.delimited()
.names("name", "email")
.targetType(Employee.class)
.build();
}
@Bean
public JpaItemWriter<Employee> writer() {
JpaItemWriter<Employee> writer = new JpaItemWriter<>();
writer.setEntityManagerFactory(entityManagerFactory);
return writer;
}
}
๐ REST Controller to Trigger the Job
@RestController
@RequestMapping("/jobs")
public class JobLauncherController {
@Autowired private JobLauncher jobLauncher;
@Autowired private Job job;
@GetMapping("/run-skip-job")
public String runJob() throws Exception {
JobParameters params = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(job, params);
return "Job launched!";
}
}
๐ Summary
- We used
SkipPolicy
to skip faulty records with invalid emails. - Errors are gracefully ignored while keeping track of skipped records.
- Only valid records are written to the database.
๐บ Want to learn Spring with hands-on videos?
Subscribe to our YouTube channel: Spring Java Lab for practical tutorials on Spring Batch, Boot, and more!
Subscribe to our YouTube channel: Spring Java Lab for practical tutorials on Spring Batch, Boot, and more!