我正在从事以下工作:
@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 :(得分:1)
您需要定义从validateCsvHeaderStep
到COMPLETED
上的决定者的流程,如下所示:
.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
希望这会有所帮助。