Spring Batch restart uncompleted jobs from the same execution and step

Multi tool use
Multi tool use
The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


Spring Batch restart uncompleted jobs from the same execution and step



I use the following logic to restart the Spring Batch uncompleted(for example after application abnormal termination) jobs:


public void restartUncompletedJobs() {

LOGGER.info("Restarting uncompleted jobs");

try {
jobRegistry.register(new ReferenceJobFactory(documetPipelineJob));

List<String> jobs = jobExplorer.getJobNames();
for (String job : jobs) {
Set<JobExecution> runningJobs = jobExplorer.findRunningJobExecutions(job);

for (JobExecution runningJob : runningJobs) {
runningJob.setStatus(BatchStatus.FAILED);
runningJob.setEndTime(new Date());
jobRepository.update(runningJob);
jobOperator.restart(runningJob.getId());
LOGGER.info("Job restarted: " + runningJob);
}
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}



This works fine but with one side effect - it doesn't restart the failed job execution but creates a new execution instance. How to change this logic in order to restart the failed execution from the failed step and do not create a new execution ?



UPDATED



When I try the following code:


public void restartUncompletedJobs() {
try {
jobRegistry.register(new ReferenceJobFactory(documetPipelineJob));

List<String> jobs = jobExplorer.getJobNames();
for (String job : jobs) {

Set<JobExecution> jobExecutions = jobExplorer.findRunningJobExecutions(job);

for (JobExecution jobExecution : jobExecutions) {
jobOperator.restart(jobExecution.getId());
}
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}



it fails with the following exception:


2018-07-30 06:50:47.090 ERROR 1588 --- [ main] c.v.p.d.service.batch.BatchServiceImpl : Illegal state (only happens on a race condition): job execution already running with name=documetPipelineJob and parameters={ID=826407fa-d3bc-481a-8acb-b9643b849035, inputDir=/home/public/images, STORAGE_TYPE=LOCAL}

org.springframework.batch.core.UnexpectedJobExecutionException: Illegal state (only happens on a race condition): job execution already running with name=documetPipelineJob and parameters={ID=826407fa-d3bc-481a-8acb-b9643b849035, inputDir=/home/public/images, STORAGE_TYPE=LOCAL}
at org.springframework.batch.core.launch.support.SimpleJobOperator.restart(SimpleJobOperator.java:283) ~[spring-batch-core-4.0.1.RELEASE.jar!/:4.0.1.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobOperator$$FastClassBySpringCGLIB$$44ee6049.invoke(<generated>) ~[spring-batch-core-4.0.1.RELEASE.jar!/:4.0.1.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-5.0.6.RELEASE.jar!/:5.0.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684) [spring-aop-5.0.6.RELEASE.jar!/:5.0.6.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobOperator$$EnhancerBySpringCGLIB$$7659d4c.restart(<generated>) ~[spring-batch-core-4.0.1.RELEASE.jar!/:4.0.1.RELEASE]
at com.example.pipeline.domain.service.batch.BatchServiceImpl.restartUncompletedJobs(BatchServiceImpl.java:143) ~[domain-0.0.1.jar!/:0.0.1]



The following code creates new executions in jobstore database:


public void restartUncompletedJobs() {
try {
jobRegistry.register(new ReferenceJobFactory(documetPipelineJob));

List<String> jobs = jobExplorer.getJobNames();
for (String job : jobs) {

Set<JobExecution> jobExecutions = jobExplorer.findRunningJobExecutions(job);

for (JobExecution jobExecution : jobExecutions) {

jobExecution.setStatus(BatchStatus.STOPPED);
jobExecution.setEndTime(new Date());
jobRepository.update(jobExecution);

Long jobExecutionId = jobExecution.getId();
jobOperator.restart(jobExecutionId);
}
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}

}



The question is - how to continue to run the old uncompleted executions without creating new ones after application restart?





Please don't duplicate questions. See my answer in stackoverflow.com/questions/51568654/…
– Mahmoud Ben Hassine
yesterday







This is not duplication - this question relates to a simple restart of uncompleted jobs from the same execution and step. The linked question relates to restart of uncompleted jobs in the clustered environment. I apologize, but your answer doesn't solve the described issue there. It is not clear how to distinguish uncompleted and not running jobs from uncompleted but running jobs.
– alexanoid
yesterday





On the single node cluster, after application restart, I'm pretty sure that there is no one running job at this moment and can restart all of them but in the multi-node cluster with a shared job repository - I don't know what exact job is running and what - not.
– alexanoid
yesterday





Well, if you change the question there, How do you want the answer to still solve the issue described there?
– Mahmoud Ben Hassine
yesterday





"how to continue to run the old uncompleted executions without creating new ones after application restart?" > The design of Spring batch does not work like this. Whenever you submit a job, it create a new execution. However if you are submitting a job with param of a failed job instance, a new Job execution will be created, starting from the previously failed position.
– Adrian Shum
18 hours ago






1 Answer
1



TL;DR: Spring Batch will always create new Job Execution and will not reuse a previous failed job execution to continue its execution.



Longer answer: First you need to understand three similar but different concept in Spring Batch: Job, Job Instance, Job Execution



I always use this example:



In high-level, that's how Spring Batch's recovery works:



Assuming your first execution failed in the step 3. You can submit the same Job (End-of-Day Batch) with same Parameters (2018-01-01). Spring Batch will try to look up last Job Execution (End-Of-Day Batch for 2018-01-01, execution #1) of the submitted Job Instance (End-of-Day Batch for 2018-01-01), and found that it has previously failed in step 3. Spring Batch will then create a NEW execution, [End-Of-Day Batch for 2018-01-01, execution #2], and start the execution from step 3.



So by design, what Spring trying to recover is a previously failed Job Instance (instead of Job Execution). Spring batch will not reuse execution when you are re-running a previous-failed execution.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

0UHvxHM,wC8Z1P,5HO,1zZFS78D0Ez2wgxB9wEIU3zjWrf,TDWG2w qlyhDfyd2o8dnS,HoxJyS XwjmTPI,6iIkCV,1Sx0f8E 8,5KS2
tcY9yqxwyF9lf0 skOfwpXlkRGhkjR

Popular posts from this blog

Makefile test if variable is not empty

Visual Studio Code: How to configure includePath for better IntelliSense results

Will Oldham