Archive for February 7th, 2010

07
Feb
10

Multiple Batch Runs with Spring Batch

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

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




Follow

Get every new post delivered to your Inbox.

Join 34 other followers