概要
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をクリックします。
注意事項
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を付与したクラス、
実行時に指定するクラスです。
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}"
で指定したタイミングで実行されます。
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ドキュメントをご確認ください。
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を実装しました。
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;
}
カスタムバリデーション用のアノテーションです。
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です。
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;
}
}
カスタムバリデータです。
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として実行します。
以上です。最後までお読みいただき、ありがとうございました。