今日は時間がなくて小ネタ。
Spring Bootにはspring-boot-devtools
というものがあります。これをいれると./gradlew bootRun
で起動中にソースコードを変更しても./gradlew bootRun
を一度終了して再度起動するということをせずとも反映させることができます。これをAutomatic Restartといいます。
docs.spring.io
ここでは、以下の環境で試しました。
- Spring Boot 2.6.3
- Gradle 7.3.3
導入
build.gradle
のdependencies
にて以下を追記するだけです。
developmentOnly("org.springframework.boot:spring-boot-devtools")
EclipseとかのIDEとかを導入しているとこれだけでOKなようなのですが、IDEを使わずエディタだけで開発していた場合はこれだけではAutomatic Restartはうまく動きません。
実行
Automatic Restartをうまく動かすには、./gradlew bootRun
以外に別のコンソールにて./gradlew -t classes
を実行します。
ここでポイントは以下の二つです。
-t
オプションを指定する
classes
タスクを実行する
-t
オプションは./gradlew -h
を実行してみると以下のような説明です。
-t, --continuous Enables continuous build. Gradle does not exit and will re-execute tasks when task file inputs change.
-t
オプションを指定した場合はタスクを終了してもプロンプトを返さず待機してファイルの変更を待ち受ける状態です。
classes
タスクは以下に説明があります。
docs.gradle.org
あとはクラスパス内にあるJavaファイルやHTMLファイルを変更するとそれを検出して自動的にAutomatic Restartが動きます。
例えばPostsController.java
というプログラムを更新すると、./gradlew -t classes
を実行している画面には以下のような表示が行われます。
BUILD SUCCESSFUL in 4s
2 actionable tasks: 1 executed, 1 up-to-date
Waiting for changes to input files of tasks... (ctrl-d to exit)
modified: /Users/hogehoge/work/app_modernization_example/webapp/src/main/java/com/example/webapp/PostsController.java
Change detected, executing build...
BUILD SUCCESSFUL in 486ms
2 actionable tasks: 1 executed, 1 up-to-date
Waiting for changes to input files of tasks... (ctrl-d to exit)
./gradlew bootRun
を実行している画面はアプリケーションが再起動されていることが確認できます。
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.3)
2022-01-30 16:02:50.789 INFO 19683 --- [ restartedMain] com.example.webapp.WebappApplication : Starting WebappApplication using Java 11.0.11 on hikari.local with PID 19683 (/Users/hogehoge/work/app_modernization_example/webapp/build/classes/java/main started by hogehoge in /Users/hogehoge/work/app_modernization_example/webapp)
2022-01-30 16:02:50.789 INFO 19683 --- [ restartedMain] com.example.webapp.WebappApplication : No active profile set, falling back to default profiles: default
2022-01-30 16:02:50.899 INFO 19683 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2022-01-30 16:02:50.900 INFO 19683 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 0 ms. Found 0 JDBC repository interfaces.
2022-01-30 16:02:50.945 INFO 19683 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-30 16:02:50.946 INFO 19683 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-30 16:02:50.946 INFO 19683 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-30 16:02:50.953 INFO 19683 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-30 16:02:50.953 INFO 19683 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 162 ms
2022-01-30 16:02:51.001 INFO 19683 --- [ restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
2022-01-30 16:02:51.078 INFO 19683 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting...
2022-01-30 16:02:51.091 INFO 19683 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed.
2022-01-30 16:02:51.101 INFO 19683 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2022-01-30 16:02:51.106 INFO 19683 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-30 16:02:51.109 INFO 19683 --- [ restartedMain] com.example.webapp.WebappApplication : Started WebappApplication in 0.34 seconds (JVM running for 35.92)
2022-01-30 16:02:51.110 INFO 19683 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
2022-01-30 16:02:59.474 INFO 19683 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-01-30 16:02:59.475 INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-01-30 16:02:59.475 INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
aaa
2022-01-30 16:03:20.680 INFO 19683 --- [ Thread-7] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Shutdown initiated...
2022-01-30 16:03:20.684 INFO 19683 --- [ Thread-7] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Shutdown completed.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.3)
2022-01-30 16:03:20.729 INFO 19683 --- [ restartedMain] com.example.webapp.WebappApplication : Starting WebappApplication using Java 11.0.11 on hikari.local with PID 19683 (/Users/hogehoge/work/app_modernization_example/webapp/build/classes/java/main started by hogehoge in /Users/hogehoge/work/app_modernization_example/webapp)
2022-01-30 16:03:20.729 INFO 19683 --- [ restartedMain] com.example.webapp.WebappApplication : No active profile set, falling back to default profiles: default
2022-01-30 16:03:20.814 INFO 19683 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2022-01-30 16:03:20.814 INFO 19683 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 0 ms. Found 0 JDBC repository interfaces.
2022-01-30 16:03:20.850 INFO 19683 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-01-30 16:03:20.851 INFO 19683 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-01-30 16:03:20.851 INFO 19683 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-30 16:03:20.858 INFO 19683 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-01-30 16:03:20.858 INFO 19683 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 127 ms
2022-01-30 16:03:20.903 INFO 19683 --- [ restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index
2022-01-30 16:03:20.997 INFO 19683 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-3 - Starting...
2022-01-30 16:03:21.008 INFO 19683 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-3 - Start completed.
2022-01-30 16:03:21.017 INFO 19683 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2022-01-30 16:03:21.020 INFO 19683 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-30 16:03:21.023 INFO 19683 --- [ restartedMain] com.example.webapp.WebappApplication : Started WebappApplication in 0.309 seconds (JVM running for 65.834)
2022-01-30 16:03:21.024 INFO 19683 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
2022-01-30 16:03:24.452 INFO 19683 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-01-30 16:03:24.453 INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-01-30 16:03:24.453 INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
aaa1
<==========---> 80% EXECUTING [1m 18s]
自分が手元で試した感じ、ファイルを保存したらすぐさま変更が反映されるというわけではなく、数秒ぐらいの待ちが発生する感じがしましたが、いちいち自分で./gradlew bootRun
を終了して再度実行する手間を考えると些細な待ち時間かなと思います。