Spring Batch从外部类停止作业执行

时间:2019-04-03 16:25:37

标签: java spring spring-batch

我有一个现有的Spring Batch项目,该项目有多个步骤。我想修改一个步骤,以便停止工作:jobExecution.getStatus() == STOPPED

我的步骤:

@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
private StepReader reader;
@Autowired
private StepProcessor processor;
@Autowired
private StepWriter writer;
@Autowired
public GenericListener listener;
@Bean
@JobScope
@Qualifier("mystep")
public Step MyStep() throws ReaderException {
    return stepBuilderFactory.get("mystep")
            .reader(reader.read())
            .listener(listener)
            .processor(processor)
            .writer(writer)
            .build();
}

GenericListener实现ItemReadListener, ItemProcessListener, ItemWriteListener并覆盖基本上写日志的方法之前和之后。

这里的重点是StepReader类及其返回read()的{​​{1}}方法:

FlatFileItemReader

我尝试在@Component public class StepReader { public static final String DELIMITER = "|"; @Autowired private ClassToAccessProperties classToAccessProperties; private Logger log = Logger.create(StepReader.class); @Autowired private FlatFileItemReaderFactory<MyObject> flatFileItemReaderFactory; public ItemReader<MyObject> read() throws ReaderException { try { String csv = classToAccessProperties.getInputCsv(); FlatFileItemReader<MyObject> reader = flatFileItemReaderFactory.create(csv, getLineMapper()); return reader; } catch (ReaderException | EmptyInputfileException | IOException e) { throw new ReaderException(e); } catch (NoInputFileException e) { log.info("Oh no !! No input file"); // Here I want to stop the job return null; } } private LineMapper<MyObject> getLineMapper () { DefaultLineMapper<MyObject> mapper = new DefaultLineMapper<>(); DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer(); delimitedLineTokenizer.setDelimiter(DELIMITER); mapper.setLineTokenizer(delimitedLineTokenizer); mapper.setFieldSetMapper(new MyObjectFieldSetMapper()); return mapper; } } 中实现StepExecutionListener,但是没有运气,我想是因为StepReader中的reader方法期望{ {1}}方法,它与课程的其余部分无关。

我正在寻找想法或解决方案,以便在遇到StepBuilderFactory时停止整个工作(而不是失败)。

1 个答案:

答案 0 :(得分:2)

  

我正在寻找想法或解决方案,以便在捕获到NoInputFileException时能够停止整个作业(不会失败)。

这是一种常见的模式,在参考文档的Handling Step Completion When No Input is Found部分中有详细说明。该部分中的示例显示了在找不到输入文件时如何使作业失败,但是由于您想停止作业而不是使其失败,因此可以在侦听器中使用StepExecution#setTerminateOnly();,并且作业将以状态{ {1}}。在您的示例中,您需要将该监听器添加到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());
    }

}

希望这会有所帮助。