Reputation: 343
I tried the spring batch retry in this example. Retry feature is not working in Spring Batch and it works. I am trying to achieve the same with retrytemplate, but couldn't see the retry not working when thrown exception.
@Configuration
@EnableBatchProcessing
//@EnableRetry
public class RetryBatchJob {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public ItemReader<Integer> itemReader() {
return new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}
@Bean
public ItemWriter<Integer> itemWriter() {
return items -> {
for (Integer item : items) {
System.out.println("item = " + item);
if (item.equals(7)) {
throw new Exception("Sevens are sometime nasty, let's retry them");
}
}
};
}
@Bean
public Step step() {
return steps.get("step")
.<Integer, Integer>chunk(2)
.reader(itemReader())
.writer(itemWriter())
/*.faultTolerant()
.retryLimit(5)
.retry(Exception.class)*/
.build();
}
@Bean
public Job job() {
Job job = null;
try {
job = retryTemplate().execute(new RetryCallback<Job, Throwable>() {
@Override
public Job doWithRetry(RetryContext context) throws Throwable {
return jobs.get("job")
.start(step())
.build();
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return job;
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(RetryBatchJob.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(5, singletonMap(Exception.class, true));
retryPolicy.setMaxAttempts(5);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
Am I missing something when I use RetryTemplate? I tried declarative configuration on step and job methods too, but no luck.
@Retryable(value = {Exception.class},
maxAttemptsExpression = "5"
)
Note: using spring-retry 1.2.2 RELEASE.
Upvotes: 1
Views: 2551
Reputation: 11
Thrown exceptions during job execution do not stop the execution, the job continue until it returns the execution result either FAILED OR COMPLETED ... Which makes it a positive result for RetryTemplate.execute(). You can take advantage of the execution status returned to throw a runtimeException in case of failure.
RetryTemplate template = new RetryTemplate();
ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy();
exponentialBackOffPolicy.setInitialInterval(5000);
exponentialBackOffPolicy.setMultiplier(ExponentialBackOffPolicy.DEFAULT_MULTIPLIER);
exponentialBackOffPolicy.setMaxInterval(ExponentialBackOffPolicy.DEFAULT_MAX_INTERVAL);
Map<Class<? extends Throwable>, Boolean> exceptions = new HashMap<>();
exceptions.put(Exception.class, true);
SimpleRetryPolicy policy = new SimpleRetryPolicy(3, exceptions);
template.setRetryPolicy(policy);
template.setBackOffPolicy(exponentialBackOffPolicy);
template.execute(new RetryCallback<JobExecution, Exception>() {
@Override
public JobExecution doWithRetry(RetryContext context) throws Exception {
return runJob(job, paramMap);
}
});
Function: runJob()
public JobExecution runJob(Job job, Map<String, JobParameter> paramMap) throws Exception {
JobExecution exe = jobLauncher.run(job, new JobParameters(paramMap));
if(exe.getStatus().equals(BatchStatus.FAILED))
throw new RuntimeException(exe.toString());
return exe;
}
Upvotes: 1
Reputation: 31590
The method @Bean public Job job() { ... }
is intended to define a Spring Bean of type Job
. According to your code, you are calling retryTemplate().execute
inside this method and expecting the job to be retried. This is not correct.
What you can try is first define your job like:
@Bean
public Job job() {
return jobs.get("job")
.start(step())
.build();
}
then call the retry template on the job bean you get from the application context in the main
method, something like:
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(RetryBatchJob.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
RetryTemplate retryTemplate = context.getBean(RetryTemplate.class);
retryTemplate.execute(new RetryCallback<JobExecution, Exception>() {
@Override
public JobExecution doWithRetry(RetryContext context) throws Exception {
return jobLauncher.run(job, new JobParameters());
};
});
}
If I understand correctly, you are trying to automatically retry a failed job with a retry template, something similar to what is suggested in this PR: https://github.com/spring-projects/spring-batch/pull/440.
Anyway, I hope the example helps.
Upvotes: 0