TL; DR
-
CommandLineRunner
は使うけど、CommandLineRunner#run(String... args) は、Application 起動完了前に呼び出されてしまうため、初期化に読み替えて、サブクラスでオーバーライドする - 複数のコマンドは
@ConditionalOnProperty(name = "command", havingValue = "xxx")
で起動し分けるとよさげ。
Motivation
Spring boot 、Web サーバーをさくっと上げるところから本格的なサービスにも使えて、Batch もある程度あります。
Web サービスに使ってるロジックや、Batch 用ロジックなんかを手元で実行したかったり(何かおこったときの再実行とか。。。。)にそのまま実行できる .jar を作っておくと便利なのですが、やり方が色々あって悩む事多しの状況だったのでメモです。
Sampleコード全部
package echo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SpringBootApplication
public class EchoApplication {
public abstract static class Command implements CommandLineRunner {
public final void run(final String... args) throws Exception {
log.debug("Initialize started on {}", getClass());
// 実際、CommandLineRunner#run(String... args) は、Application 起動完了前に呼び出されてしまう。
// ここでは初期化に読み替えて、サブクラスでオーバーライドする
init(args);
}
void init(final String... args) throws Exception {
// 生引数を引き取って何かする
}
/**
* サブクラスで実装
* @throws Exception
*/
abstract void execute() throws Exception;
}
public static void main(final String... args) throws Exception {
try (ConfigurableApplicationContext context = SpringApplication.run(EchoApplication.class, args)) {
context.getBean(Command.class).execute();
// Command を取って実行
}
}
@Service
@ConditionalOnProperty(name = "command", havingValue = "foo")
public static class FooFeature extends Command {
@Override
void execute() throws Exception {
log.info("Foo");
}
}
@Service
@ConditionalOnProperty(name = "command", havingValue = "bar")
public static class BarFeature extends Command {
@Override
void execute() throws Exception {
log.info("Bar");
}
}
}
実行するとこんな感じに
% java -jar xxxx.jar --command=foo
2017-09-09 20:58:48.464 INFO 20274 --- [ main] echo.EchoApplication : Started EchoApplication in 2.895 seconds (JVM running for 3.342)
2017-09-09 20:58:48.464 INFO 20274 --- [ main] echo.EchoApplication : Foo
% java -jar xxxx.jar --command=bar
2017-09-09 20:58:48.464 INFO 20274 --- [ main] echo.EchoApplication : Started EchoApplication in 2.895 seconds (JVM running for 3.342)
2017-09-09 20:58:48.464 INFO 20274 --- [ main] echo.EchoApplication : Bar
その他
WebApp とまとめる
WebApp, CommandLine Tool をまとめたいときは、command line tool として実行するときは
--spring.main.web-environment=false
で Web Context が起動しなくなります。
command profile を作って application.yml
に書いておくと楽かも