This page describes the process of setting up your spring batch programs to run multiple times without specifying a new parameter. Sometimes specifying a new unique parameter is not a big deal. In that case that would be the preferred approach.
If you are getting the following errors this page will definitely help:
- A job instance already exists and is complete for parameters
- JobInstanceAlreadyCompleteException
The reason why these errors occur is that Spring Batch ensures against accidental job executions. As you can imagine something like that could be detrimental to the health of your business or your reputation.
example: customer gets billed twice etc…
Spring batch looks for differences in parameters that are used to execute your job:
mvn exec:java -Dexec.mainClass=org.springframework.batch.core.launch.support.CommandLineJobRunner -Dexec.args="simpleJob.xml helloWorldJob run.id=1"
In the above code you can see that run.id parameter has been entered. Spring Batch will check the JobRepository to see if this job parameter has run before. If it has it will throw the errors you saw in the bulleted list above.
Requirements
- No real requirements for this one. Just knowledge of the basics of Spring Batch.
- A quick look at my previous posting for some Background Information
Generating a run ID dynamically
As with many systems that run automated, generating a new ID in each batch run could be a problem. There is a method to have spring generate a new run id without changing the command to execute the job. Please keep in mind that by doing this your program will need to take the responsibility of detecting duplicate runs.
Make the following simple changes
Define the job Explorer. This object is like a read only job repository. It is used by various parts of the spring batch to read the status of executed jobs.
<beans:bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"> <beans:property name="dataSource" ref="dataSource"/> </beans:bean>
This is a an incrementor that is used to bump up the run.id parameter.
package com.test;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersIncrementer;
public class SampleIncrementer implements JobParametersIncrementer {
public JobParameters getNext(JobParameters parameters) {
System.out.println("got job parameters: " + parameters);
if (parameters==null || parameters.isEmpty()) {
return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters();
}
long id = parameters.getLong("run.id",1L) + 1;
return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
}
}
Add the following to your spring Configuration file…
<beans:bean name="sampleIncrementer" class="com.test.SampleIncrementer"/>
Update your job’s definition to include an incrementer.
<job id="helloWorldJob" incrementer="sampleIncrementer"> ... </job>
Run Your Job With “-next” Parameter
Last but not least you need to provide a -next parameter to the job. This allows the CommandLineJobRunner to execute your Incrementer.
Run your job multiple times without the worry of changing job parameters.
mvn exec:java -Dexec.mainClass=org.springframework.batch.core.launch.support.CommandLineJobRunner -Dexec.args="simpleJob.xml helloWorldJob -next"
References
- http://static.springsource.org/spring-batch/
- http://blog.springsource.com/2008/05/30/running-a-spring-batch-job-in-the-springsource-aplication-platform/
Nice approach, but I found it much more convenient to simply add a new unique parameter to the batch, containing e.g. the current time.
Thanks for your comment!
You are right. Adding a date would definitely work!
Doing it the way described on this page allows the programmer to implement a check for duplicate runs in the “SampleIncrementer” class described above. If it is in fact a duplicate run you can stop the execution right there. The logic of checking the duplicate run would nicely be encapsulated in that class.
Thanks this was really very helpful for me as i had similar requirement.
I used the following command.
mvn exec:java -Dexec.mainClass=org.springframework.batch.core.launch.support.CommandLineJobRunner -Dexec.args=”META-INF/applicationContext.xml job jobName=generateFile -next”
and it worked like a charm
I have one more requirement where I need to use an executable Jar.
I want to run the job using CommandLineJobRunner by taking the required files from that executablejar not from target folder of project(in production system i can copy only executable jar not source with target folder)
say i have placed the jar scheduler-1.0.one-jar.jar & batch file scheduler.bat(containing command script to run the job using CommandLineJobRunner) in folder C:\a\
i must be able to run the batch file which takes required classfiles, classpath from that executable jar
Can you please help me out in this ?
The following tutorial describes how to Package and deploy the application as a self contained jar.