In this post under Spring Batch, I will explain how to retry a Job if it fails in the first attempt.
When processing records in batch, they may be exceptions thrown that will force us to stop the processing further and they may be exceptions thrown at first attempt but in next attempt that exceptions are not thrown again resulting in successful processing of the job.
So whenever an exception is thrown it is better to retry again may be in the next attempt the exception is gone and the job is successful.
Spring Batch provides this retry feature.
For our example, we will create a simulator class named “ExceptionSimulator” that will throw exception when reading records at odd position, as shown below
package package31;
import org.springframework.batch.item.ItemProcessor;
public class ExceptionSimulator implements ItemProcessor<Employee, Employee> {
int count = 0;
@Override
public Employee process(Employee employee) throws Exception {
Employee employee1 = null;
if (count % 2 == 0) {
employee1 = employee;
count = count + 1;
} else if (count %2 == 1) {
System.out.println("retry record: " + employee);
count = 0;
throw new IllegalArgumentException();
}
return employee1;
}
}
Employee records at even position are returned as it is but records at odd position will throw IllegalArgumentException.
Now we have to configure Spring Batch in such a way that when IllegalArgumentException is thrown it retry processing records from start again for 5 times. If at the sixth attempt same exception is thrown, further processing of records will be stopped. This is done as shown in the below xml configuration
1 <batch:job id="importEmployees">
2 <batch:step id="readWriteEmployees">
3 <batch:tasklet start-limit="2">
4 <batch:chunk reader="reader" writer="writer" commit-interval="50" retry-limit="5" processor="exceptionSimulator">
5 <batch:retryable-exception-classes>
6 <batch:include class="java.lang.IllegalArgumentException"/>
7 </batch:retryable-exception-classes>
8 </batch:chunk>
9 </batch:tasklet>
10 </batch:step>
11 </batch:job>
In the above xml code, at line 4, we set the number of times to retry to 5 by using the attribute “retry-limit”.
Next from line 5 to 7 we tell Spring Batch, what exception to retry by using the “retryable-exception-classes” element.
Below is the complete xml configuration for your reference
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">
<bean id="employee" class="package31.Employee" scope="prototype"/>
<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="file:FileInput.txt"/>
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="id,name,status,salary"/>
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="prototypeBeanName" value="employee"/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="writer" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="file:FileOutput.txt"/>
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="fieldExtractor">
<bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<property name="names" value="id,name,status,salary"/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="exceptionSimulator" class="package31.ExceptionSimulator" />
<batch:job id="importEmployees">
<batch:step id="readWriteEmployees">
<batch:tasklet start-limit="2">
<batch:chunk reader="reader" writer="writer" commit-interval="50" retry-limit="5" processor="exceptionSimulator">
<batch:retryable-exception-classes>
<batch:include class="java.lang.IllegalArgumentException"/>
</batch:retryable-exception-classes>
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
</beans>