我们从数据库中读取了大部分数据。有时结果集是空的,对于这种情况,我们希望作业立即停止,而不是移交给作者。如果没有输入,我们不想创建文件。
目前我们通过Step-Listener实现了这个目标,它返回一个特定的String,它是转换到下一个business-step或delete-step的输入,删除我们之前创建的文件(该文件包含没有真正的数据。)
在读者意识到没有输入后,我希望工作能够结束吗?
答案 0 :(得分:0)
使用JobExecutionDecider并根据StepExecution的读取次数设置新的FlowExecutionStatus并将其路由到作业的末尾可能会更清晰。
答案 1 :(得分:0)
约书亚的回答解决了停止工作而不是过渡到下一个商业步骤的问题。
您的文件编写者可能仍会不必要地创建该文件。您可以使用委托(FlatFileItemWriter)创建类似LazyItemWriter的东西,如果调用write方法,它只会调用delegate.open(一次)。当然,只有在先前打开了委托时,才需要检查是否需要调用delegate.close()。这样可以确保不会创建空文件,并且不再需要删除它。
答案 2 :(得分:0)
我和OP有同样的问题。我正在使用所有注释,如果读者在没有找到任何结果(在我的情况下是文件中)时返回null,那么Job bean将无法使用UnsatisfiedDependencyException初始化,并且该异常将被抛出到stdout。
如果我创建了一个Reader,然后在没有指定File的情况下返回它,那么将创建Job。之后抛出了ItemStreamException,但是它被抛出到我的日志中,因为我已经过了Job自动装配并且在那个步骤内部。这似乎更可取,至少对我正在做的事情而言。
任何其他解决方案都将受到赞赏。
答案 3 :(得分:0)
这种方法是在找不到文件时优雅地移至下一步或结束批处理应用程序,并防止执行不必要的步骤(以及它们的侦听器)。
->检查任务集中是否存在文件,例如FileValidatorTasklet
。
->如果找不到文件,请设置一些退出状态(枚举或最终字符串),这里我们设置了EXIT_CODE
示例小任务
public class FileValidatorTasklet implements Tasklet {
static final String EXIT_CODE = "SOME_EXIT_CODE";
static final String EXIT_DESC = "SOME_EXIT_DESC";
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
boolean isFileFound = false;
//do file check and set isFileFound
if(!isFileFound){
stepContribution.setExitStatus(new ExitStatus(EXIT_CODE, EXIT_DESC));
}
return RepeatStatus.FINISHED;
}
}
->在执行FileValidatorTasklet之后,在此应用程序的作业配置中,检查EXIT_CODE
是否存在。
->如果找到了代码,则提供该作业的后续路径,否则将执行正常的工作流程。(在这里,我们只是在找到EXIT_CODE
时终止该作业,否则继续下一步)< / p>
样本配置
public Job myJob(JobBuilderFactory jobs) {
return jobs.get("offersLoaderJob")
.start(fileValidatorStep).on(EXIT_CODE).end() // if EXIT_CODE is found , then end the job
.from(fileValidatorStep) // else continue the job from here, after this step
.next(step2)
.next(finalStep)
.end()
.build();
}
在这里,我们在弹簧批处理中利用了有条件的步骤流。 我们必须从步骤A定义两个单独的路径。流程类似于A-> B-> C或A-> D-> E。
我已经经历了这个,因此我正在分享我的方法。最好
throw new RunTimeException("msg");
。
它将开始终止Spring Application,而不是在那时精确终止。 (读取器/写入器)中的所有类似close()的方法都将被调用,而所有bean的destroy方法将被调用。
注意:在Listener中执行此操作时,请记住,到此为止,所有bean都已被初始化,并且它们的初始化代码(如afterPropertySet())已经执行。
我认为上面是正确的方法,但是如果您只愿意在此时终止,可以尝试
System.exit(1);