I have a Spring batch that will write data into a text file, after write to the text file, the batch has another step to rename the file and do backup. The following is part of my code in my batch xml:
<job id="sprFileGenerationJob" xmlns="http://www.springframework.org/schema/batch">
<step id="FileGeneration_step1" next="backupFileGenerationStep">
<tasklet>
<chunk reader="fileGenerationTableReader" writer="fileGenerationFileWriter" chunk-completion-policy="fileGenerationCompletionPolicy" />
<transaction-attributes isolation="DEFAULT" propagation="REQUIRES_NEW" />
</tasklet>
</step>
<step id="backupFileGenerationStep">
<tasklet ref="fileGenerationBackupFileTasklet"/>
</step>
</job>
This is the fileGenerationFileWriter
bean:
<bean id="fileGenerationFileWriter" class="com.job.writer.FileGenerationFileWriter" scope="step">
<property name="delegate">
<bean class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="file:#{jobParameters['output.dir']}" />
<property name="lineAggregator">
<!-- Our Mapper for file writer -->
<bean class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<!-- Header call back, add in when necessary -->
<property name="headerCallback" ref="bulkPaymentFileGenerationFileWriter" />
<!-- Footer call back, add in when necessary -->
<property name="footerCallback" ref="bulkPaymentFileGenerationFileWriter" />
<property name="appendAllowed" value="false" />
</bean>
</property>
<property name="companyId" value="#{jobParameters['companyId']}" />
<property name="dataSource" ref="dataSource" />
</bean>
And this is fileGenerationCompletionPolicy
bean:
<bean id="fileGenerationCompletionPolicy" class="org.springframework.batch.repeat.policy.DefaultResultCompletionPolicy"/>
And this is the fileGenerationBackupFileTasklet
bean:
<bean id="bulkpaymentFileGenerationBackupFileTasklet" class="com.job.tasklet.BulkPaymentFileGenerationBackUpFileTasklet" />
Nothing special in this class, its just implements Spring Tasklet
, and do the execute():
localFile = resource.getFile();
log.info("localFile.length() : " + localFile.length());
if (localFile.length() > 0) {
// do file rename
}
However, in this class, the log show that the file length is 0, means the file is empty. But in fact, I go check the file, the file is written with correct data. Means the TaskLet step run first before the Writer finish its job.
Because of the if checking found that the file length is 0, thus the rename process didn't run.
I am thinking that is it the Spring Writer delay to write the file and my Tasklet
run first. Is it the step in Spring batch is not synchronized? The Tasklet
will run no matter the writer is complete or not?
If yes, how to prevent this?