LoginSignup
1
3

More than 3 years have passed since last update.

Spring Batchを試してみた

Last updated at Posted at 2020-09-27

概要

STSを使ってSpring Batchを使ったときの備忘録を残しておきます。
主に自分用。
Spring Batchとは、Spring Frameworkをベースにしたバッチアプリケーションフレームワークです。

開発環境は次の通りです。
OS : Windows 7 Home Edition 64bit
Java : JavaSE 8 update 181
Spring Boot : 2.3.4
STS : 4.6.1

STSのセットアップ

STSのセットアップは自分の備忘録を参考にしました。

プロジェクトの作成

下記のCreate new Spring Starter Projectをクリックします。
createProject.PNG

プロジェクトの設定をします。
NewSpringStarterProject.PNG

ライブラリ参照を設定します。
dependencies.PNG

site infoを設定、変更無しです。
siteInfo.PNG

プロジェクトができました。
ProjectExplorer.PNG

注意事項

Lombokについて

Lombokだけはjarをダウンロードして、
インストーラーで使っているSTSを選択、インストールしてください。
インストーラーはLombok公式からダウンロード可能です。
Lombokはプロジェクト参照させているため、
アノテーションを使ってもコンパイルエラーになりませんが、
getter/setter、コンストラクタが自動生成されず、
これらを呼び出そうとするとコンパイルエラーになります。
getter/setter等はIDEに自動生成させる必要があるため、
STSへのインストールも必要です。

Oracle Driverのインストール

本記事ではDBを用いていませんが、
Spring Boot+Spring Batchの構成ではDB利用を前提としています。
そのため、application.propertiesやapplication.ymlに
DB接続情報を記載していなかったり、
そもそもOracle Driverが無いといった構成で
アプリケーションを実行すると
datasourceが必要というエラーで実行できません。
そのため、動作確認したPCにセットアップしていたOracleに
接続できるよう、ライブラリ参照しています。
また、実行時にDBを起動しなくても実行可能です。
ライブラリがあって、DBスキーマに接続しようとする構成、設定なら
OKということです。

バッチアプリケーションの作成

Spring Batch公式のget startedはこちらです。
上記の場合、作ったjarを実行してcsvデータをDBのテーブルにロードする仕様です。

この記事では、cronを使わずにバッチ処理をスケジューリングしてみます。
参考にしたのはSpring Batch scheduling tasks
@Scheduledのドキュメントです。

例としてBeanを作成し、その内容をログ出力する処理を実装してみます。
ログ出力用の変数宣言やBeanクラスのボイラープレートを省略するため、Lombokを参照します。

実装したクラスは次の通りです。

まず、@SpringBootApplicationを付与したクラス、
実行時に指定するクラスです。

BatchSampleApplication.java
package jp.co.illmatics;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BatchSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(BatchSampleApplication.class, args);
    }

}

バッチ処理のメインルーチンです。
@EnableSchedulingを指定することで
バッチのスケジューリングが可能になり、
@Scheduledを指定したメソッドが
cron = "${cron.pattern1}"
で指定したタイミングで実行されます。

Batch.java
package jp.co.illmatics;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import jp.co.illmatics.bean.Member;
import jp.co.illmatics.enumeration.VoicePart;
import lombok.extern.slf4j.Slf4j;

@Configuration
@EnableScheduling
@Slf4j
public class Batch {

    private String firstName = "Dummy";
    private String familyName = "Family";
    private String part = VoicePart.LEAD_VOCAL.toString();
    private String birthday = "1991/01/01";

    @Scheduled(cron = "${cron.pattern1}")
    public void execute() {
        Member member = new Member(firstName, familyName, part, birthday);
        log.info("member = " + member.toString());
    }

}

リソースファイルです。
キーcron.pattern1でバッチ処理の実行タイミングを
毎分0秒ごとに指定しています。
書式については公式APIドキュメントをご確認ください。

application.properties
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.username=xxxxxx
spring.datasource.password=xxxxxx
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.show-sql=true

cron.pattern1: 0 * * * * *

テストデータ用のBeanです。
Bean Validationを使ってバリデーションしています。
その中でも、カスタムバリデーションとして@ExistsInVoicePartを実装しました。

Member.java
package jp.co.illmatics.bean;

import javax.validation.constraints.NotEmpty;

import org.springframework.format.annotation.DateTimeFormat;

import jp.co.illmatics.validator.annotation.ExistsInVoicePart;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Data
@AllArgsConstructor
public class Member {

    @NotEmpty(message = "Input first name.")
    private String firstName;

    @NotEmpty(message = "Input family name.")
    private String familyName;

    @ExistsInVoicePart
    private String part;

    @DateTimeFormat(pattern = "yyyy/MM/dd")
    private String birthday;

}

カスタムバリデーション用のアノテーションです。

ExistsInVoicePart.java
package jp.co.illmatics.validator.annotation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

import jp.co.illmatics.validator.VoicePartValidator;

@Constraint(validatedBy = {VoicePartValidator.class})
@Target({FIELD})
@Retention(RUNTIME)
public @interface ExistsInVoicePart {

    String message() default "Input voice part.";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    @Target({FIELD})
    @Retention(RUNTIME)
    public @interface List {
        ExistsInVoicePart[] value();
    }

}

カスタムバリデータ用のEnumです。

VoicePart.java
package jp.co.illmatics.enumeration;

public enum VoicePart {

    LEAD_VOCAL("lead vocal"),
    BEATBOXER("beatboxer"),
    BASS("bass"),
    OTHERS("others");

    @SuppressWarnings("unused")
    private final String name;

    private VoicePart(String name) {
        this.name = name;
    }
}

カスタムバリデータです。

VoicePartValidator.java
package jp.co.illmatics.validator;

import java.util.Arrays;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import jp.co.illmatics.enumeration.VoicePart;
import jp.co.illmatics.validator.annotation.ExistsInVoicePart;

public class VoicePartValidator implements ConstraintValidator<ExistsInVoicePart, String> {

    public void initialize(ExistsInVoicePart annotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return Arrays.stream(VoicePart.values()).filter(part -> part.name().equals(value)).findFirst().isPresent();
    }
}

動作確認

BatchSampleApplication.javaを右クリック、
Spring Boot Applicationとして実行します。

毎分0秒ごとに実行されています。
実行結果.PNG

以上です。最後までお読みいただき、ありがとうございました。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3