2016-05-03 2 views
0

В нашем задании SpringBatch есть один шаг с ItemReader, ItemProcessor и ItemWriter. Мы выполняем одну и ту же работу одновременно с разными параметрами. ItemReader имеет состояние, поскольку он содержит входной поток, из которого он считывает.Как обрабатывать читателя с учетом состояния в SpringBatch

Итак, мы не хотим, чтобы один и тот же экземпляр ItemReader использовался для каждого вызова JobInstance (Job + Parameters).

Я не совсем уверен, что является лучшим «показателем» для этой ситуации.

1) Должен ли быть аннотированный шаг с помощью @JobScope и ItemReader прототипом?

ИЛИ

2) В случае, если шаг аннотироваться с @StepScope и ItemReader прототипом?

ИЛИ

3) Если оба Шаг и ItemReader быть аннотированный в качестве прототипа?

Конечный результат должен быть таким, чтобы новый ItemReader создавался для каждого нового выполнения задания с разными идентификационными параметрами (то есть для каждого нового JobInstance).

Спасибо. -AP_

ответ

0

Вот как это идет от класса экземпляра точки зрения (от наименее к большинству случаев):

  • Singleton (на JVM)
  • JobScope (на работу)
  • StepScope (за шагом)
  • Прототип (за ссылки)

Если у вас есть несколько заданий, работающих в одной виртуальной машины Java (Assum вы не находитесь в секционированном шаге, JobScope будет достаточным. Если у вас есть секционированный шаг, вам понадобится StepScope. Прототип был бы излишним во всех сценариях.

Однако, если эти задания запускаются в разных JVM (а не секционированном шаге), тогда простой синглтон-компонент будет просто отлично.

0

Нет необходимости в том, чтобы каждый компонент (Step, ItemReader, ItemProcessor, ItemWriter) был весенним компонентом. Например, с SpringBatch-JAVAAPI, только ваша работа должна быть SpringBean, но не ваши шаги, Читатели и писатели:

@Autowired 
private JobBuilderFactory jobs; 

@Autowired 
private StepBuilderFactory steps; 

@Bean 
public Job job() throws Exception { 
    return this.jobs.get(JOB_NAME) // create jobbuilder 
      .start(step1()) // add step 1 
      .next(step2()) // add step 2 
      .build(); // create job 
} 

@Bean 
public Job job() throws Exception { 
    return this.jobs.get(JOB_NAME) // create jobbuilder 
      .start(step1(JOB_NAME)) // add step 1 
      .next(step2(JOB_NAME)) // add step 2 
      .build(); // create job 
} 

private Step step1(String jobName) throws Exception { 

    return steps.get(jobName + "_Step_1").chunk(10) // 
      .faultTolerant() // 
      .reader(() -> null) // you could lambdas 
      .writer(items -> { 
      }) // 
      .build(); 
} 

private Step step2(String jobName) throws Exception { 
    return steps.get(jobName + "_Step_2").chunk(10) // 
      .faultTolerant() // 
      .reader(createDbItemReader(ds, sqlString, rowmapper)) // 
      .writer(createFileWriter(resource, aggregator)) // 
      .build(); 
} 

Единственное, что вы должны обратить внимание на то, что вы должны вызвать «afterPropertiesSet» -методов при создании экземпляров, как JdbcCurserItemReader, FlatFileItemReader/Writer:

private static <T> ItemReader<T> createDbItemReader(DataSource ds, String sql, RowMapper<T> rowMapper) throws Exception { 
    JdbcCursorItemReader<T> reader = new JdbcCursorItemReader<>(); 

    reader.setDataSource(ds); 
    reader.setSql(sql); 
    reader.setRowMapper(rowMapper); 

    reader.afterPropertiesSet(); // don't forget 
    return reader; 
} 

private static <T> ItemWriter<T> createFileWriter(Resource target, LineAggregator<T> aggregator) throws Exception { 
    FlatFileItemWriter<T> writer = new FlatFileItemWriter(); 

    writer.setEncoding("UTF-8"); 
    writer.setResource(target); 
    writer.setLineAggregator(aggregator); 

    writer.afterPropertiesSet(); // don't forget 
    return writer; 
} 

Таким образом, нет необходимости для вас хлопот вокруг с Скоупсом. Каждый Иов будет иметь свои собственные примеры своих шагов и их читателей и писателей.

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

Смежные вопросы