用一个决策器春季批处理两个步骤

时间:2018-09-17 08:18:09

标签: kotlin spring-batch

我正在从事以下工作:

@Bean
fun createCsvJob(
    jobs: JobBuilderFactory,
    validateCsvHeaderStep: Step,
    processCsvStep: Step,
    moveCsvStep: Step,
    markCsvAsFailedStep: Step,
    moveFailedCsvStep: Step
) = jobs.get(PROCESS_CSV_JOB)
    .start(validateCsvHeaderStep)
    .next(processCsvStep)
    .on("*").to(decider())
    .from(decider()).on(ExitStatus.COMPLETED.exitCode).to(moveCsvStep)
    .from(decider()).on(ExitStatus.FAILED.exitCode).to(markCsvAsFailedStep).next(moveFailedCsvStep)
    .build()
    .build()!!

有两个步骤可能导致validateCsvHeaderStepprocessCsvStep失败。当处理错误将流向markCsvAsFailedStepmoveFailedCsvStep时,我希望有一个流程,但是当一切正常时,应该流向moveCsvStep

当前,如果validateCsvHeaderStep失败,则整个作业都会失败。

当我尝试添加决策者时:

    .start(validateCsvHeaderStep)
    .on(ExitStatus.FAILED.exitCode).to(decider())
    .on(ExitStatus.COMPLETED.exitCode).to(processCsvStep)
    .on("*").to(decider())
    .from(decider()).on(ExitStatus.COMPLETED.exitCode).to(moveCsvStep)
    .from(decider()).on(ExitStatus.FAILED.exitCode).to(markCsvAsFailedStep).next(moveFailedCsvStep)

我得到:

Next state not found in flow=myJob for state=myJob.validateCsvStep with exit status=COMPLETED

有没有一种方法可以在不重复逻辑的情况下实现两个步骤的错误处理?

1 个答案:

答案 0 :(得分:1)

您需要定义从validateCsvHeaderStepCOMPLETED上的决定者的流程,如下所示:

.start(validateCsvHeaderStep)
.on(ExitStatus.COMPLETED.exitCode).to(processCsvStep)
.from(validateCsvHeaderStep)on("*").to(decider())
  

这有两个步骤可能会使validateCsvHeaderStep和processCsvStep失败。当处理错误将转到markCsvAsFailedStep和moveFailedCsvStep时,我希望有一个流程,但是当一切正常时,应该转到moveCsvStep。

这里是一个例子:

import org.springframework.batch.core.ExitStatus;
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.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 validateCsvHeaderStep() {
        return steps.get("validateCsvHeaderStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("validateCsvHeaderStep");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step processCsvStep() {
        return steps.get("processCsvStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("processCsvStep");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step markCsvAsFailedStep() {
        return steps.get("markCsvAsFailedStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("markCsvAsFailedStep");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step moveFailedCsvStep() {
        return steps.get("moveFailedCsvStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("moveFailedCsvStep");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step moveCsvStep() {
        return steps.get("moveCsvStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("moveCsvStep");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Job job() {

        return jobs.get("job")
                .flow(validateCsvHeaderStep())
                    .on(ExitStatus.FAILED.getExitCode()).to(markCsvAsFailedStep())
                    .from(validateCsvHeaderStep()).on("*").to(processCsvStep())

                    .from(processCsvStep()).on(ExitStatus.FAILED.getExitCode()).to(markCsvAsFailedStep())
                    .from(processCsvStep()).on("*").to(moveCsvStep())

                    .from(markCsvAsFailedStep()).on("*").to(moveFailedCsvStep())

                    .from(moveFailedCsvStep()).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());
    }

}

它打印:

validateCsvHeaderStep
processCsvStep
moveCsvStep

如果例如validateCsvHeaderStep失败:

    @Bean
    public Step validateCsvHeaderStep() {
        return steps.get("validateCsvHeaderStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("validateCsvHeaderStep");
                    chunkContext.getStepContext().getStepExecution().setExitStatus(ExitStatus.FAILED);
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

它打印:

validateCsvHeaderStep
markCsvAsFailedStep
moveFailedCsvStep

如果processCsvStep失败:

    @Bean
    public Step processCsvStep() {
        return steps.get("processCsvStep")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("processCsvStep");
                    chunkContext.getStepContext().getStepExecution().setExitStatus(ExitStatus.FAILED);
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

它打印:

validateCsvHeaderStep
processCsvStep
markCsvAsFailedStep
moveFailedCsvStep

希望这会有所帮助。