Try   HackMD

Spring Batchで
自動化

tags: 発表資料 AOSN メモ

aosn読書会@湯涌温泉 
2017/09/16
Takumi Okamoto


お前誰やねん

Name : 岡本 拓海

  • Tasktoys Robotics 代表
  • (株)BridgeSolution 取締役
    普段は機械設計をしたり、Webのサーバーサイド書いたりして糊口をしのいでます。
    SNSとか
  • Twitter: @MrBearin
  • Facebook: takumi.okamoto

Spring Batchとは何ぞや

  • 仕事で使ったのでちょっと紹介
  • JavaのフレームワークSpringFrameworkの一部
  • リスタートや失敗時の復帰なども簡単に書ける
  • 並列処理やWebインターフェース等、便利な機能が色々とある

概要 Job

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →


Stepの仕組み

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →


やってみよう

  • 普通にSpringApplicationを準備
  • @EnableBatchConfigurationを付与したConfigurationクラスを準備

基本設定

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
	@Bean // <-各ジョブはBeanとして定義
	public Job test(){
		// startから順番に実行される
		return jobBuilderFactory.get("test")
		.start(testStep())
		.next(testChunkStep())
               .next(lambdaStep())
               .build();
	}
}

基本はこのクラスの中に設定を書いてく


SpringBatchの基本構造

Job ⊃ Step ⊃ Tasklet or chunk


処理はどうやって書く?

  • Taskletを実装する
    • task同士の値のやり取りがない場合
  • Reader/Writerを利用する <-こっちが多いかも
    • task同士で値をやり取りする場合

Taskletを実装する場合

@Bean // 単一のタスクレットを読み込むステップ
public Step testStep(){
    return stepBuilderFactory.get("test step ")
                .tasklet(lambdaStep()).build();
}
@Bean // Taskletはラムダ式で記述することも可能
public Step lambdaStep(){
    LOGGER.info("lamda");
    return stepBuilderFactory.get("lambda step").tasklet(
            (stepContribution ,chunkContex ) 
            ->  RepeatStatus.FINISHED
        ).build();
}


値のやり取りがある場合

  1. Chunkを作る(BatchConfiguration.javaで)
  2. Reader / Processor / Writer を実装

Stepの設定

BatchConfiguration.javaで設定

//Reader -> Processor -> Writerを設定するステップ
@Bean
public Step testChunkStep(){
    return stepBuilderFactory.get("chunk step")
        .<String,String>chunk(5)
        .reader(sampleReader)
        .processor(sampleProcessor) //<-何個も書ける
        .writer(sampleWriter) // <- 基本一個だけ
        .build();
}

Reader

DBから読込み等のデータ生成タスク

@Component
public class SampleReader implements ItemReader<String>{
	int cnt = 0;
	@Override
	public String read() throws UnexpectedInputException, ParseException, NonTransientResourceException {
		if(cnt > 100) return null; //<-nullを返すと次のデータが存在しない意味になる
		cnt++;
		StringBuilder builder 
                    = new StringBuilder("No."+cnt+"//");
		builder.append(ZonedDateTime.now()
                .format(DateTimeFormatter.ISO_INSTANT));
		return builder.toString();
	}
}

Processor

バッチ処理難関の本体になるクラスクラスを受け取って他のクラスへ変換

@Component
public class SampleProcessor 
        implements ItemProcessor<String, String>{
	@Override
	public String process(String item) throws Exception {
		return new StringBuilder("****")
				.append(item)
				//.append("["+"test"+ "]")
				.append("*****").toString();
	}
}

Writer

最終的な書き出し処理

@Component
public class SampleWriter implements ItemWriter<String> {
	private static final Logger LOGGER = Logger.getLogger(SampleWriter.class);
	@Override
	public void write(List<? extends String> items) throws Exception {
		// 注意:Writer はListを受け取って処理
		items.forEach(LOGGER::info);
	}
}


DEMO

ソースはココを参照


その他

  • Restを作ってAPI化できる
  • マルチスレッド化も可能

使いどころは限られると思うけど、みんな使ってみてね!


# the End