Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring batch A job instance already exists

OK,

I know this has been asked before, but I still can't find a definite answer to my question. And my question is this: I am using spring batch to export data to SOLR search server. It needs to run every minute, so I can export all the updates. The first execution passes OK, but the second one complains with:

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 date-time 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 query 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 didn't provide the time parameter. So seems like I can run the job once and get the last execution time, or i can run it multiple times and not get the last execution time. I am really stuck :(

like image 812
Petar Tahchiev Avatar asked Oct 02 '14 18:10

Petar Tahchiev


People also ask

Is it possible to restart a completed job in Spring Batch?

By default, it does not allow completed jobs to be restarted. When a job is restarted, Spring Batch will create a new job execution for the particular job instance that failed, and it will restart at the failed step, executing from that point forward.

What is job instance in Spring Batch?

In Spring Batch, a Job is simply a container for Step instances. It combines multiple steps that belong logically together in a flow and allows for configuration of properties global to all steps, such as restartability. The job configuration contains: The simple name of the job.

What is Incrementer in Spring Batch?

This incrementer increments a "run.id" parameter of type Long from the given job parameters. If the parameter does not exist, it will be initialized to 1. The parameter name can be configured using setKey(String) .

What is Spring Batch Jobparameter?

JobParameters can be used for identification during the job run. They have reserved names, so to access them we can use Spring Expression Language. For example we can provide the following as job parameters- File path of the source location containing the files to be processed by String Batch.


2 Answers

Use the Job Explorer as suggested by Luca Basso Ricci.

Because you do not know the job parameters you need to look up by instance.

  1. Look for the last instance of job named searchExportJob
  2. Look for the last execution of the instance above

This way you use Spring Batch API only

//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());
 }

Note this code only work for Spring Batch 2.2.x and above in 2.1.x the API was somewhat different

like image 157
Haim Raman Avatar answered Oct 30 '22 15:10

Haim Raman


Assumption

Spring Batch use some tables to store each JOB executed with its parameters. If you run twice the job with the same parameters, the second one fails, because the job is identified by jobName and parameters.

1# Solution

You could use JobExecution when run 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 could implement a custom JobExecutionDao and perform a custom query to find your JobExecution on BATCH_JOB_EXECUTION table. See here the reference of Spring.

I hope my answer is helpful to you.

like image 36
Xstian Avatar answered Oct 30 '22 14:10

Xstian