ruhungry ruhungry - 3 months ago 16
Java Question

Spring Batch - A job instance already exists: JobInstanceAlreadyCompleteException

I wrote an easy scheduler included in my Spring Application. I run my local server and after few seconds, in class Importer, checker.start() is being invoked each 5 seconds as how I configured in config file.

After that, this method invokes Job with JobLauncher and here I have got an error.

A job instance already exists and is complete for p arameters={}. If
you want to run this job again, change the parameters.

I found a solution how to fix it using annotation but I want to keep it this way.

Thank you in advance

public class Importer {

private Checker checker;

public Importer() {

public void myMethod() {
try {
} catch (ClientProtocolException e) {
} catch (IOException e) {

with .xml file:

<bean id="schedulerTask"
<property name="targetObject" ref="fileimport" />
<property name="targetMethod" value="myMethod" />

<bean id="fileimport" />
<property name="targetMethod" value" class="com...Importer">
<property name="checker">
<bean id="checker" class="com...Checker">


<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="schedulerTask" />
<property name="delay" value="${xyz.startdelay}" />
<property name="period" value="${xyz.checkinterval}" />

<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<ref local="scheduledTask" />

And property file:



In class Checker I have got the method:

static ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("/simplefile-context.xml");
Job job = (Job) applicationContext.getBean("fileBatch");
JobLauncher launcher = (JobLauncher) applicationContext.getBean("jobLauncher");
public void start() throws ClientProtocolException, IOException {
// ...
try {, new JobParameters());
} catch (Exception e) {

and my "simplefile-context.xml" file looks like this:

<bean id="jobRepository" class="">
<property name="transactionManager" ref="transactionManager"/>

<!-- bean for lauching the job -->
<bean id="jobLauncher" class="">
<property name="jobRepository" ref="jobRepository" />

<task:executor id="taskExecutor" pool-size="100" />

<!-- -->
<!-- JOBS -->
<!-- -->
<batch:job id="fileBatch" restartable="true">
<batch:step id="readLines" >
<batch:tasklet task-executor="taskExecutor" >
<batch:chunk reader="fileReader" writer="fooWriter" commit-interval="100" />

<bean id="fileReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="linesToSkip" value="1"/>
<property name="resource" value="file:./src/main/resources/sample.csv" />
<property name="lineMapper" ref="lineMapper" />

<bean id="lineMapper" class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer" ref="lineTokenizer"/>
<property name="fieldSetMapper" ref="fieldsetEntityMapper"/>

<bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value=";" />
<property name="names" value="field1,field2,field3,field4,field5,field6,field7" />
<property name="strict" value="false"/>

<bean id="fieldsetEntityMapper" class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="targetType" value="com...model.ModelObject"/>
<property name="customEditors">
<entry key="java.lang.Double">
<bean class="org.springframework.beans.propertyeditors.CustomNumberEditor">
<constructor-arg index="0" value="java.lang.Double"/>
<constructor-arg index="1" value="true"/>

<bean id="fooWriter" class="com...springbatch.writer.FooWriter" />


With your current setup you will only be able to launch the job only once., new JobParameters());

The job is unique identified by its id together with the parameters. Currently there is no way to make a distinction based on the parameters. Instead of adding new JobParameters() use the JobParamtersBuilderBuilder and add the current date and time.

JobParametersBuilder builder = new JobParametersBuilder();
builder.addDate("date", new Date());, builder.toJobParameters());

This will allow you to run the job multiple times.