SpringBatchを触ってみた。入門編
お仕事でバッチ処理を開発することになったので、その予習です。
具体的にどんな形になるのかは不明なので、今回はSpringBatchをいじってみました。
意外とやることが多いため、記事が少々長めになっています。
環境
・Spring boot batch 2.1.3.RELEASE (2019/03/03 最新)
(※サンプルの為、DBは未使用設定。次回予定!)
SpringBatchって
SpringはJavaをやってる人でしたら、1回は聞いたことのあるフレームワークだと思います。SpringBatchはそのフレームワークの仲間で、バッチ処理(一括処理など)に特化したフレームワークになります。
実際、バッチ処理の代表的なものは、夜間に大量のデータをファイルから読み込み、DBに書き込むとか、逆にDBに保存されているものを、一括で外部に連携するためにファイルに出力するとか、一括処理が多いのです。
SpringBootBatch
Springの中でもSpringBootと呼ばれるものがあります。これはSpringを扱いやすくする為に、いろいろなライブラリを集めて使いやすくしたものになります。
そのため、逆に不要なものが入り込んだりすることもあり、扱いには注意が必要な部分があります。(アプリがいっぱい入ったメーカー製ノートPCみたいな感じ(笑))
SpringBootBatchは、SpringBatchを扱いやすくする為、いろいろなモジュールをまとめてくれたものと考えればいいでしょう。
今回はこのSpringBootBatchを使うことにします。
導入
ライブラリ導入を楽にする為、Eclipseから、[新規]→[Maven プロジェクト]を選択して、Mavenプロジェクトを作成します。(Gradleなどを使って作成しても問題ありません)
今回は、archtypeは「maven-archtype-quickstart」を使っています。
生成されたプロジェクトのpom.xmlに以下のように編集します。
※今回はDBを使用しないようにする為、exclusion
を追加しています。これをしておかないと、DB関連の設定がない場合、実行時にエラーとなります。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jp.digitalchild.sample</groupId>
<artifactId>batch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>batch</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
<version>2.1.3.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
ファイルを保存すると自動的にMaven依存ライブラリにいろいろライブラリが追加されます。
これで一旦準備完了です。
バッチ起動のプログラムを作る
次にバッチを起動するためのクラスを作成します。といっても、よくあるmainメソッドをもったクラスになります。
EclipseからMavenプロジェクトを作成すると、App.javaというクラスができていると思うので、それを修正してみます。
package jp.digitalchild.sample.batch;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
このクラスがバッチの起動クラスになります。ここで一度実行してみると、以下のようにコンソールに出力がされるはずです。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)
2019-03-03 11:17:00.070 INFO 30488 --- [ main] jp.digitalchild.sample.batch.App : Starting App on xxxxxx with PID 999999 (XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
2019-03-03 11:17:00.073 INFO 30488 --- [ main] jp.digitalchild.sample.batch.App : No active profile set, falling back to default profiles: default
2019-03-03 11:17:00.809 INFO 30488 --- [ main] jp.digitalchild.sample.batch.App : Started App in 1.203 seconds (JVM running for 1.753)
※フォルダ情報などは、変更しています。
起動が確認できたら、次へ行きましょう。
ジョブを定義する。
SpringBatchはJOB->STEP->TASKLET or CHUNKの順に実行時の階層を持っています。それぞれを記述する必要があります。
今回はシンプルにTASKLETと呼ばれる実行単位でクラスを作成しました。
1つのクラス内に、JOBとSTEPとTASKLETを記述しています。
package jp.digitalchild.sample.batch;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableBatchProcessing
public class SampleBatchApplication {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Bean
public Job sampleJob() {
return this.jobBuilderFactory.get("sampleJob")
.start(sampleStep1())
.build();
}
@Bean
public Step sampleStep1() {
return this.stepBuilderFactory.get("sampleStep1")
.tasklet(sampleTasklet1())
.tasklet(sampleTasklet2())
.build();
}
private Tasklet sampleTasklet1() {
System.out.println("TASK1 START");
return null;
}
private Tasklet sampleTasklet2() {
System.out.println("TASK2 START");
return null;
}
}
見たいただければ、予想はできると思うのですが、sampleJob→sampleStep1→sampleTasklet1→sampleTasklet2の順に実行されていきます。sampleJob内でsampleStep1を登録し、sampleStep1内でsampleTasklet1とsampleTasklet2を順番に登録することで、上記のような順で実行がされます。
実行してみると、以下のようなコンソールが出力されます。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)
2019-03-03 11:38:05.806 INFO 32532 --- [ main] jp.digitalchild.sample.batch.App : Starting App on xxxxxx with PID 999999 (XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
2019-03-03 11:38:05.809 INFO 32532 --- [ main] jp.digitalchild.sample.batch.App : No active profile set, falling back to default profiles: default
TASK1 START
TASK2 START
2019-03-03 11:38:06.800 INFO 32532 --- [ main] jp.digitalchild.sample.batch.App : Started App in 1.424 seconds (JVM running for 2.005)
無事、Tasklet1とTasklet2が順番に実行されたことがわかると思います。
最後に
今回は、SpringBatchを導入してみよう程度の為、SpringBatchを使うメリットがよくわかりませんでしたが、CHUNKを使ってみたり、実行制御を使ってみたりすることで、わかりやすいプログラムができるのではないかと考えています。
また、Chunkを使った検証が終わったら、記事にしたいと思います。