[英]Spring Batch Conditional Flow Not executing the else part
我正在嘗試使用 Spring 批處理實現下圖所示的流程。 我指的是https://docs.spring.io/spring-batch/4.0.x/reference/pdf/spring-batch-reference.pdf 的第 85 頁上的 java 配置,它討論了 Java 配置。
出於某種原因,當判定器返回 TYPE2 時,批處理以失敗狀態結束,沒有任何錯誤消息。 以下是我工作的java配置:
jobBuilderFactory.get("myJob")
.incrementer(new RunIdIncrementer())
.preventRestart()
.start(firstStep())
.next(typeDecider()).on("TYPE1").to(stepType1()).next(lastStep())
.from(typeDecider()).on("TYPE2").to(stepType2()).next(lastStep())
.end()
.build();
我認為 java 配置有問題,盡管它與 Spring 文檔匹配。 流程在這里很有用,但我相信沒有它會有辦法。 關於如何實現這一目標的任何想法?
您不僅需要定義從stepType1
到后續步驟的流程,還需要定義從stepType1
和stepType2
到lastStep
。 下面是一個例子:
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 firstStep() {
return steps.get("firstStep")
.tasklet((contribution, chunkContext) -> {
System.out.println("firstStep");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public JobExecutionDecider decider() {
return (jobExecution, stepExecution) -> new FlowExecutionStatus("TYPE1"); // or TYPE2
}
@Bean
public Step stepType1() {
return steps.get("stepType1")
.tasklet((contribution, chunkContext) -> {
System.out.println("stepType1");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step stepType2() {
return steps.get("stepType2")
.tasklet((contribution, chunkContext) -> {
System.out.println("stepType2");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step lastStep() {
return steps.get("lastStep")
.tasklet((contribution, chunkContext) -> {
System.out.println("lastStep");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Job job() {
return jobs.get("job")
.start(firstStep())
.next(decider())
.on("TYPE1").to(stepType1())
.from(decider()).on("TYPE2").to(stepType2())
.from(stepType1()).on("*").to(lastStep())
.from(stepType2()).on("*").to(lastStep())
.build()
.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());
}
}
這打印:
firstStep
stepType1
lastStep
如果決策程序返回TYPE2
,則示例打印:
firstStep
stepType2
lastStep
希望這可以幫助。
遇到了類似的問題,即沒有調用 else 部分(從技術上講,只調用了首先配置的 on())
幾乎所有與流程和決策程序示例相關的網站都有類似的作業配置,無法弄清楚是什么問題。
經過一些研究,找到了 spring 如何維護決策者和決策的方式。 在高層,在初始化應用程序時,spring 基於作業配置維護決策對象(如 decsion0、decision1 等)的決策列表。
當我們調用決策者()方法時,它總是為決策者返回一個新對象。 當它返回一個新對象時,該列表只包含每個對象的一個映射(即 decision0 )並且由於它是一個列表,它總是返回第一個配置的決策。所以這就是為什么只有第一個配置的轉換才被叫。
解決方案:不是對決策程序進行方法調用,而是為決策程序創建一個單例 bean 並在作業配置中使用它
例子:
@Bean
public JobExecutionDecider stepDecider() {
return new CustomStepDecider();
}
注入它並在作業創建 bean 中使用它
@Bean
public Job sampleJob(Step step1, Step step2,Step step3,
JobExecutionDecider stepDecider) {
return jobBuilderFactory.get("sampleJob")
.start(step1)
.next(stepDecider).on("TYPE1").to(step2)
.from(stepDecider).on("TYPE2").to(step3)
}
希望這可以幫助。
創建一個 dummyStep,它將返回 FINISH 狀態並跳轉到下一個決策程序。 完成當前步驟后,您需要將流光標重定向到下一個決策程序或虛擬步驟
.next(copySourceFilesStep())
.next(firstStepDecider).on(STEP_CONTINUE).to(executeStep_1())
.from(firstStepDecider).on(STEP_SKIP).to(virtualStep_1())
//-executeStep_2
.from(executeStep_1()).on(ExitStatus.COMPLETED.getExitCode())
.to(secondStepDecider).on(STEP_CONTINUE).to(executeStep_2())
.from(secondStepDecider).on(STEP_SKIP).to(virtualStep_3())
.from(virtualStep_1()).on(ExitStatus.COMPLETED.getExitCode())
.to(secondStepDecider).on(STEP_CONTINUE).to(executeStep_2())
.from(secondStepDecider).on(STEP_SKIP).to(virtualStep_3())
//-executeStep_3
.from(executeStep_2()).on(ExitStatus.COMPLETED.getExitCode())
.to(thirdStepDecider).on(STEP_CONTINUE).to(executeStep_3())
.from(thirdStepDecider).on(STEP_SKIP).to(virtualStep_4())
.from(virtualStep_3()).on(ExitStatus.COMPLETED.getExitCode())
.to(thirdStepDecider).on(STEP_CONTINUE).to(executeStep_3())
.from(thirdStepDecider).on(STEP_SKIP).to(virtualStep_4())
@Bean
public Step virtulaStep_2() {
return stepBuilderFactory.get("continue-virtualStep2")
.tasklet((contribution, chunkContext) -> {
return RepeatStatus.FINISHED;
})
.build();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.