Spring batch job instance already exists
OK
I know this has been asked before, but I still cannot find a definitive answer to my question. And my question is this: I am using spring package to export data to SOLR search server. It should run every minute, so I can export all updates. The first execution runs fine, but the second complains:
2014-10-02 20:37:00,022 [defaultTaskScheduler-1] ERROR: catching
org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={catalogVersionPK=3378876823725152,
type=UPDATE}. If you want to run this job again, change the parameters.
at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:126)
at
Of course, I can add a datetime parameter to the job like this:
.addLong("time", System.getCurrentTimeMillis())
and then the job can be run more than once. However, I also want to request the last execution of the job, so I have code like this:
DateTime endTime = new DateTime(0);
JobExecution je = jobRepository.getLastJobExecution("searchExportJob", new JobParametersBuilder().addLong("catalogVersionPK", catalogVersionPK).addString("type", type).toJobParameters());
if (je != null && je.getEndTime() != null) {
endTime = new DateTime(je.getEndTime());
}
and this returns nothing because I have not provided a time parameter. It seems I can run the job once and get the latest execution time, or I can run it multiple times and not get the last execution time. I am really stuck :(
source to share
Use the quest guide suggested by Luca Basso Ricci.
Since you don't know the job parameters you need to search by instance.
- Look for the latest instance of a job named searchExportJob
- Find the latest execution of the instance above
This way you only use Spring Batch API
//We can set count 1 because job instance are ordered by instance id descending
//so we know the first one returned is the last instance
List<JobInstance> instances = jobExplorer.getJobInstances("searchExportJob",0,1);
JobInstance lastInstance = instances.get(0);
List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(lastInstance);
//JobExcectuin is ordered by execution id descending so first
//result is the last execution
JobExecution je = jobExecutions.get(0);
if (je != null && je.getEndTime() != null) {
endTime = new DateTime(je.getEndTime());
}
Please note that this code only works for Spring Batch 2.2.x and higher in 2.1.x the API was slightly different
source to share
Assumption
Spring Batch use some tables to store each task being run with its parameters. If you run a job twice with the same parameters, the second fails because the job is identified by name_name and parameters.
1 # Solution
You can use JobExecution when starting a new job.
JobExecution execution = jobLauncher.run(job, new JobParameters());
.....
// Use a JobExecutionDao to retrieve the JobExecution by ID
JobExecution ex = jobExecutionDao.getJobExecution(execution.getId());
2 # Solution
You can implement a custom JobExecutionDao and run a custom query to find the JobExecution
on table BATCH_JOB_EXECUTION
.
See Spring link here .
Hope my answer helps you.
source to share
There is another interface that you can use: JobExplorer
From your javadoc:
Entry point to view the progress of work or historical orders and steps. Since data can be re-hydrated from persistent storage, it may not contain volatile fields that would be active
source to share