Весенняя партия в два этапа с одним решающим устройством

У меня следующая работа:

@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()!!

Есть два шага, которые могут привести к сбою validateCsvHeaderStep и processCsvStep. Я хотел бы иметь поток, когда ошибка в обработке перейдет в markCsvAsFailedStep и moveFailedCsvStep, но когда все работает нормально, она должна перейти в 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

Есть ли способ добиться обработки ошибок на обоих этапах без дублирования логики?

0
0
1 519
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо определить поток, начиная с validateCsvHeaderStep и заканчивая решающим устройством на COMPLETED, как показано ниже:

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

here are two steps that can fail validateCsvHeaderStep and processCsvStep. I would like to have a flow when error in processing will go to markCsvAsFailedStep and moveFailedCsvStep, but when everything works fine it should go to 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

Надеюсь это поможет.

Другие вопросы по теме