1
votes

I have a requirement to read one of our module related transaction table using Spring default FlatFileReader to fetch record and use Spring FlatFileWriter to write so I don't have control on these reader and writer as they are not custom one. Then the second step is tasklet to transmit the same flat file to the remote location using SFTP.

But some times when Spring FlatFile reader don't get record then it will generate empty File with header.

So I am checking the content of the file in the second step tasklet and checking if it contains header and record then transmit the same in that step otherwise I'm inserting some default records which is holding some logic into the transaction table. Once insertion is completed then I would like to call previous step that is step 1 Spring flat file reader from the current tasklet step.

Please let me know on the same to call previous step from the current step which is tasklet.

Please find the below sample job config

    <batch:step id="FlatFileStep3" next="TransmissionFlatFileStep4">
    <batch:tasklet>
        <batch:chunk reader="FlatFileReader" writer="FlatFileWriter" commit-interval="50"/> 
    </batch:tasklet>
                   </batch:step>
<batch:step id="TransmissionFlatFileStep4">
    <batch:tasklet>
        <batch:chunk ref="TransmissionFlatFileTasklet"/>    
        <batch:next on="NOT_COMPLETED" to="FlatFileStep3"/>
        <batch:next on="COMPLETED" to="UpdateTxnTableStep5"/>
    </batch:tasklet>
</batch:step>
<batch:step id="UpdateTxnTableStep5">
    <batch:tasklet>
        <batch:chunk ref="UpdateTxnTableTasklet"/>  
    </batch:tasklet>
</batch:step>

when the spring batch comes to the TransmissionFlatFileStep4 then in the TransmissionFlatFileTasklet I have logic to check the file content. if the file is empty then I have insertion logic to insert some default data to our transaction table. Then in the same tasklet (TransmissionFlatFileTasklet) I override the public ExitStatus afterStep(StepExecution stepExecution) method by implementing StepExecutionListener interface and set the custom exit status NOT_COMPLETED & COMPLETED so its calling UpdateTxnTableStep5 when the status is COMPLETED as well as it call FlatFileCreationStep3 on NOT_COMPLETED so this time the flat file will be generated with those default records but once the flat file completes then it should again call TransmissionFlatFileStep4 which is not happening the batch is throwing error : unable to find the next state

2

2 Answers

1
votes

Have you consider using the control flow documented in section 5.3. With it you have the ability to define an exit code that could represent when you want to call back to step one and then have a similar thing on step one that might control whether to fall through the entire process again or go to the end.

Just as an example of what I am thinking:

<job id="job">
<step id="firstStep" parent="parent1">
    <next on="*" to="secondStep" />
    <end on="GOTOEND" />
</step>
<step id="secondStep" parent="parent2" next="thirdStep" />
<step id="thirdStep" parent="parent3" >
    <next on="RESEND" to="firstStep" />
    <end on="*" />
</step>

You could switch it around, however you wanted to manage the exit status from a step.

From there you could control the exit status of a step via a step listener that could check some transient data set in the step context.

One other option might be using the decider to choose where to go. I have not used these personally but based on the documentation they might work for you.

1
votes

In addition of Mark Kouba's answer, here are a few tips for an implementation.

To control the return code of your tasklet (ie. the value "on=" in the "next" tag), you can for example implement StepExecutionListener (or add a custom listener which implements this class). Then in the method afterStep, you can use your own logic to return a custom exitCode :

@Override
public ExitStatus afterStep(StepExecution stepExecution) {

    if (true) // Your logic
        return new ExitStatus("GOTOEND"); // Your custom code
    else
        return null; // Inherit status from step
}

A bit more about Decider : Those are placed in your job definition between steps and use your own logic to determine the next step. They work in the same way afterStep does :

<batch:decision decider="myDecider" id="myDecider">
    <batch:end on="GOTOEND" />
    <batch:next on="OTHER" to="OtherStep"/>
    <batch:fail on="*" />
</batch:decision>

<bean id="myDecider" class="xx.xx.xx.MyDecider"></bean>

The referenced class of the bean needs to implement JobExecutionDecider and override the method decide :

@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {

    if (true) // Your logic 
        return new FlowExecutionStatus("GOTOEND");
    else
        return FlowExecutionStatus.FAILED;

}

Also, if you need to control the content of your FlatFileItemWriter, there is a property shouldDeleteIfEmpty which you can set to false to prevent the file from being created. See FlatFileItemWriter documentation.