I was wondering for a flow like this:
ItemReader -> ItemProcessor -> ItemWriter
where each one of those is a custom class implementing the equivalent interface and in a chunk-oriented step, When each constructor will be called?
As I understand so far(correct me if I'm wrong) the ItemWriter constructor will be called once in the beginning of the step and for each chunk, write() will be called only. This rule applies for the other 2?
Vinay answer is correct but need some elaboration.
For reader-processor->writer Spring calls the default constructor (let's ignore @PostConstruct etc.) Scope(“step”), as the name implies is creating a new bean for every step. Step does not have to be one to one with thread, for example let's say I have the following reader-processor->writer
@Component
@Scope("step")
public class DoNothingItemReader implements ItemReader<String>{
public DoNothingItemReader() {
LOGGER.info(String.format("New %s created"
,ClassUtils.getShortName(this.getClass())));
}
@Override
public String read() throws Exception{
LOGGER.info("Nothing to read...");
..
}
}
@Component
@Scope("step")
public class DoNothingItemProcessor implements ItemProcessor<String, String> {
public DoNothingItemProcessor() {
LOGGER.info(String.format("New %s created"
,ClassUtils.getShortName(this.getClass())));
}
@Override
public String process(String i) throws Exception {
LOGGER.info("Nothing to process...");
return i;
}
}
@Component
@Scope("step")
public class DoNothingItemWritter implements ItemWriter<String[]> {
public DoNothingItemWritter() {
LOGGER.info(String.format("New %s created"
,ClassUtils.getShortName(this.getClass())));
}
@Override
public void write(List<? extends String[]> items) throws Exception {
LOGGER.info("Nothing to write...");
}
Now we reuse this above in two steps eg
<batch:job id="testScopStep">
<batch:step id="step1" next="step2">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="doNothingItemReader"
processor="doNothingItemProcessor"
writer="doNothingItemWritter" commit-interval="3">
</batch:chunk>
</batch:tasklet>
</batch:step>
<batch:step id="step2">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="doNothingItemReader"
processor="doNothingItemProcessor"
writer="doNothingItemWritter" commit-interval="3">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
The constructor will be called twice for ever reader->processor->writer
The log will be
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] launched>
[SimpleStepHandler] - <Executing step: [step1]>
[DoNothingItemReader] - <New DoNothingItemReader created>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemProcessor] - <New DoNothingItemProcessor created>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemWritter] - <New DoNothingItemWritter created>
[DoNothingItemWritter] - <Nothing to write...>
[SimpleStepHandler] - <Executing step: [step2]>
[DoNothingItemReader] - <New DoNothingItemReader created>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemProcessor] - <New DoNothingItemProcessor created>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemWritter] - <New DoNothingItemWritter created>
[DoNothingItemWritter] - <Nothing to write...>
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] completed
Now consider the following scenario when we are using a composite writer
<batch:job id="testScopStep">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="doNothingItemReader"
processor="doNothingItemProcessor"
writer="compositeWriter" commit-interval="3">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
Here The constructors will be called only once.
The log will display
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] launched>
[SimpleStepHandler] - <Executing step: [step1]>
[DoNothingItemReader] - <New DoNothingItemReader created>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemReader] - <Nothing to read...>
[DoNothingItemProcessor] - <New DoNothingItemProcessor created>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemProcessor] - <Nothing to process...>
[DoNothingItemWritter] - <New DoNothingItemWritter created>
[DoNothingItemWritter] - <Nothing to write...>
[DoNothingItemWritter] - <Nothing to write...>
[SimpleJobLauncher] - <Job: [FlowJob: [name=testScopStep]] completed
So in such case we should be careful taking in to consideration we are sharing the same writer.
ItemWriter, Reader and Writer are all Spring beans. If you have marked them with @component
then all of them created once only and constructor is called when you create ApplicationContext. Though there are different scope you can specify like @scope("step")
. This will make each thread will have their own component in Multi-threaded batch
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.