SpringBatchのFlatFileItemWriterをSpringBatch以外で利用する方法

# はじめに
SpringBatchを利用していないプロジェクトで固定長ファイルを出力する場合にSpringBatchの`FlatFileItemWriter`を利用する方法の備忘メモ

# ライブラリの設定
今回はMavenを利用しているので`pom.xml`にSpringBatchのライブラリを追加する。

```xml
<!-- Spring Batch -->
<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-infrastructure</artifactId>
    <!-- 2021/5時点の最新バージョン -->
    <version>4.3.3</version>
</dependency>
```

# Entityクラス実装

今回出力するファイルはヘッダ部と詳細部のファイル構造からなる固定長ファイルとする。

ヘッダ部と詳細部のEntityクラスを実装する。

```java
@Getter
@Setter
@AllArgsConstructor
public class Header {
    private String param01;
    private String param02;
    private String param03;
}

@Getter
@Setter
@AllArgsConstructor
public class Detail {
    private String detail01;
    private String detail02;
    private String detail03;
    private String detail04;
}
```

# Bean定義実装
`FlatFileItemWriter`とヘッダ部と詳細部の`LineAggregator`のBeanを定義する。
今回は固定長ファイルなので、`FormatterLineAggregator`を利用する。

```java
// FlatFileItemWriterのBean定義
@Bean
public FlatFileItemWriter flatFileItemWriter() {
    FlatFileItemWriter flatFileItemWriter = new FlatFileItemWriter();
    flatFileItemWriter.setEncoding("UTF-8");
    flatFileItemWriter.setLineSeparator("\r\n");
    flatFileItemWriter.setAppendAllowed(true);
    flatFileItemWriter.setLineAggregator(new PassThroughLineAggregator());
    return flatFileItemWriter;
}

// ヘッダ部のAggregator
@Bean
public FormatterLineAggregator headlerFormatterLineAggregator() {
    final String[] parameterNames = {"param01", "param02", "param03"};
    BeanWrapperFieldExtractor beanWrapperFieldExtractor = new BeanWrapperFieldExtractor();
    beanWrapperFieldExtractor.setNames(parameterNames);

    FormatterLineAggregator formatterLineAggregator = new FormatterLineAggregator();
    formatterLineAggregator.setFormat("%6s%6s%6s");
    formatterLineAggregator.setFieldExtractor(beanWrapperFieldExtractor);
    return formatterLineAggregator;
}

@Bean
public FormatterLineAggregator detailFormatterLineAggregator() {
    final String[] parameterNames = {"detail01", "detail02", "detail03", "detail04"};
    BeanWrapperFieldExtractor beanWrapperFieldExtractor = new BeanWrapperFieldExtractor();
    beanWrapperFieldExtractor.setNames(parameterNames);

    FormatterLineAggregator formatterLineAggregator = new FormatterLineAggregator();
    formatterLineAggregator.setFormat("%6s%3s%3s%6s");
    formatterLineAggregator.setFieldExtractor(beanWrapperFieldExtractor);
    return formatterLineAggregator;
}
```



# ロジック実装
ファイル書き込みを実装するクラスに上記で定義したBean定義をインジェクトしファイル書き込み処理を実装する。

```java
@Autowired
FlatFileItemWriter<String> flatFileItemWriter;

@Autowired
FormatterLineAggregator headlerFormatterLineAggregator;

@Autowired
FormatterLineAggregator detailFormatterLineAggregator;

public void run(String... args) throws Exception {

    Header header = new Header("aaaa","bbbbb", "cc");
    Detail detail1 = new Detail("AAAA", "BB", "BBB", "CCCC");
    Detail detail2 = new Detail("AAAA2", "BB", "BBB", "CCCC2");
    List<Detail> detailList = new ArrayList(Arrays.asList(detail1, detail2));

    //出力先ファイルパスの設定
    //openの前に出力先ファイルパスの設定が必要
    flatFileItemWriter.setResource(new FileSystemResource("C:\\Users\\user\\test.txt"));
    flatFileItemWriter.open(new ExecutionContext());
    writeeHeader(header);
    writeDetail(detailList);

    flatFileItemWriter.close();
}

//ヘッダ部ファイル書き込みメソッド
private void writeeHeader(final Header header) throws Exception {
    final String headerString = headlerFormatterLineAggregator.aggregate(header);
    flatFileItemWriter.write(Collections.singletonList(headerString));
}

//詳細部ファイル書き込みメソッド
private void writeDetail(final List<Detail> detailList) throws Exception {
    List<String> detailStringList = new ArrayList<>();
    for(Detail detail: detailList) {
        detailStringList.add(detailFormatterLineAggregator.aggregate(detail));
    }
    flatFileItemWriter.write(detailStringList);
}
```

※詳細部をDBから取得するなどの実装を行う場合は、`detailList`のOutOfMemoryErrorに注意すること。

上記実装により、固定長ファイルが出力される。

```
  aaaa bbbbb    cc
  AAAA BBBBB  CCCC
 AAAA2 BBBBB CCCC2
```