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 :(

+3


source to share


3 answers


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

+3


source


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.

+1


source


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

+1


source







All Articles