Spring Batchで最高にシンプルな実装を考えてみた。

内容はタイトル負けしているかもしれません。

# やりたいこと
- 様々な Job を定義しておいて、用途に応じて実行する Job を切り替えたい
- めんどくさい記述は避けたい(後述)

## 簡単に Job を定義したい
主に[ココらへん](https://terasoluna-batch.github.io/guideline/5.0.0.RELEASE/ja/Ch02_SpringBatchArchitecture.html))を見て構成を理解したのですが、実装方法に関しては資料が少なかったり、資料によって書いてあることが違ってたりして混乱しました。

- xmlに定義しているsampleがあった

※ [こちらを参照しています](https://terasoluna-batch.github.io/guideline/5.0.0.RELEASE/ja/Ch03_CreateTaskletJob.html)

```xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:batch="http://www.springframework.org/schema/batch"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
             http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">

    <import resource="classpath:META-INF/spring/job-base-context.xml"/>

    <context:annotation-config/>

    <context:component-scan
          base-package="org.terasoluna.batch.functionaltest.app.common"/>

    <batch:job id="jobSimpleJob" job-repository="jobRepository"> 
        <batch:step id="simpleJob.step01">
            <batch:tasklet transaction-manager="jobTransactionManager"
                           ref="simpleJobTasklet"/>
        </batch:step>
    </batch:job>

</beans>
```

条件反射です。見た瞬間にこの記述タイプは拒否しました。
個人的な見解ですが、
慣れていない人にxmlは見にくい、今後Jobが増えていくにあたってどんどん見づらくなる可能性が高い。等の理由ももちろんあります。

# 前提
- というわけで、xmlを避けていかにJobをシンプルに定義するかを調べました。
- Spring Batchの基本的な用語についての説明はしていません。

## 環境
- Spring Boot : 2.1.1.RELEASE
- Kotlin  : 1.3.21
- spring-boot-starter-batch

# 実装
## Stepの定義
- Jobを構成するstepを定義します。
- stepを複数組み合わせてJobを構成します。
- 自由に実装を書きたかったのでTaskletを継承しています。

```SampleTasklet1.kt
class SampleTasklet1: Tasklet {
  override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus? {
    *TODO*(“not implemented”) //To change body of created functions use File | Settings | File Templates.
  }
}
```

## Job定義
- 肝心のJob定義です。

```SampleJob.kt
// 以下のアノテーションを必ず付与する
@Configuration
@EnableBatchProcessing
class SampleJob(
    val jobBuilderFactory: JobBuilderFactory,
    val stepBuilderFactory: StepBuilderFactory
    val sampleTasklet1: SampleTasklet1
    val sampleTasklet2: SampleTasklet2) {

	// Stepの定義
  @Bean
  fun sampleStep1(): Step = stepBuilderFactory.get(“sample-step1”).tasklet(sampleTasklet1).build()

  @Bean
  fun sampleStep2(): Step = stepBuilderFactory.get(“sample-step2”).tasklet(sampleTasklet2).build()

  // Jobの定義
  @Bean
  fun sample(): Job? = jobBuilderFactory.get(“sample”)
      .start(sampleStep1())
      .next(sampleStep2())
      .build()

}
```

- `jobBuilderFactory.get(“sample”)`
ここで設定した値が Job 実行時に指定する Job 名となります。
今回は sample が Job 名です。

- 別の Job 定義したいときは別クラスを同じように作成します。
- ※ Job名の重複はビルドエラーになります(実行時だった気もする)

# 実行コマンド
```
java SampleApp.jar --spring.batch.job.names=sample --spring.batch.job.enabled=true
```

- `spring.batch.job.names`
ここに実行したい Job 名を指定すると、指定した値に一致する Job が実行されます。

- その他のパラメーター
起動時に他のパラメーターを渡したいときは同じように `—-retry=1` などして渡すと、step実行時にChunkContextから参照できます。

# おわり
これで Job の定義を分けつつ各 Job を切り替えて実行できるようになりました。