Spring Batch

framework

Job

  • 複数の Step からなる

Step

Chunk

Job はチャンクタイプの Step からなり, チャンクタイプは

  1. 対象読み込み(ItemReader<In>)
  2. 処理(ItemProcessor<In, Out>)
  3. 書き込み(ItemWriter<Out>)

の流れでバッチ処理が行われます.
各バッチは XXXBatchConfigJobStep が定義されています. これらのJobは XXXExecutor@Scheduled がついたメソッドで定期実行されます.

@Component
class XXXExecutor(
    private val jobLauncher: JobLauncher,
    private val job: Job,
) {
    @Scheduled(cron = "")
    fun xxxBatch() { ... }
}
 
@Configuration
class XXXBatchConfig() {
    @Bean
    fun step(...): Step {
        return stepBuilderFactory.get("step")
            .chunk()
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build()
    }
 
    @Bean
    fun job(step: Step): Job {
        return jobBuilderFactory
            .get("job")
            .incrementer(RunIdIncrementer())
            .start(step)
            .build()
    }
}

Stepする

@Bean
public Step step1() {
	return this.stepBuilderFactory.get("step1")
				.<String, String>chunk(2)
				.reader(fooReader())
				.processor(fooProcessor())
				.writer(compositeItemWriter())
				.stream(barWriter())
				.build();
}

JPAPagingItemReader

@Bean
public JpaPagingItemReader itemReader() {
	return new JpaPagingItemReaderBuilder<CustomerCredit>()
           				.name("creditReader")
           				.entityManagerFactory(entityManagerFactory())
           				.queryString("select c from CustomerCredit c")
           				.pageSize(1000)
           				.build();
}

Tasklet

class HogeTasklet(
    private val jobRepository: JobRepository
) : Tasklet {
    override fun execute(contribution: StepContribution, context: ChunkContext): RepeatStatus {
        return RepeatStatus.FINISHED
    }
}

メタテーブル

2022-12-22

以下のメタテーブルが作成される

  • batch_job_instance
  • batch_job_execution
  • batch_job_execution_params
  • batch_job_execution_context
  • batch_step_execution
  • batch_step_execution_context

@EnableBatchProcessing が DataSource を使う

2022-07-22

@SpringBatchTest
@RunWith(SpringRunner::class)
@ContextConfiguration(classes = [NotifyDealEndBatchConfiguration::class])
class BatchTest {
    @Autowired
    private lateinit var jobLauncherTestUtils: JobLauncherTestUtils
}
 

Error creating bean with name ‘jobLauncherTestUtils’: Unsatisfied dependency expressed through method ‘setJob’ parameter 0; nested exception is org.springframework.beans.factory

が出る, 内部で @Autowire Job するがJobが複数あるから?
-> @SpringBatchTest をつけると内部で JobLauncherTestUtils
作ろうとするからつけずに @SpringBootTest だけつけて
jobLauncher.run(job, JobParameters()) で実行する

JobParameter

2023-01-22
同一 JobParameter での実行は同一ジョブの再起動と見做される

  • そうしたくないなら
    • RunIdIncrementer() でjobidを変える
    • JobBuilder.preventRestart() を付ける(再起動不可能Jobとする)

2022-08-05

  • 渡す側
val now = Timestamp.valueOf(LocalDateTime.now()).time
val params = JobParametersBuilder()
    .addLong("currentTime", now)
    .toJobParameters()
jobLauncher.run(autoCompleteDealJob, params)
  • 受け取る側
@Value("#{jobParameters[xxx]}")
Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

JobParametersを参照するBeanのスコープはStepスコープでなければならない
JobParametersを参照する際は、参照するBeanのスコープをStepスコープとする必要がある。 これは、JobParametersを参照する際に、Spring Batchのlate bindingという仕組みを使用しているためである。

  • taskletなComponentを実装するのは : Tasklet でいいが, chunkの時はどうすれば? class: Tasklet@StepScope 付けている例はたくさんあるが

参考文献