Help us understand the problem. What is going on with this article?

SpringBatchで簡単なオンデマンドバッチを作成

More than 1 year has passed since last update.

要旨

簡単なSpringBatchを作成し、Webリクエストからバッチ起動する。

環境

  • Java SE 8 (jdk-8u181)
  • Spring Boot 2.1.0

詳細手順

プロジェクト作成

SpringBatchを使用するため、依存関係にspring-boot-starter-batchを加える。
また、Job管理にDBを使用するため、適当なJDBCも加える。

pom.xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <scope>runtime</scope>
</dependency>

バッチ作成

基本的にこちらを参考に作成

バッチ実処理

@Serviceとして適当な処理クラスを作成

@Service
public class MyBatchService {

    public void execute(Long id, String name, Date reqDate) throws InterruptedException {
        // 適当なバッチ処理
        Thread.sleep(5000);
    }
}

バッチ設定

バッチ処理の肝。今回は簡単に1ステップ(タスクレット)のジョブを1つ作成する。
Javaのコンフィグレーションクラスで設定する。

@Configuration
@EnableBatchProcessing //(1)
public class BatchConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory; //(2)
    @Autowired
    private StepBuilderFactory stepBuilderFactory; //(2)

    @Autowired
    private MyBatchService service;

    @Bean
    public JobLauncher jobLauncher1(JobRepository jobRepository) { //(2),(3)
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 同時実行数は3.それ以上はキュー待ちになる.
        taskExecutor.setCorePoolSize(3); //(4)
        // java.lang.IllegalStateException: ThreadPoolTaskExecutor not initialized
        taskExecutor.initialize(); //(5)

        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        jobLauncher.setTaskExecutor(taskExecutor);

        return jobLauncher;
    }

    @Bean
    public Job job(Step step1) { //(6)
        return jobBuilderFactory.get("batchjob")
                    .incrementer(new RunIdIncrementer())
                    .start(step1)
                    .build();
    }

    @Bean
    public Step step1(Tasklet tasklet1) { //(6)
        return stepBuilderFactory.get("step1")
                    .tasklet(tasklet1)
                    .build();
    }

    @Bean
    @StepScope //(7)
    public Tasklet tasklet1( //(6)
            @Value("#{jobParameters['id']}") Long id, //(8)
            @Value("#{jobParameters['name']}") String name,
            @Value("#{jobParameters['reqDate']}") Date reqDate
            ) {
        //(9)
        MethodInvokingTaskletAdapter tasklet = new MethodInvokingTaskletAdapter();
        tasklet.setTargetObject(service);
        tasklet.setTargetMethod("execute");
        tasklet.setArguments(new Object[] {id, name, reqDate});

        return tasklet;
    }
}
(1) SpringBatchの設定であることを示す@EnableBatchProcessing@Configurationとともに付与する。
(2) いくつかのBeanはデフォルトでコンテキストに含まれているのでAutowiredすることができる。
(3) Job実行環境の設定。
(4) CorePoolSizeで同時実行数(スレッドを立てる数)を設定する。これを超える場合はキュー待ちになり、スレッドが空き次第順次実行される。
(5) initializeしておかないと"java.lang.IllegalStateException: ThreadPoolTaskExecutor not initialized"という例外が発生する。
(6) Job, Step, Taskletの設定。
(7) 実行時のパラメータを設定する場合は起動時にBeanを作成できないので@StepScopeを付与しBean作成のタイミングを変更する。
(8) jobParametersからオブジェクトを取り出す設定。
(9) Invokeで実行する。

バッチ呼び出し

@Service
public class MyServletService {

    @Autowired
    private JobLauncher jobLauncher1;
    @Autowired
    private Job job;

    public void request(Long id, String name) throws JobExecutionException {
        // (10)
        JobParameters params = new JobParametersBuilder()
                                .addLong("id", id)
                                .addString("name", name)
                                .addDate("reqDate", Calendar.getInstance().getTime())
                                .toJobParameters();

        jobLauncher1.run(job, params);
    }
}
(10) Jobに渡すパラメータをJobParametersにまとめて渡す。

起動設定

application.ymlに設定を追加する。

application.yml
spring:
  datasource: # (11)
    url: jdbc:postgresql://localhost:5432/kurukuruz1
    username: u-s-e-r
    password: p-a-s-s
    driver-class-name: org.postgresql.Driver
  batch:
    initialize-schema: always # (12)
    job:
      enabled: false # (13)
(11) 使用するDBの接続情報を設定する。
(12) SpringBatchが使用するテーブルのDDLを実行するための設定。デフォルトではembeddedで、PostgreSQLを使用する場合はDDLが実行されないので、明示的に変更しておく。
(13) デフォルトではtrueでSpring起動時にJobが実行されるが、起動時はJobParametersがないため起動時には実行できない。そのため明示的に変更しておく。

参考サイト

SpringBatch再入門 - 自分なりに使い方を整理してみた - Qiita
BLOG.IK.AM - 誤解しがちなThreadPoolTaskExecutorの設定
Spring Batch サンプルコード (Java/Gradle) - Qoosky
【Spring Batch】Jobの自動実行を行わない 指定したJob以外が自動で実行されてしまう時の制御法 - Qiita
コジオニルク - Spring Boot Batch で Hello World

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away