Spring Batch Job is composed of Reader, Processor and Writer. This post shows some more details on Reader.
Reader is the implementation of org.springframework.batch.item.Reader. I recommend to use the following implementations.
- AmqpItemReader (org.springframework.batch.item.amqp.AmqpItemReader) : to interact with queue such as RabbitMQ
- FlatFileItemReader (org.springframework.batch.item.file.FlatFileItemReader) : to interact with a file
- JdbcCursorItemReader (org.springframework.batch.item.database.JdbcCursorItemReader) : to interact with a database
Or you can make a custom Reader.
I’ll show you some examples with JdbcCursorItemReader. But the tips can be applied to the other implementations.
Passing parameters
When reading a table, we need to pass parameters to the sql. JdbcCursorItemReader use JDBC sql format. Therefore, parameters are defined as “?” marker. (For example, SELECT COL1, COL2, COL3 FROM TB_SOURCE WHERE COL1 = ?)
JdbcCursorItemReader use a PreparedStatementSetter bean to set parameter. The following is a sample Reader definition.
<bean id="SourceMapper" | |
class="test.rowmapper.TbSourceMapper"/> | |
<bean id="ParameterSetter" class="test.reader.TestParameterSetter"> | |
<property name="param" value="col1-1"/> | |
</bean> | |
<bean id="TestReader" | |
class="org.springframework.batch.item.database.JdbcCursorItemReader" | |
scope="step"> | |
<property name="dataSource" ref="testDataSource"/> | |
<property name="sql" | |
value="SELECT COL1, COL2, COL3 | |
FROM TB_SOURCE | |
WHERE COL1 = ?"/> | |
<property name="rowMapper" | |
ref="SourceMapper"/> | |
<property name="preparedStatementSetter" ref="ParameterSetter"/> | |
<property name="fetchSize" value="100" /> | |
<property name="maxRows" value="0" /> | |
</bean> |
Notice that TestReader has preparedStatementSetter property.
The following is the sample parameter setter bean.
import java.sql.PreparedStatement; | |
import java.sql.SQLException; | |
import org.springframework.jdbc.core.PreparedStatementSetter; | |
public class TestParameterSetter implements PreparedStatementSetter { | |
private String param; | |
public void setParam(String param) { | |
this.param = param; | |
} | |
@Override | |
public void setValues(PreparedStatement ps) throws SQLException { | |
ps.setString(1, this.param); | |
} | |
} |
Parameter setter must implement org.springframework.jdbc.core.PreparedStatementSetter.
Passing parameter from outer environment
Above sample is setting parameter value at Spring context.xml. But sometimes, we need to get the value from outer environment. Spring Batch supports it with JobParameter. It can be set when we invoke Spring Batch job.
The following is modified Reader definition.
<bean id="SourceMapper" | |
class="test.rowmapper.TbSourceMapper"/> | |
<bean id="ParameterSetter" class="test.reader.TestParameterSetter" scope="step"> | |
<property name="param" value="#{jobParameters['param1']}"/> | |
</bean> | |
<bean id="TestReader" | |
class="org.springframework.batch.item.database.JdbcCursorItemReader" | |
scope="step"> | |
<property name="dataSource" ref="testDataSource"/> | |
<property name="sql" | |
value="SELECT COL1, COL2, COL3 | |
FROM TB_SOURCE | |
WHERE COL1 = ?"/> | |
<property name="rowMapper" | |
ref="SourceMapper"/> | |
<property name="preparedStatementSetter" ref="ParameterSetter"/> | |
<property name="fetchSize" value="100" /> | |
<property name="maxRows" value="0" /> | |
</bean> |
Now, intead of static value, the parameter setter is using “#{jobParameters[‘param_name‘]}” syntax.
JobParameter values are set at job invocation time. The following is a sample invocation program.
import org.springframework.context.ApplicationContext; | |
import org.springframework.context.support.ClassPathXmlApplicationContext; | |
import org.springframework.batch.core.Job; | |
import org.springframework.batch.core.launch.JobLauncher; | |
import org.springframework.batch.core.JobParameters; | |
import org.springframework.batch.core.JobParametersBuilder; | |
public class TestRun2_2 { | |
public static void main(String[] args) throws Exception{ | |
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/job-test02-02-context.xml"}); | |
JobLauncher jobLauncher = context.getBean(JobLauncher.class); | |
Job testJob = context.getBean("TestJob02", Job.class); | |
JobParameters jobParameters = new JobParametersBuilder() | |
.addString("start_time", Long.toString(System.currentTimeMillis())) | |
.addString("param1", "col1-1") | |
.toJobParameters(); | |
jobLauncher.run(testJob, jobParameters); | |
// | |
((ClassPathXmlApplicationContext)context).close(); | |
} | |
} |
Above sample shows that JobParameters.addString(“param_name”, “param_value”) is setting the job parameter.
And also notice that ParameterSetter’s bean scope is “step”. Spring Batch is extending bean scope with “step” and “job”. (More on Spring Batch Scope) To access to JobParameter, bean’s scope must be “step” or “job”.
You can download the full sources from github.