我有一个现有的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
时停止整个工作(而不是失败)。
答案 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());
}
}
希望这会有所帮助。