Spring Batch after JVM crash

纵然是瞬间 提交于 2019-12-09 17:25:29

问题


How to restart Jobs after a JVM crash?

I was running a lot of Jobs implemented in Spring Batch framework, when my JVM crashed or the system failed. How can I restart these Jobs after failure?


回答1:


Basically, you can do as follows:

  1. Configure a JobExplorer factory bean in your application context:

  2. Configure a JobOperator bean in your applictaion context

  3. Query the jobExplorer for distinct job names: jobExplorer.getJobNames()

  4. For each job from step (3), query the jobExplorer for unfinished jobs: jobExplorer.findRunningJobExecutions(String jobName)

  5. For each JobExecution from step (4) invoke:jobOperator.restart(jobExecution.getJobId())

  6. Make sure to call this procedure during boot sequence, before any other job is launched

Technically it is possible to merge steps 3+4 for something like findRunningJobExecutions() by overriding JobExecutionDao, but the current API doesn't support it.

For help in aforementioned Spring bean configuration, consult the reference documentation




回答2:


You need to mark the "running" jobs as failed before restarting them, like this:

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

    for (JobExecution runningJob : runningJobs) {
        try {
            runningJob.setStatus(BatchStatus.FAILED);
            runningJob.setEndTime(new Date());
            jobRepository.update(runningJob);
            jobOperator.restart(runningJob.getId());
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }
}



回答3:


Here is the complete solution to restart a job after JVM crash.

  1. Make a job restartable by making restarable="true"

job id="jobName" xmlns="http://www.springframework.org/schema/batch" restartable="true"

2 . Code to restart a job

import java.util.Date;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;

public class ResartJob {

    @Autowired
    private JobExplorer jobExplorer;
    @Autowired
    JobRepository jobRepository;
    @Autowired
    private JobLauncher jobLauncher;
    @Autowired 
    JobOperator jobOperator;

    public void restart(){
        try {
            List<JobInstance> jobInstances = jobExplorer.getJobInstances("jobName",0,1);// this will get one latest job from the database
            if(CollectionUtils.isNotEmpty(jobInstances)){
               JobInstance jobInstance =  jobInstances.get(0);
               List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(jobInstance);
               if(CollectionUtils.isNotEmpty(jobExecutions)){
                   for(JobExecution execution: jobExecutions){
                       // If the job status is STARTED then update the status to FAILED and restart the job using JobOperator.java
                       if(execution.getStatus().equals(BatchStatus.STARTED)){ 
                           execution.setEndTime(new Date());
                           execution.setStatus(BatchStatus.FAILED);                               
                           execution.setExitStatus(ExitStatus.FAILED);                               
                           jobRepository.update(execution);
                           jobOperator.restart(execution.getId());
                       }
                   }
               }
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
}

3.

<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean" p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" p:lobHandler-ref="oracleLobHandler"/>

<bean id="oracleLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>


<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean" p:dataSource-ref="dataSource" />

<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />

<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository" />
        <property name="taskExecutor" ref="jobLauncherTaskExecutor" />
</bean>
<task:executor id="jobLauncherTaskExecutor" pool-size="6" rejection-policy="ABORT" />

<bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator" p:jobLauncher-ref="jobLauncher" p:jobExplorer-re`enter code here`f="jobExplorer" p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry"/>


来源:https://stackoverflow.com/questions/15461040/spring-batch-after-jvm-crash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!