Spring Batch остановить выполнение задания из внешнего класса - PullRequest
1 голос
/ 03 апреля 2019

У меня есть существующий весенний пакетный проект, который имеет несколько шагов Я хочу изменить шаг, чтобы остановить работу: 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() методу, который возвращает 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 в StepBuilderFactory ожидает ItemReader от метода reader.read(), и ему все равно остальная часть класса.

Я ищу идеи или решение, чтобы иметь возможность остановить всю работу (не подвести ее), когда пойман NoInputFileException.

1 Ответ

2 голосов
/ 04 апреля 2019

Я ищу идеи или решение, чтобы иметь возможность остановить всю работу (не подвести ее), когда перехватывается 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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...