Функция перезапуска Spring Batch не работает при использовании @StepScope - PullRequest
0 голосов
/ 04 февраля 2019

Я хочу использовать функцию перезапуска Spring Batch (v3.0.9), чтобы при перезапуске JobInstance шаг процесса считывался из последней неудачной точки чанка вперед.Мой перезапуск работает нормально, пока я не использую аннотацию @StepScope к моему методу myBatisPagingItemReader.
Я использовал @StepScope, чтобы я мог выполнить позднюю привязку, чтобы получить JobParameters в моем myBatisPagingItemReader метод bean @Value("#{jobParameters['run-date']}"))
Если я использую аннотацию @StepScope для метода myBatisPagingItemReader(), перезапуск не работает, поскольку он создает новый экземпляр (scope = step, name = scopedTarget.myBatisPagingItemReader).
Если я используюstepsccope, возможно ли, чтобы myBatisPagingItemReader установил read.count с последнего сбоя, чтобы перезагрузка заработала?

Я объяснил эту проблему с помощью приведенного ниже примера.

@Configuration
@EnableBatchProcessing
public class BatchConfig {
    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
        ItemReader<Model> myBatisPagingItemReader,
        ItemProcessor<Model, Model> itemProcessor,
         ItemWriter<Model> itemWriter) {

         return stepBuilderFactory.get("data-load")
            .<Model, Model>chunk(10)
            .reader(myBatisPagingItemReader)
            .processor(itemProcessor)
             .writer(itemWriter)
             .listener(itemReadListener())
             .listener(new JobParameterExecutionContextCopyListener())
             .build();
   }
   @Bean
   public Job job(JobBuilderFactory jobBuilderFactory, @Qualifier("step1") 
               Step step1) {
           return jobBuilderFactory.get("load-job")
            .incrementer(new RunIdIncrementer())
            .start(step1)
            .listener(jobExecutionListener())
            .build();
   }
   @Bean
   @StepScope
   public ItemReader<Model> myBatisPagingItemReader(
         SqlSessionFactory sqlSessionFactory,
         @Value("#{JobParameters['run-date']}") String runDate) 
  {
     MyBatisPagingItemReader<Model> reader = new 
     MyBatisPagingItemReader<>();
     Map<String, Object> parameterValues = new HashMap<>();
     parameterValues.put("runDate", runDate);
     reader.setSqlSessionFactory(sqlSessionFactory);
     reader.setParameterValues(parameterValues);
     reader.setQueryId("query");
     return reader;
   }
}

Пример перезапуска, когда я использую аннотацию @Stepscope для myBatisPagingItemReader(), читатель выбирает 5 записей, и у меня есть размер чанка (интервал фиксации) установлен на 3.

Экземпляр задания - 01 - Параметр задания - 01/02 / 2019.
chunk-1:
- запись процесса-1
- запись процесса-2
- запись процесса-3
запись - запись всех 3 записей
успешное принятие фрагмента-1

фрагмент-2:
запись процесса-4
запись процесса-5- Броски и исключение
Задание завершено и установлено состояние «СБОЙ»

Теперь задание перезапускается снова с использованием того же параметра задания.
Экземпляр задания - 01 - Параметр задания - 01/02/2019.
chunk-1:
запись процесса-1
запись процесса-2
запись процесса-3
Writer - запись всех 3 записей
успешное принятие фрагмента-1

chunk-2:
запись процесса-4
запись процесса-5 - выбросы и исключение
Задание завершено и установлено в состояние «СБОЙ»

Аннотация @StepScope к методу myBatisPagingItemReader() создает новый экземпляр, см. Ниже сообщение журнала.
Создание объекта в scope = step, name = scopedTarget.myBatisPagingItemReader
Зарегистрированный обратный вызов уничтожения в scope = step, name= scopedTarget.myBatisPagingItemReader
Поскольку это новый экземпляр, он запускает процесс с начала, а не с чанка-2.

Если я не использую @Stepscope, он перезапускается с чанка-2, когда устанавливается перезапущенный шаг задания - MyBatisPagingItemReader.read.count = 3.

1 Ответ

0 голосов
/ 04 февраля 2019

Проблема здесь в том, что вы возвращаете ItemReader вместо полностью определенного класса (MyBatisPagingItemReader) или как минимум ItemStreamReader.Когда вы используете область действия Spring Batch, мы создаем прокси для поздней инициализации.Прокси-сервер основан на типе возврата метода (ItemReader в вашем случае).Проблема, с которой вы сталкиваетесь, заключается в том, что, поскольку прокси имеет ItemReader, Spring Batch не знает, что ваш компонент также реализует ItemStream, и это тот интерфейс , который обеспечивает возможность перезапуска.По умолчанию Spring Batch автоматически зарегистрирует все компоненты типа ItemStream (вы также можете явно зарегистрировать компоненты самостоятельно, но обычно это не требуется).

Для решения вашей проблемы должно работать следующее (обратите внимание на изменение типа возвращаемого значения):

   @Bean
   @StepScope
   public MyBatisPagingItemReader<Model> myBatisPagingItemReader(
         SqlSessionFactory sqlSessionFactory,
         @Value("#{JobParameters['run-date']}") String runDate) {

     MyBatisPagingItemReader<Model> reader = 
         new MyBatisPagingItemReader<>();

     Map<String, Object> parameterValues = new HashMap<>();
     parameterValues.put("runDate", runDate);

     reader.setSqlSessionFactory(sqlSessionFactory);
     reader.setParameterValues(parameterValues);
     reader.setQueryId("query");

     return reader;
   }

Поэтому я рекомендую, чтобы, когда это возможно, при использовании аннотированных методов @Bean вы возвращали наиболее конкретный возможный тип, чтобы Spring мог помочькак можно больше.

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