デジタルチャイルド日記

コンピュータ関連のいろいろメモを残していく子供部屋です。

SpringBatchを触ってみた。入門編

お仕事でバッチ処理を開発することになったので、その予習です。

具体的にどんな形になるのかは不明なので、今回はSpringBatchをいじってみました。

意外とやることが多いため、記事が少々長めになっています。

 

環境

Eclipse Neon (ver 4.6.0)

・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を使った検証が終わったら、記事にしたいと思います。