Spring Batch настраивает несколько устройств чтения / обработки / записи для одного задания на основе параметров задания

У меня есть весеннее пакетное приложение, настроенное по ссылке ниже.

https://spring.io/guides/gs/batch-processing/

Теперь мне нужно настроить step таким образом, чтобы он принимал FlatFileItemReader, если пользовательский ввод является файлом, и JdbcPagingItemReader, если вводится SQL. Я бы передал входные данные (файл / sql) как параметры задания.

Насколько я понимаю, все в приведенном выше примере Spring - это одноэлементные bean-компоненты, которые загружаются в ApplicationContext при запуске приложения. Как шаг можно настроить только один раз с одним Читателем. Как мне настроить его, чтобы он принимал разные ридеры в зависимости от ввода пользователя

Я не предпочитаю создавать несколько рабочих мест, если меняется только читатель.

Я думал об использовании шаблонов Factory / Strategy, но это возможно, только если Step не является bean-компонентом. Здесь все это bean-компоненты, которые загружаются при запуске приложения.

Независимо от шаблонов, было бы полезно использовать разные считыватели на шаге на основе параметров задания.


person karthik    schedule 08.11.2017    source источник


Ответы (3)


Ваше предположение о бобах верно.

Самым быстрым решением было бы просто создать две вакансии, если у вас всего два вкуса. Но давайте проигнорируем реальность и поговорим о теории:

Вы можете создать два шага, по одному для каждого варианта, и использовать JobExecutionDecider для выполнения одного или другого шага (см. docs).

Или вы создаете свой собственный ItemReader и позволяете ему динамически создавать делегированного читателя. Если вы используете ItemStreamSupport или AbstractItemCountingItemStreamItemReader в качестве базового класса, вы получите метод open(ExecutionContext executionContext).

Образец кода:

public class TicTacReader extends ItemStreamSupport implements ItemReader<TicTac>{

  protected ItemReader<TypedFieldSet<RecordType>> delegate;

  public TicTacReader() {
    super();
    setName(TicTacReader.class.getName());
  }

  @Override
  public void open(ExecutionContext executionContext) throws ItemStreamException {
    super.open(executionContext);
    // TODO: use the appropriate reader
    this.delegate = new VoodooReader();
  }

      @Override
  public TicTac read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
    TypedFieldSet<RecordType> line = this.delegate.read();
    // TODO ...
 }
}
person dube    schedule 08.11.2017
comment
Я тоже не считаю правильным создавать несколько шагов, так как это будет продолжать увеличивать количество шагов, когда в будущем будет больше читателей / процессоров и писателей. Я реализовал ItemStreamReader в соответствии с вашим решением для читателя. Это решило проблему с несколькими читателями. Есть ли решение для процессоров и писателя, позволяющее избежать создания шагов и рабочих мест ???? - person karthik; 09.11.2017
comment
Я думаю, что есть композитныйItemProcessor, и что-то в Writer должно быть доступно для этого. Я обновлю, как только выполню poc на процессоре и писателе. Спасибо за фору и решение @dube - person karthik; 09.11.2017
comment
Случайные подсказки из моего последнего пакетного проекта (около 10 файлов с ~ 15 типами записей): создайте класс конфигурации для каждого шага, тогда это не повредит, если у вас есть похожие (под-) шаги и потоки. Присвоение им бинов с некоторым суффиксом также помогло случайно не связать подэтап в глобальной конфигурации задания. - person dube; 10.11.2017

Вы можете реализовать это с помощью @StepScope. Поместите свое имя bean-компонента, например, FlatFileItemReader / или SQL, в параметры задания, затем используйте приведенный ниже код

образец реализации

способ конфигурации java

    @StepScope
        public Step step(@Value("#{jobParameters['beanId']}") final String beanId) {
        return stepBuilderFactory.get("step")
                .<POJO, POJO> chunk(10000)
                .reader(getReader(beanId))
                .processor(Processor)
                .writer(Writer)             
                .build();
     }


 getReader(String beanId)
     {
        return applicationContext.getBean(beanId);
     }

XML

<batch:chunk reader="#{jobParameters['beanId']}" writer="writer" processor="processor" commit-interval="100" />
person Niraj Sonawane    schedule 09.11.2017

Помните, что конфигурации Spring (следовательно, bean-компоненты) могут быть привязаны к профилям Spring, переменным среды, присутствию bean-компонентов контекста приложения, свойствам и т. Д.

  • @Профиль
  • @ConditionalOnBean @ConditionalOnMissingBean
  • @ConditionalOnClass @ConditionalOnMissingClass
  • @ConditionalOnExpression (SpringEL)
  • @ConditionalOnJava (версия JVM)
  • @ConditionalOnJndi
  • @ConditionalOnProperty
  • @ConditionalOnResource
  • @ConditionalOnWebApplication @ConditionalOnNotWebApplication
  • @ConditionalOnEnabledEndpoint (см. Привод)

Таким образом, вы должны иметь возможность фильтровать свои фабрики (через классы @Configuration и методы @Bean) в зависимости от контекста выполнения.

person Thomas Escolan    schedule 13.05.2019