Featured image of post 【Dockerでも可能】IntelliJ IDEでSpringBootのリモートデバッグ(remote debug)を使ってみよう【開発スピードアップ】

【Dockerでも可能】IntelliJ IDEでSpringBootのリモートデバッグ(remote debug)を使ってみよう【開発スピードアップ】

1962文字

リモートデバッグがしたい

IDEのデバッガーは優秀

SpringBootを使って開発する際は、EclipseやIntelliJなどのIDEを使うのが定番になってきています。

IDEには優秀なデバッガー機能がついているので、ローカル環境で開発をする際には欠かせない機能となっています。

デバッガーが使えない場合の対処方法

しかし、Dockerなどを使って仮想的な開発環境を作って開発をしている場合、ホスト側のIDEのデバッガーが使えずにとても苦労する場合があります。

[adsense-responsive]

そんな時は、SpringBootのリモートデバッグ機能を使えばホストとコンテナで環境が分かれている場合でもIDEのデバッガーを使うことが出来ます。

手順

前提

今回はGradleプロジェクトをIntelliJで読み込んでいることを前提としてます。

ブレイクポイントの設置

まずは、IntelliJ側デバッグポイントをマーキングしましょう。
エディターの行番号の右をクリックすると赤いマーカーがつきます。

今回はリモートデバッグを行いたいので、IntelliJからの起動ではなく以下のコマンドで起動します。

コマンド
./gradlew bootrun

もちろん、この状態ではデバッグに引っかかる事なく起動が完了してしまいます。

起動ログ
> Task :bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.0.RELEASE)

2018-11-30 17:12:29.952  INFO 59710 --- [           main] jp.blogenist.sample.SampleApplication    : Starting SampleApplication on 120.143.15.197.static.zoot.jp with PID 59710 (/Users/blogenist/tmp/work/java/springBoot/2.1.0/java/sample/build/classes/java/main started by blogenist in /Users/blogenist/tmp/work/java/springBoot/2.1.0/java/sample)
2018-11-30 17:12:29.959  INFO 59710 --- [           main] jp.blogenist.sample.SampleApplication    : No active profile set, falling back to default profiles: default
2018-11-30 17:12:31.975  INFO 59710 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2018-11-30 17:12:32.024  INFO 59710 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-11-30 17:12:32.024  INFO 59710 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/9.0.12
2018-11-30 17:12:32.043  INFO 59710 --- [           main] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/blogenist/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2018-11-30 17:12:32.197  INFO 59710 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-11-30 17:12:32.198  INFO 59710 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2132 ms
2018-11-30 17:12:32.246  INFO 59710 --- [           main] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-11-30 17:12:32.251  INFO 59710 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-11-30 17:12:32.252  INFO 59710 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-11-30 17:12:32.252  INFO 59710 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'formContentFilter' to: [/*]
2018-11-30 17:12:32.252  INFO 59710 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-11-30 17:12:32.615  INFO 59710 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2018-11-30 17:12:32.991  INFO 59710 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-11-30 17:12:32.996  INFO 59710 --- [           main] jp.blogenist.sample.SampleApplication    : Started SampleApplication in 3.833 seconds (JVM running for 4.443)
Debug Point.
<=========----> 75% EXECUTING [11s]
> :bootRun

RemoteConfigの作成

では、IntelliJ側にリモートデバッグを検知するための設定を作成しましょう。

ツールバーのRunからEdit Configurationsを選択します。

次に、左上の+マークをクリックしてRemoteを選択します。

すると、設定ダイアログが表示されるので、Nameに任意の名称を入れ、その他はデフォルトのままOKボタンをクリックします。

これでIntelliJ側の設定は完了です。

起動コマンドにオプションを追加

次に起動する際のコマンドに--debug-jvmオプションを加えて起動してみてください。

コマンド
./gradlew bootrun --debug-jvm

すると、以下のようにListening状態になります。

起動ログ
> Task :bootRun
Listening for transport dt_socket at address: 5005
<=========----> 75% EXECUTING [25s]
> :bootRun

これは、5005ポートデバッグ先を探している状態になります。
このログが表示されたらIntelliJ側で先ほど作成したRemoteで起動してみましょう。

すると、以下のようなログがIntelliJ側で出力されます。

bootrun側も正常に起動が始まります。

起動ログ
> Task :bootRun
Listening for transport dt_socket at address: 5005

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.0.RELEASE)

2018-11-30 17:26:03.112  INFO 60057 --- [           main] jp.blogenist.sample.SampleApplication    : Starting SampleApplication on 120.143.15.197.static.zoot.jp with PID 60057 (/Users/blogenist/tmp/work/java/springBoot/2.1.0/java/sample/build/classes/java/main started by blogenist in /Users/blogenist/tmp/work/java/springBoot/2.1.0/java/sample)
2018-11-30 17:26:03.121  INFO 60057 --- [           main] jp.blogenist.sample.SampleApplication    : No active profile set, falling back to default profiles: default
2018-11-30 17:26:05.595  INFO 60057 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2018-11-30 17:26:05.654  INFO 60057 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-11-30 17:26:05.656  INFO 60057 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/9.0.12
2018-11-30 17:26:05.747  INFO 60057 --- [           main] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/blogenist/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2018-11-30 17:26:06.019  INFO 60057 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-11-30 17:26:06.026  INFO 60057 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2793 ms
2018-11-30 17:26:06.083  INFO 60057 --- [           main] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-11-30 17:26:06.093  INFO 60057 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-11-30 17:26:06.094  INFO 60057 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-11-30 17:26:06.095  INFO 60057 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'formContentFilter' to: [/*]
2018-11-30 17:26:06.095  INFO 60057 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-11-30 17:26:06.563  INFO 60057 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2018-11-30 17:26:06.951  INFO 60057 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-11-30 17:26:06.957  INFO 60057 --- [           main] jp.blogenist.sample.SampleApplication    : Started SampleApplication in 4.64 seconds (JVM running for 13.966)
<=========----> 75% EXECUTING [2m 57s]
> :bootRun

[adsense-responsive]

そして、IntelliJ側のデバッグポイントに引っかかるようになりました!!

もちろん、引数が存在していれば中身を確認することも出来ます。
試してみましょう。

build.gradleに以下を追記して、

build.gradle
bootRun {
	if (project.hasProperty('args')) {
		args project.args.split('\\s+')
	}
}

以下のコマンドで再度起動してみましょう。

コマンド
./gradlew bootrun -Pargs="hoge" --debug-jvm

正しく変数内の値も参照出来ますね。

終わりに

システム開発をする際に、デバッグが出来るか出来ないかで大きく開発スピードが変わってきます。

毎回ログに出して確認する方法だと、他の変数の値を確認したくなった場合に都度loggerの仕込みをする必要があったり、loggerの消し忘れなどの懸念があるので、なるべくデバッガーを使うようにしてみましょう。