问题
I'm new to Spring batch. I've created a decider which returns a FlowExecutionStatus as "YES" / "NO". Based on the FlowExecutionStatus, I need to call step2() or step3().
In my below code, step2() is getting called before decider. How to modify the code so that decider will be called and based on the "FlowExecutionStatus" returned bu the decider, either step2() or step3() should be called. Please help.
@Autowired
private NumberDecider decider;
@Bean
public Job NumberLoaderJob() throws NumberFormatException, IOException {
return jobBuilderFactory.get("numberLoaderJob").start(step1()).listener(new MyNumberJobListener())
.next(decider).on("YES").to(step2())
.from(decider).on("NO").to(step3()).end().build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("Exiting step1() execute()");
return RepeatStatus.FINISHED;
}
}).build();
}
/**
* Step 2
*
* @return
* @throws NumberFormatException
* @throws IOException
*/
@Bean
public Step step2() throws NumberFormatException, IOException {
return stepBuilderFactory.get("step2").listener(new MyStepListener())
.<OrderNumber, OrderNumber>chunk(Integer.valueOf(chunkSize)).faultTolerant()
.listener(new MyChunkListener()).reader(new MyItemReader())
.listener(new MyItemReaderListener()).writer(customItemWriter())
.listener(new MyWriteListener()).build();
}
回答1:
You would need to to set the exit status in step1 so that the decider picks it up and make the decision:
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("Exiting step1() execute()");
chunkContext.getStepContext().getStepExecution().setExitStatus(new ExitStatus("YES")); // or NO
return RepeatStatus.FINISHED;
}
}).build();
}
EDIT: I thought that the decider should make the decision based on the exit status of step1, hence the previous sample. So adding a sample to show how to use a decider (after clarification):
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableBatchProcessing
public class MyJob {
@Autowired
private JobBuilderFactory jobs;
@Autowired
private StepBuilderFactory steps;
@Bean
public Step step1() {
return steps.get("step1")
.tasklet((contribution, chunkContext) -> {
System.out.println("hello");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public JobExecutionDecider decider() {
return (jobExecution, stepExecution) -> new FlowExecutionStatus("YES"); // or NO
}
@Bean
public Step step2() {
return steps.get("step2")
.tasklet((contribution, chunkContext) -> {
System.out.println("world");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step step3() {
return steps.get("step3")
.tasklet((contribution, chunkContext) -> {
System.out.println("!!");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Job job() {
return jobs.get("job")
.start(step1())
.next(decider())
.on("YES").to(step2())
.from(decider()).on("NO").to(step3())
.end()
.build();
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
}
In this example, step1 is executed first, then the decider. If the decider returns YES, step2 is executed and if returns NO, step3 is executed.
Hope this helps.
来源:https://stackoverflow.com/questions/52168976/how-to-use-decider-in-spring-batch