I am trying to stop and restart a spring batch job in every 10
seconds. I am trying to do this with job_execution_id
but it throws an error saying "No job configuration with the name [loadUserJob] was registered"
.
This is a test application for a real process where I want to start and stop on specific time of the day. Here is the scheduler method.
@Scheduled(cron = "*/10 * * * * *")
public void batchScheduler() {
LOG.info("---Beginning of batchScheduler()---");
if(isRunning) {
try {
LOG.info("....stopping the job!");
LOG.info("-----------> 2");
jobExecutionId = jobRepository.getLastJobExecution("dataFilterJob", jobParameter).getId();
LOG.info("##### ExecutionID-1: " + jobExecutionId);
this.isRunning = false;
this.jobOperator.stop(jobExecutionId);
} catch (NoSuchJobExecutionException | JobExecutionNotRunningException e) {
this.isRunning = true;
LOG.info("Error in Stopping job!!");
e.printStackTrace();
}
}
else {
try {
LOG.info("Restarting the job....");
LOG.info("-----------> 3");
LOG.info("##### ExecutionID-2: " + jobExecutionId);
this.isRunning = true;
this.jobOperator.restart(jobExecutionId);
} catch (JobInstanceAlreadyCompleteException | NoSuchJobExecutionException | NoSuchJobException
| JobRestartException | JobParametersInvalidException e) {
this.isRunning = false;
LOG.info("Error in Restarting the job!!");
e.printStackTrace();
}
}
LOG.info("---End of batchScheduler()---");
}
jobRepository
and jobOperator
are autowired in the same class. Not sure why it can't find the job with stopped execution id.
Here is the whole class. I am using CommandLineRunner
@SpringBootApplication
@EnableScheduling
public class DatafilterBatchApplication implements CommandLineRunner{
public static final Logger LOG = LogManager.getLogger(DatafilterBatchApplication.class);
@Autowired
private JobLauncher jobLauncher;
@Autowired
private ApplicationContext context;
@Autowired
private JobRepository jobRepository;
@Autowired
private JobOperator jobOperator;
@Autowired
private JobExplorer jobExplorer;
@Autowired
private JobRegistry jobRegistry;
long jobExecutionId;
boolean isRunning = false;
boolean isNotRunning = false;
private String batchName;
private String filePath;
private long currentMillis = System.currentTimeMillis();
private JobParameters jobParameter;
public static void main(String[] args) {
SpringApplication.run(DatafilterBatchApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
LOG.info("---Beginning of run()---");
try {
if(args.length == 2) {
batchName = args[0];
filePath = args[1];
jobParameter = new JobParametersBuilder()
.addLong("time", currentMillis)
.addString("inputFile", filePath)
.toJobParameters();
ExitStatus exitStatus = jobController(jobParameter);
LOG.info("Job completed with status-" + exitStatus);
}else {
LOG.info("Invalid Job Parameters!!");
}
} catch (Exception e) {
e.printStackTrace();
}
LOG.info("---End of run()---");
}
public ExitStatus jobController(JobParameters jobParameters) {
LOG.info("---Beginning of jobController()---");
Job job = this.context.getBean("dataFilterJob", Job.class);
ExitStatus exitStatus = ExitStatus.UNKNOWN;
try {
isRunning = true;
exitStatus = jobLauncher.run(job, jobParameters).getExitStatus();
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
LOG.info("Error in launching job!!");
e.printStackTrace();
}
LOG.info("---End of jobController()---");
return exitStatus;
}
@Scheduled(cron = "*/10 * * * * *")
public void batchScheduler() {
LOG.info("---Beginning of batchScheduler()---");
if(isRunning) {
try {
LOG.info("....stopping the job!");
LOG.info("-----------> 2");
jobExecutionId = jobRepository.getLastJobExecution("dataFilterJob", jobParameter).getId();
LOG.info("##### ExecutionID-1: " + jobExecutionId);
this.isRunning = false;
this.jobOperator.stop(jobExecutionId);
} catch (NoSuchJobExecutionException | JobExecutionNotRunningException e) {
this.isRunning = true;
LOG.info("Error in Stopping job!!");
e.printStackTrace();
}
}
else {
try {
LOG.info("Restarting the job....");
LOG.info("-----------> 3");
LOG.info("##### ExecutionID-2: " + jobExecutionId);
this.isRunning = true;
this.jobOperator.restart(jobExecutionId);
} catch (JobInstanceAlreadyCompleteException | NoSuchJobExecutionException | NoSuchJobException
| JobRestartException | JobParametersInvalidException e) {
this.isRunning = false;
LOG.info("Error in Restarting the job!!");
e.printStackTrace();
}
}
LOG.info("---End of batchScheduler()---");
}
}
Here is the exception screenshot:
UPDATE
I tried JobRegistryBeanPostProcessor
to set JobRegistry
and it seems working
@Autowired
private JobRegistry jobRegistry;
@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}
But now it turned out that the scheduler is called only twice and after the second call it is never been called so the batch never ends. Is that a Scheduler
issue or JobRegistryBeanPostProcessor
is causing this ? because if I remove it then the Scheduler
is called frequently at every 10
seconds but throwing same error: "org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [dataFilterJob] was registered."
Here is the whole updated class:
@SpringBootApplication
@EnableScheduling
public class DatafilterBatchApplication implements CommandLineRunner{
public static final Logger LOG = LogManager.getLogger(DatafilterBatchApplication.class);
@Autowired
private JobLauncher jobLauncher;
@Autowired
private ApplicationContext context;
@Autowired
private JobRepository jobRepository;
@Autowired
private JobRegistry jobRegistry;
@Autowired
private JobOperator jobOperator;
@Autowired
private JobExplorer jobExplorer;
private String jobName;
private JobParameters jobParameters;
private String completionStatus;
boolean isRunning = false;
private String filePath;
@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}
public static void main(String[] args) {
SpringApplication.run(DatafilterBatchApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
LOG.info("---Beginning of run()---");
try {
if(args.length == 2) {
jobName = args[0];
filePath = args[1];
ExitStatus exitStatus = jobController(jobName, filePath);
LOG.info("Job completed with status-" + exitStatus);
}else {
LOG.info("Invalid Job Parameters!!");
}
} catch (Exception e) {
e.printStackTrace();
}
LOG.info("---End of run()---");
}
public ExitStatus jobController(String jobName, String fileName) {
LOG.info("---Beginning of jobController()---");
Job job = this.context.getBean(jobName, Job.class);
ExitStatus exitStatus = ExitStatus.UNKNOWN;
jobParameters = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.addString("inputFile", fileName)
.toJobParameters();
try {
isRunning = true;
exitStatus = jobLauncher.run(job, jobParameters).getExitStatus();
if(exitStatus.getExitCode().equals(ApplicationConstants.JOB_EXITSTATUS_STOPPED)) {
isRunning = false;
}
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
LOG.info("Error in launching job!!");
isRunning = false;
e.printStackTrace();
}
LOG.info("---End of jobController()---");
return exitStatus;
}
@Scheduled(cron = "*/10 * * * * *")
public void batchScheduler() {
LOG.info("---Beginning of batchScheduler()---");
if(isRunning) {
try {
LOG.info("....stopping the job!");
this.isRunning = false;
jobOperator.stop(jobRepository.getLastJobExecution(jobName, this.jobParameters).getId());
} catch (NoSuchJobExecutionException | JobExecutionNotRunningException e) {
this.isRunning = true;
LOG.info("Error in Stopping job!!");
e.printStackTrace();
}
}else {
try {
LOG.info("Restarting the job....");
this.isRunning = true;
jobOperator.restart(jobRepository.getLastJobExecution(jobName, this.jobParameters).getId());
} catch (JobInstanceAlreadyCompleteException | NoSuchJobExecutionException | NoSuchJobException
| JobRestartException | JobParametersInvalidException e) {
this.isRunning = false;
LOG.info("Error in Restarting the job!!");
e.printStackTrace();
}
}
LOG.info("---End of batchScheduler()---");
}
}
UPDATE
I think the issue was with JobOperator
and as I updated before JobRegistryBeanPostProcessor
would be the solution. But as I mentioned my scheduler is called only twice. So once the application starts, it calls after 10
seconds and stop the running job. It again call one more time after 10
seconds and restart the job and that's all. The scheduler never gets called. So the job just continue to run. I have cron for mat as - (cron = "*/10 * * * * *") so it should be calling in every 10
seconds. Can anyone help me to find out what is going on here. Is that something to do with my scheduler ?
UPDATE
I think I should take back