Java Spring批处理从外部类停止作业执行

Java Spring批处理从外部类停止作业执行,java,spring,spring-batch,Java,Spring,Spring Batch,我有一个现有的spring批处理项目,它有多个步骤。我想修改一个步骤,以便停止作业:jobsecution.getStatus()==STOPPED 我的步骤: @Autowired 公共StepBuilderFactory StepBuilderFactory; @自动连线 私人分步读取器; @自动连线 专用步进处理器; @自动连线 私人继作者; @自动连线 公共通用侦听器; @豆子 @工作范围 @限定词(“mystep”) 公共步骤MyStep()引发ReaderException{ 返回s

我有一个现有的spring批处理项目,它有多个步骤。我想修改一个步骤,以便停止作业:
jobsecution.getStatus()==STOPPED

我的步骤:

@Autowired
公共StepBuilderFactory StepBuilderFactory;
@自动连线
私人分步读取器;
@自动连线
专用步进处理器;
@自动连线
私人继作者;
@自动连线
公共通用侦听器;
@豆子
@工作范围
@限定词(“mystep”)
公共步骤MyStep()引发ReaderException{
返回stepBuilderFactory.get(“mystep”)
.reader(reader.read())
.listener(侦听器)
.处理器(处理器)
.作者(作者)
.build();
}
genericstener
实现了
ItemReadListener、ItemProcessListener、ItemWriteListener
和重写基本上写日志的前后方法

这里的重点是
StepReader
类及其
read()
方法,该方法返回
FlatFileItemReader

@组件
公共类步进读取器{
公共静态最终字符串分隔符=“|”;
@自动连线
私有类ToAccessProperties类ToAccessProperties;
私有记录器log=Logger.create(StepReader.class);
@自动连线
私有FlatFileItemReaderFactory FlatFileItemReaderFactory;
public ItemReader read()引发ReaderException{
试一试{
字符串csv=classToAccessProperties.getInputCsv();
FlatFileItemReader=flatFileItemReaderFactory.create(csv,getLineMapper());
返回读取器;
}捕获(ReaderException | EmptyInputfileException | IOException e){
抛出新的ReaderException(e);
}捕获(NoInputFileException e){
log.info(“哦,不!!没有输入文件”);
//在这里,我想停止这项工作
返回null;
}
}
专用线映射器getLineMapper(){
DefaultLineMapper映射器=新的DefaultLineMapper();
DelimitedLineTokenizer DelimitedLineTokenizer=新的DelimitedLineTokenizer();
delimitedLineTokenizer.setDelimiter(分隔符);
setLineTokenizer(delimitedLineTokenizer);
setFieldSetMapper(新的MyObjectFieldSetMapper());
返回映射器;
}
}
我试图在
StepReader
中实现
StepExecutionListener
,但没有成功,我认为这是因为
StepBuilderFactory
中的
reader
方法期望从
reader.read()
方法中得到一个
ItemReader
,它不关心类的其余部分

我正在寻找能够在捕获
NoInputFileException
时停止整个作业(而不是使其失败)的想法或解决方案

我正在寻找的想法或解决方案,能够停止整个工作(而不是失败),当NoInputFileException被捕获

这是一种常见模式,在参考文档的章节中有详细描述。该部分中的示例显示了在找不到输入文件时如何使作业失败,但由于您希望停止作业而不是使其失败,因此可以使用
StepExecution#setTerminateOnly(),您的作业将以状态
STOPPED
结束。在您的示例中,您可以将该侦听器添加到
MyStep
步骤

但是,我建议添加一个预验证步骤,如果没有文件,则停止作业。下面是一个简单的例子:

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
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 fileValidationStep() {
        return steps.get("fileValidationStep")
                .tasklet((contribution, chunkContext) -> {
                    // TODO add code to check if the file exists
                    System.out.println("file not found");
                    chunkContext.getStepContext().getStepExecution().setTerminateOnly();
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

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

    @Bean
    public Job job() {
        return jobs.get("job")
                .start(fileValidationStep())
                .next(fileProcessingStep())
                .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);
        JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
        System.out.println("Job status: " + jobExecution.getExitStatus().getExitCode());
    }

}
该示例打印:

file not found
Job status: STOPPED

希望这有帮助

在这里。Luca Basso Ricci comment应该适合您。虽然这不是我所希望的解决方案,因为
MyStep
按设计负责验证和读取输入文件,但您的解决方案帮助我避免了批处理的技术问题。谢谢
MyStep按设计负责验证和读取输入文件
:。这个评论很有建设性,我只是想善意地帮助你,而不是质疑你的设计。但我真的建议每一步都做一件事(并且做得很好)。我完全同意你的观点,但这是一个旧的现有项目,我试图将维护成本降到最低,因此不涉及现有设计。不过,我调整了您的解决方案,目前效果良好。非常感谢。