LoginSignup
13
13

More than 5 years have passed since last update.

Spring Bootのwebアプリとバッチ処理をひとつにまとめる

Last updated at Posted at 2016-12-12

Dockerで運用しているSpring Bootでできたwebアプリに、あらたにバッチ処理が必要になった。
webアプリと同じサーバで実行するので、同一のjarでwebアプリもバッチ処理も行えるようにしてみた。
仕組みとしては、javaコマンドでjarを実行するときに目的のAppクラスを指定出来るようになっている。

ビルドの設定

pom.xml
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>sandbox.Entrypoint</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
    </plugins>
</build>

mavenでjarをビルドする時に、javaコマンドで実行されるクラスが指定する。
このクラスで、引数に応じて目的のAppクラスを切り替えられるようにする。

アプリの基底クラス

AppBase.java
@Configuration
public abstract class AppBase {

    @Autowired
    DataSource dataSource;

    @Autowired
    Dialect dialect;

    @Autowired
    Naming naming;

}

webアプリ/バッチ処理で共通して利用するデータソースの設定などを行う。

webアプリ

WebApp.java
@EnableAutoConfiguration
@ComponentScan
public class WebApp extends AppBase {

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

}

元のAppクラスから、わかりやすいように名称を変更した。
特に変わったことは行わない。

バッチ処理

Batch.java
@EnableBatchProcessing
@EnableAutoConfiguration
@ComponentScan
public class Batch extends AppBase {

    @Autowired
    JobBuilderFactory jobBuilderFactory;

    @Autowired
    StepBuilderFactory stepBuilderFactory;

    @Autowired
    Crawler crawler;

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Batch.class);
        application.setWebEnvironment(false);
        System.exit(SpringApplication.exit(application.run(args)));
    }

    @Bean
    public Step crawl() {
        return stepBuilderFactory.get("crawl").tasklet(new Tasklet() {
            public RepeatStatus execute(StepContribution stepContribution,
                    ChunkContext chunkContext) throws Exception {
                crawler.crawl();
                return RepeatStatus.FINISHED;
            }
        }).build();
    }

    @Bean
    public Job job(Step crawl) throws Exception {
        return jobBuilderFactory.get("site-crawl")
                .incrementer(new RunIdIncrementer()).start(crawl).build();
    }

}

新たに実装したAppクラス。
実行時に不要なTomcatが起動しないようにしている。

エンドポイント

Entrypoint.java
public class Entrypoint {

    public static void main(String[] args) throws Exception {
        if (args != null && args.length > 0 && "web".equals(args[0])) {
            WebApp.main(args);
            return;
        }

        Batch.main(args);
    }

}

引数に応じて目的のAppクラスを切り替えるクラス。
第1引数が「web」の場合にwebアプリを実行するように定義。
新たなバッチ処理が増えた場合は、この引数のパターンを増やして対処が出来ると思う。

Docker

FROM frolvlad/alpine-oraclejdk8:slim
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/var/app.jar"]

イメージを作成するDockerfileではjarの実行を指定するのみ。

実行

Dockerを実行するサーバの/var/xxx.jarへ、avenでビルドしたjarを配置する。

run_web.sh
docker run --name site-crawler-web \
  -d \
  -v /etc/localtime:/etc/localtime:ro \
  -v /var/xxx.jar:/var/app.jar \
  -p 80:8080 \
  container \
  web

webアプリを実行するときは、引数に「web」を指定する。

run_batch.sh
docker run --name site-crawler-batch \
  -d \
  -v /etc/localtime:/etc/localtime:ro \
  -v /var/xxx.jar:/var/app.jar \
  container \
  batch

バッチを実行するときは、引数に「batch」(「web」以外)を指定する。
バッチ処理が終わるとコンテナが終了する。

13
13
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
13
13