Spring Boot + npm + Geb で入力フォームを作ってテストする ( その78 )( PMD を 6.5.0 → 6.6.0 へバージョンアップする+gradle-processes を導入する )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- build 時の警告ログが出なくなるような記事を見かけたので、PMD を 6.5.0 → 6.6.0 へバージョンアップしてみます。
- Gradle 4.6 以降に対応した gradle-processes 0.5.0 がリリースされていましたので、正式に導入します。
参照したサイト・書籍
目次
手順
PMD を 6.5.0 → 6.6.0 へバージョンアップする
build.gradle の以下の点を変更します。
pmd { toolVersion = "6.6.0" sourceSets = [project.sourceSets.main] ignoreFailures = true consoleOutput = true ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml") ruleSets = [] }
toolVersion = "6.5.0"
→toolVersion = "6.6.0"
に変更します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
clean タスク実行 → Rebuild Project → build タスクを実行してみますが、出力されるログはほとんど変わりませんでした。
- 以前は出ていなかった
Could not determine ant log level, no supported build listeners found. Log level is set to FINEST
というメッセージが表示されていました。 This analysis could be faster, please consider using Incremental Analysis: https://pmd.github.io/pmd-6.6.0/pmd_userdocs_incremental_analysis.html
が2行出力される点は変わらず。
Could not determine ant log level, no supported build listeners found. Log level is set to FINEST
の方は調べると以下の Issue を見つけました。PMD 6.7.0 待ちのようです。
- [core] No supported build listeners found with Gradle
- [core] Add support for Gradle's AntLoggingAdapter
gradle-processes を導入する
https://mvnrepository.com/artifact/gradle.plugin.com.github.jengelman.gradle.plugins/gradle-processes を見ると 0.5.0 がリリースされていました。
Not compatible with gradle 4.8.1 due to changes in gradles internal api の Issue が反映されたバージョンのはずなので、正式に導入してみます。
build.gradle の以下の点を変更します。
buildscript { ext { group "ksbysample" version "1.0.2-RELEASE" } repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } } plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.0.4.RELEASE" id "io.spring.dependency-management" version "1.0.6.RELEASE" id "groovy" id "net.ltgt.errorprone" version "0.0.14" id "checkstyle" id "com.github.spotbugs" version "1.6.2" id "pmd" id "com.moowork.node" version "1.2.0" id "com.gorylenko.gradle-git-properties" version "1.5.1" id "com.github.johnrengelman.processes" version "0.5.0" }
- buildscript block に
repositories { ... }
を追加します。 - plugins block に
id "com.github.johnrengelman.processes" version "0.5.0"
を追加します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
次に build.gradle に Web アプリの自動起動、自動停止のタスクを追加します。build.gradle の以下の点を変更します。
buildscript { ext { group "ksbysample" version "1.0.2-RELEASE" mainClass = "ksbysample.webapp.bootnpmgeb.Application" } .......... } .......... // for Geb + Spock Integration Test task startServer(type: com.github.jengelman.gradle.plugins.processes.tasks.JavaFork) { jvmArgs = [ '-Dspring.profiles.active=develop', '-Dlogging.level.root=OFF', '-Dlogging.level.org.springframework.web=OFF', '-Dlogging.level.jdbc.sqlonly=OFF', '-Dlogging.level.jdbc.sqltiming=OFF', '-Dlogging.level.jdbc.audit=OFF', '-Dlogging.level.jdbc.resultset=OFF', '-Dlogging.level.jdbc.resultsettable=OFF', '-Dlogging.level.jdbc.connection=OFF' ] classpath += sourceSets.main.runtimeClasspath main = "${mainClass}" doLast { Thread.sleep(15000) } } task stopServer { doLast { startServer.processHandle.abort() } } def drivers = ["chrome", "firefox"] drivers.each { driver -> task "${driver}Test"(type: Test) { // 前回実行時以降に何も更新されていなくても必ず実行する outputs.upToDateWhen { false } systemProperty "geb.env", driver exclude "ksbysample/**" dependsOn startServer finalizedBy stopServer } } task gebTest { dependsOn drivers.collect { tasks["${it}Test"] } enabled = false }
- buildscript block に
mainClass = "ksbysample.webapp.bootnpmgeb.Application"
を追加します。 - startServer, stopServer タスクを追加します。
drivers.each { driver -> task "${driver}Test"(type: Test) { ... } }
内に以下の2行を追加します。dependsOn startServer
finalizedBy stopServer
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
まずは clean タスク実行 → Rebuild Project → build タスクを実行してみます。BUILD SUCCESSFUL が出力されて、startServer と stopServer タスクは実行されませんでした。
gebTask を実行してみます。startServer → chromeTest, firefoxTest → stopServer の順に実行されて、BUILD SUCCESSFUL が表示されました。
chromeTest タスクだけを実行しても startServer → chromeTest → stopServer の順に実行されて、テストは全て成功しました。
firefoxTest タスクだけを実行しても startServer → chromeTest → stopServer の順に実行されて、テストは全て成功しました。
最後に
やりたいことが一通り終わりました。「Spring Boot + npm + Geb で入力フォームを作ってテストする」は以上で終わりです。
次は以下のことを書くつもりです。
- Windows 10 PC を購入したので、まずは今の環境(Windows 7)から移行します。
- その後に ksbysample-webapp-lending の Spring Boot 1.5 → 2.0 バージョンアップを行います。
- 気がむいたら Spring Integration ネタをしばらく書いていないので、何か書くかもしれません。あるいは最近覚えている AWS 関連で何か試したいネタを見つけて書けるといいかな。。。
履歴
2018/08/13
初版発行。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その77 )( RequestAndResponseLogger クラスの Cookie ログは name, value だけ出力するように変更する+SESSION Cookie の secure 属性を true にするには? )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その76 )( Spring Boot Actuator を導入する ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Spring Boot + npm + Geb で入力フォームを作ってテストする ( その75 )( コネクションプーリング用ライブラリを Tomcat connection pool → HikariCP に切り替える ) で RequestAndResponseLogger クラスが出力しているリクエスト、レスポンスのログを見て SESSION Cookie の domain 属性が null、httponly 属性が false と出力されていて、何か問題がありそうだったので調査します。
参照したサイト・書籍
Turn off HttpOnly Spring boot
https://stackoverflow.com/questions/22428233/turn-off-httponly-spring-bootAdd secure flag to JSESSIONID cookie in spring automatically
https://stackoverflow.com/questions/39252924/add-secure-flag-to-jsessionid-cookie-in-spring-automaticallySpring Session
https://docs.spring.io/spring-session/docs/2.0.4.RELEASE/reference/html5/Spring Session - Custom Cookie
https://docs.spring.io/spring-session/docs/2.0.4.RELEASE/reference/html5/guides/java-custom-cookie.html
目次
- 現在の状況を確認する
- サーバから Cookie の domani 属性が未セットの状態で返されると、ブラウザはアクセスした時のドメインをセットする?
- Spring Session では SESSION Cookie の httponly 属性をデフォルトで有効にしている?
- RequestAndResponseLogger クラスの Cookie のログでは name, value しか出力しないように変更する
- SESSION Cookie の secure 属性を true にするには?
手順
現在の状況を確認する
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その75 )( コネクションプーリング用ライブラリを Tomcat connection pool → HikariCP に切り替える ) で、ksbysample.webapp.bootnpmgeb.aspect.logging.RequestAndResponseLogger が出力しているログを見ると SESSION Cookie の domain 属性が null だったり、httponly 属性が false だったりしていたのですが、
[req][cookie] name = SESSION, value = MThlNDQ3NGUtNmQ0Mi00Y2Q2LTlmNTYtMDA4ZDZlYjg3NTQ3, domain = null, path = null, maxage = -1, secure = false, httponly = false
Chrome の Develper Tools で SESSION Cookie を確認すると domain 属性も httponly 属性もセットされていました。
Develper Tools で SESSION Cookie を削除してから再度リクエストを送信し、Fiddler で SESSION Cookie が最初に返される時の HTTP ヘッダを確認したところ以下の文字列が返ってきており、domain 属性はありませんが httponly 属性はセットされていました。
Set-Cookie: SESSION=ZDIyYThlZTctZDg1Yi00MGYyLTgwZmEtNzA4N2U4Y2E1YTY4; Path=/; HttpOnly
今度はリクエストの送信時に Cookie をどのように送信しているかを見てみると以下の文字列が HTTP ヘッダで送信されており、Cookie はキーと値しか送信されていませんでした。
Cookie: SESSION=ZDIyYThlZTctZDg1Yi00MGYyLTgwZmEtNzA4N2U4Y2E1YTY4
ということは、
- サーバから Cookie の domani 属性が未セットの状態で返されると、ブラウザはアクセスした時のドメインをセットする?
- Spring Session では SESSION Cookie の httponly 属性をデフォルトで有効にしている?
- request 時のデータを ksbysample.webapp.bootnpmgeb.aspect.logging.RequestAndResponseLogger で出力しているが、request では Cookie は name と value しか送信されないので、それ以外の属性を出力しても意味がない。
サーバから Cookie の domani 属性が未セットの状態で返されると、ブラウザはアクセスした時のドメインをセットする?
調べたら CookieのDomain属性は 指定しない が一番安全 という記事を見つけました。内容が分かりやすく納得しました。domain 属性はセットしてはいけないんですね。
Spring Session では SESSION Cookie の httponly 属性をデフォルトで有効にしている?
org.springframework.session.web.http.DefaultCookieSerializer を見ると private boolean useHttpOnlyCookie = true;
と実装されていました。デフォルトで httponly 属性を有効にしていました。
RequestAndResponseLogger クラスの Cookie のログでは name, value しか出力しないように変更する
src/main/java/ksbysample/webapp/bootnpmgeb/aspect/logging/RequestAndResponseLogger.java の以下の点を変更します。
private void loggingRequestCookies(HttpServletRequest request) { if (request.getCookies() != null) { Arrays.asList(request.getCookies()).forEach(cookie -> { StringBuilder sb = new StringBuilder(); sb.append("name = ") .append(cookie.getName()) .append(", value = ") .append(cookie.getValue()); logging(LOG_REQUEST_COOKIE, null, sb.toString()); }); } }
- loggingRequestCookies メソッド内の
.append(", domain = ") ... .append(cookie.isHttpOnly());
を削除します。
これで SESSION Cookie をログに出力すると以下のように name, value しか出力されません。
[req][cookie] name = SESSION, value = OTk1MmIzZDktMjQwMi00NDEyLTgwZWItYWQyOTQ5MGYyMmUx
SESSION Cookie の secure 属性を true にするには?
Spring Session - Custom Cookie に記述がありました。
src/main/java/ksbysample/webapp/bootnpmgeb/config/ApplicationConfig.java に cookieSerializer Bean を定義し、その中で cookieSerializer.setUseSecureCookie(true);
を呼び出して secure 属性を有効にします。独自の cookieSerializer Bean を定義すると Spring Session でこちらが使用されるようになります。
@Bean public CookieSerializer cookieSerializer() { DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); cookieSerializer.setUseSecureCookie(true); return cookieSerializer; }
動作確認してみます。bs-springboot-config.js に https: true,
を追加して Browsersync で https を処理できるようにします。
.......... serveStatic: [], https: true, ghostMode: { ..........
Tomcat を起動した後、npm run springboot
コマンドを実行します。
Chrome の Developer Tools で SESSION Cookie を削除した後、https://localhost:9080/inquiry/input/01/ にアクセスします。
画面が表示された後、Developer Tools で SESSION Cookie を見ると secure 属性が有効になっていることが確認できます。
履歴
2018/08/12
初版発行。
IntelliJ IDEA を 2018.1.6 → 2018.2.1 へバージョンアップ
IntelliJ IDEA を 2018.1.6 → 2018.2.1 へバージョンアップする
IntelliJ IDEA の 2018.2.1 がリリースされているのでバージョンアップします。
- IntelliJ IDEA 2018.2: MacBook Touch Bar, Java 11, Breakpoint Intentions, Spring Boot, Version Control, and More
https://blog.jetbrains.com/idea/2018/07/intellij-idea-2018-2-macbook-touch-bar-java-11-breakpoint-intentions-spring-boot-version-control-and-more/ - Spring and Spring Boot Improvements in IntelliJ IDEA 2018.2
https://blog.jetbrains.com/idea/2018/07/spring-and-spring-boot-improvements-in-intellij-idea-2018-2/ - IntelliJ IDEA 2018.2.1 Update Available
https://blog.jetbrains.com/idea/2018/08/intellij-idea-2018-2-1-update-available/
※ksbysample-webapp-lending プロジェクトを開いた状態でバージョンアップしています。
IntelliJ IDEA のメインメニューから「Help」-「Check for Updates...」を選択します。
「IDE and Plugin Updates」ダイアログが表示されます。「Update and Restart」ボタンではなく「Download」ボタンが表示されています。
「Download」ボタンを押して IntelliJ IDEA の Download ページを開いた後、「DOWNLOAD」ボタンを押して ideaIU-2018.2.1.exe をダウンロードします。
起動している IntelliJ IDEA を終了します。
ideaIU-2018.2.1.exe を実行します。
「IntelliJ IDEA Setup」ダイアログが表示されます。「Next >」ボタンをクリックします。
「Uninstall old versions」画面が表示されます。画面上の全てのチェックボックスをチェックした後、「Next >」ボタンをクリックします。
「Choose Install Location」画面が表示されます。「Destination Folder」を C:\IntelliJ_IDEA\2018.2.1 に変更した後、「Next >」ボタンをクリックします。
「Installation Options」画面が表示されます。何も変更せずに「Next >」ボタンをクリックします。
「Choose Start Menu Folder」画面が表示されます。何も変更せずに「Install」ボタンをクリックします。
「Installing」画面が表示されてインストールが始まりますので、完了するまで待ちます。
インストールが完了すると「Completing IntelliJ IDEA Setup」画面が表示されます。「Finish」ボタンをクリックしてダイアログを閉じます。
C:\IntelliJ_IDEA\2018.1.4 フォルダが残っていましたので削除します。
C:\IntelliJ_IDEA\2018.2.1\bin\idea64.exe を実行します。
「Complete Installation」ダイアログが表示されますので「Previous version」が選択された状態で「OK」ボタンをクリックします。
IntelliJ IDEA のメイン画面が表示され画面下部に「Indexing…」のメッセージが表示されますので、終了するまで待機します。
Plugin が最新にアップデートされていないので先にアップデートします。IntelliJ IDEA のメインメニューから「Help」-「Check for Updates...」を選択します。
「IDE and Plugin Updates」ダイアログが表示されます。何も変更せずに「Update」ボタンをクリックします。
Patch がダウンロードされた後、IntelliJ IDEA を再起動します。再起動後、画面下部に「Indexing…」のメッセージが表示されますので、終了するまで待機します。
IntelliJ IDEA のメインメニューから「Help」-「About」を選択し、2018.2.1 へバージョンアップされていることを確認します。
Gradle Tool Window のツリーを見ると「Tasks」の下に「other」しかない状態になっているので、左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
Gradle のアイコンが変わっているし、ボタンも青ではなくグレーになっていますね。よく見たら IntelliJ IDEA のボタンが全面的にグレーになっていて、調べたところ 2018.2 からアイコンを変更したことに関するBlog のページが見つかりました。個人的にアイコンがグレーなのは見にくかったので、迷わず ToolWindow Colorful Icons Plugin をインストールしました。
- New icons in IntelliJ Platform 2018.2
https://blog.jetbrains.com/blog/2018/06/26/new-icons-in-intellij-platform-2018-2/
- New icons in IntelliJ Platform 2018.2
clean タスク実行 → Rebuild Project 実行 → build タスクを実行して、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。
Run Tool Window を閉じようと思ったら、X アイコンも無くなっていますね。以下のページに無くした理由が記載されています。
- Unify closing action button for tool window
https://youtrack.jetbrains.com/issue/IDEA-72146
- Unify closing action button for tool window
Project Tool Window で src/test を選択した後、コンテキストメニューを表示して「Run with Coverage」-「All Tests」を選択し、テストが全て成功することを確認します。
最後に C:\Users\root.IntelliJIdea2018.1 を削除します。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その76 )( Spring Boot Actuator を導入する )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- Spring Boot Actuator を導入します。
参照したサイト・書籍
Spring Boot 2.0のActuator、とりあえず動かすために知っておきたい変更点3つ
https://qiita.com/suke_masa/items/acfdf52019538fd8ccc6Introducing Actuator Endpoints in Spring Boot 2.0
https://spring.io/blog/2017/08/22/introducing-actuator-endpoints-in-spring-boot-2-0Spring Boot Reference Guide - 28.4 Actuator Security
https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-security-actuatorSpring Boot Reference Guide - Part V. Spring Boot Actuator: Production-ready features
https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#production-readySpring Boot Actuator Web API Documentation
https://docs.spring.io/spring-boot/docs/current/actuator-api/html/How can authenticate user by only ip address in spring security?
https://stackoverflow.com/questions/38304078/how-can-authenticate-user-by-only-ip-address-in-spring-securityCloudFoundry: Java thread and heap dump analysis on remote containers
https://fabianlee.org/2017/12/08/cloudfoundry-java-thread-and-heap-dump-analysis-on-remote-containers/IBM Thread and Monitor Dump Analyzer for Java
https://www.ibm.com/developerworks/community/groups/service/html/communityview?communityUuid=2245aa39-fa5c-4475-b891-14c205f7333cSpring security multiple hasIPAddress antMatchers
https://stackoverflow.com/questions/28303097/spring-security-multiple-hasipaddress-antmatchersSpring Boot Actuator 2.0 & Micrometer
https://www.slideshare.net/makingx/spring-boot-actuator-20-micrometerSpring Boot Actuator metrics monitoring with Prometheus and Grafana
https://www.callicoder.com/spring-boot-actuator-metrics-monitoring-dashboard-prometheus-grafana/
目次
- Actuator を導入せずに IntelliJ IDEA から Tomcat を起動するとどのような状態か?
- build.gradle を変更する
- IntelliJ IDEA から Tomcat を起動して Run Tool Window を確認する
- ログレベルを変更してみる
/actuator/**
を Spring Security の CSRF チェックの対象外にする- ログレベルを変更してみる(続き)
- Info Endpoint から情報を取得してみる
- Shutdown Endpoint からシャットダウンしてみる
- Thread Dump Endpoint からスレッドダンプを出力してみる
/actuator/**
に IPアドレスでアクセス制限をかけるには?- 最後に
手順
Actuator を導入せずに IntelliJ IDEA から Tomcat を起動するとどのような状態か?
IntelliJ IDEA から Tomcat を起動後、画面の下の Run Tool Window 内に表示される「EndPoints」タブの中の「Health」「Mappings」タブを見ると Spring Boot Actuator is not enabled. Add dependency to the spring-boot-actuator to enable it.
のメッセージが表示されています。
build.gradle を変更する
build.gradle の以下の点を変更します。
dependencies { .......... implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-actuator") runtimeOnly("org.springframework.boot:spring-boot-devtools") ..........
implementation("org.springframework.boot:spring-boot-starter-actuator")
を追加します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
IntelliJ IDEA から Tomcat を起動して Run Tool Window を確認する
今度は「Health」「Mappings」タブ内にデータが表示されるようになりました。
- デフォルトで health check してくれる対象は 50.9.1 Auto-configured HealthIndicator に一覧があります。Elasticsearch、Rabbit、Redis 等もチェックしてくれるようです。
- 現在メールサーバ(smtp4dev)を起動していないので、mail に「Status: DOWN」のアイコンが表示されていました。
- 「Mappings」に表示されている Path の内リンクになっているもの(おそらく GET でアクセス可能なもの?)をクリックすると、ブラウザが起動してドメイン名やポート番号を追加された URL でアクセスしてくれます。大量に表示されていても IntelliJ IDEA の Search 機能が効くのでパスをタイプすると該当するものにジャンプしてくれます(下の例だと
input 03
と入力しています)。これは以外に便利な機能ではないでしょうか。 - webjars は導入していないのですが、
/webjars/**
が表示されていました。Spring Boot Reference Guide を見たところIn addition to the “standard” static resource locations mentioned earlier, a special case is made for Webjars content. Any resources with a path in /webjars/** are served from jar files if they are packaged in the Webjars format.
という記述があり、src/main/resources の下に static ディレクトリを作成すると自動で/webjars/**
の mapping?を作成するようです。初めて知りました。。。
smtp4dev を起動すると mail のアイコンが「Status: UP」のものに変わりました。IntelliJ IDEA で起動している場合にはデフォルトだと 15秒間隔でチェックされます(「Endpoints」タブ内の左側にある歯車アイコンをクリックすると設定画面が表示されます。)。
ログレベルを変更してみる
application.properties に設定を追加して Loggers endpoint を有効にします。
doma.dialect=org.seasar.doma.jdbc.dialect.H2Dialect management.endpoints.web.exposure.include=health,info,loggers spring.datasource.hikari.jdbc-url=jdbc:h2:mem:bootnpmgebdb ..........
management.endpoints.web.exposure.include=health,info,loggers
を追加します。management.endpoints.web.exposure.include
の設定を追加する場合、デフォルトで有効になっている health, info も記述しないと無効になります。
IntelliJ IDEA から Tomcat を再起動した後、ブラウザから http://localhost:8080/inquiry/input/01 にアクセスすると以下のログが出力されます。application-develop.properties に logging.level.org.springframework.web=DEBUG の設定を入れていますので、DEBUG ログが出力されています。
Spring Boot Actuator Web API Documentation を参考に、コマンドプロンプトから curl 'http://localhost:8080/actuator/loggers/org.springframework.web' -i -X POST -H 'Content-Type: application/json' -d '{"configuredLevel":"info"}'
コマンドを実行します。。。が 403 でアクセス拒否されました。Spring Security が入っているので POST メソッドだと CSRF のチェック対象から外さないとアクセスできませんでした。
/actuator/**
を Spring Security の CSRF チェックの対象外にする
src/main/java/ksbysample/webapp/bootnpmgeb/config/WebSecurityConfig.java の以下の点を変更します。http.csrf()
に .ignoringAntMatchers(...)
というメソッドがあることに気づいたのでいろいろ書き直します。
package ksbysample.webapp.bootnpmgeb.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * ??? */ @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private static final String ACTUATOR_ANT_PATTERN = "/actuator/**"; private static final String H2_CONSOLE_ANT_PATTERN = "/h2-console/**"; @Value("${spring.h2.console.enabled:false}") private boolean springH2ConsoleEnabled; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します // .antMatchers("/country/**").permitAll() // // この Web アプリケーションでは Spring Security を CSRF対策で使用したいだけなので、 // 全ての URL を認証の対象外にする .antMatchers("/**").permitAll() .anyRequest().authenticated(); // Spring Boot Actuator のパスは CSRF チェックの対象外にする http.csrf().ignoringAntMatchers(ACTUATOR_ANT_PATTERN); // spring.h2.console.enabled=true に設定されている場合には H2 Console を表示するために必要な設定を行う if (springH2ConsoleEnabled) { http.csrf().ignoringAntMatchers(H2_CONSOLE_ANT_PATTERN); http.headers().frameOptions().sameOrigin(); } } }
private static final Pattern DISABLE_CSRF_TOKEN_PATTERN = Pattern.compile("(?i)^(GET|HEAD|TRACE|OPTIONS)$");
を削除します。private static final String ACTUATOR_ANT_PATTERN = "/actuator/**";
を追加します。private static final Pattern H2_CONSOLE_URI_PATTERN = Pattern.compile("^/h2-console");
→private static final String H2_CONSOLE_ANT_PATTERN = "/h2-console/**";
に変更します。http.csrf().ignoringAntMatchers(ACTUATOR_ANT_PATTERN);
を追加します。http.csrf()
から.requireCsrfProtectionMatcher(...)
を削除し、.ignoringAntMatchers(H2_CONSOLE_ANT_PATTERN)
を追加します。
ログレベルを変更してみる(続き)
再度 curl コマンドを実行すると、今度は 204(No Content)が返ってきました。成功したようです。
ブラウザから http://localhost:8080/inquiry/input/01 にアクセスしてログを出力してみると DEBUG ログが出力されていません。これまで設定を変更して再起動しないと変更できないものと思っていたので、これはちょっと感激です。
curl 'http://localhost:8080/actuator/loggers/org.springframework.web' -i -X GET
コマンドを実行すれば、現在設定されているログレベルが取得できます。
Info Endpoint から情報を取得してみる
Spring Boot Actuator Web API Documentation - 11. Info (info) を参考にコマンドプロンプトから curl 'http://localhost:8080/actuator/info' -i -X GET
コマンドを実行してみます。。。が、何も返ってきませんでした。"git" と "build" の情報が返ってくるものと思ったのですが。
調べてみると Spring Boot Reference Guide に以下の記述を見つけました。build.gradle に設定を追加して情報を生成しないといけないようです。
build.gradle の以下の点を変更します。
plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.0.4.RELEASE" id "io.spring.dependency-management" version "1.0.6.RELEASE" id "groovy" id "net.ltgt.errorprone" version "0.0.14" id "checkstyle" id "com.github.spotbugs" version "1.6.2" id "pmd" id "com.moowork.node" version "1.2.0" id "com.gorylenko.gradle-git-properties" version "1.5.1" } .......... // for Doma 2 // JavaクラスとSQLファイルの出力先ディレクトリを同じにする processResources.destinationDir = compileJava.destinationDir // コンパイルより前にSQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する compileJava.dependsOn processResources springBoot { buildInfo() }
- plugins block に
id "com.gorylenko.gradle-git-properties" version "1.5.1"
を追加します。 springBoot { buildInfo() }
を追加します。
変更後、Tomcat を停止してから Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
clean タスク → Rebuild Project → build タスクを実行すると bootBuildInfo
と generateGitProperties
というタスクが追加されていました。
Tomcat を起動して、再び curl 'http://localhost:8080/actuator/info' -i -X GET
コマンドを実行してみますがやっぱり何も出ません。どうも Executable Jar から起動しないと何も出ないようです。
Tomcat を停止後 Executable Jar から起動して再度コマンドを実行すると、今度は情報が返ってきました。
JSON がフォーマットされていなくて見にくいので、jq というツールを入れてフォーマットしてみます。Download jq から「Windows」の jq 1.5 executables for 64-bit or 32-bit.
の 64-bit
のリンクをクリックして jq-win64.exe をダウンロードした後、ファイル名を jq.exe に変更して C:\Git\mingw64\bin の下へ入れます。
HTTPヘッダは不要なので -i
オプションを外し、他にも余計な情報を出さないように -s
オプションを付けて curl 'http://localhost:8080/actuator/info' -X GET -s | jq
コマンドを実行するときれいに整形されました。
Shutdown Endpoint からシャットダウンしてみる
application.properties に設定を追加して Shutdown endpoint を有効にします。Shutdown endpoint は management.endpoints.web.exposure.include
に endpoint 名を追加するだけでは有効にならず、management.endpoint.shutdown.enabled=true
も追加する必要があります(Appendix A. Common application properties に記述がありました)。
management.endpoints.web.exposure.include=health,info,loggers,shutdown management.endpoint.shutdown.enabled=true
IntelliJ IDEA から Tomcat を起動後、curl 'http://localhost:8080/actuator/shutdown' -i -X POST
コマンドを実行すると {"message":"Shutting down, bye..."}
のレスポンスが返ってきました。
しかし、Tomcat の方は落ちませんでした。これも Executable Jar から起動しないとダメなのかな。。。
boot-npm-geb-sample-1.0.2-RELEASE.jar を作成し直してコピーしてから、コマンドプロンプトから起動してみます。
curl 'http://localhost:8080/actuator/shutdown' -i -X POST
コマンドを実行すると、
今度は Tomcat が停止しました。ログは IntelliJ IDEA から Tomcat を起動した時と同じく HikariPool-1 - Shutdown completed.
で終わっていました。
ちなみにサービスに登録して起動してから、
curl コマンドを実行して停止してもサービスの画面上は起動したままでした。ログは HikariPool-1 - Shutdown completed.
までは出力されています。
Executable Jar を直接起動している時はきちんと落ちるようですが、IntelliJ IDEA や Windows のサービスから起動している時は落ちたことが起動元のプロセスに伝わらない、ということでしょうか?
Thread Dump Endpoint からスレッドダンプを出力してみる
application.properties に設定を追加して Thread Dump endpoint を有効にします。
management.endpoints.web.exposure.include=health,info,loggers,shutdown,threaddump management.endpoint.shutdown.enabled=true
IntelliJ IDEA から Tomcat を起動後、curl 'http://localhost:8080/actuator/threaddump' -i -X POST
コマンドを実行します。
なんかこれじゃない感が。。。 スレッドダンプと言えばテキスト形式のものだと思っていたので、JSON ではなくテキストのものを返して欲しいのですが、テキストで返す方法は見当たりませんでした。
もしかして最近はスレッドダンプは JSON 形式が常識なのか?と思って調べてみましたが、それらしい記事も見当たらず。その代わり以下の記事を見つけました。IBM Thread and Monitor Dump Analyzer for Java というツールが便利そうです。
- CloudFoundry: Java thread and heap dump analysis on remote containers
- IBM Thread and Monitor Dump Analyzer for Java
試しに Java VisualVM からスレッドダンプを出力してテキストファイルに保存した後、
java -Xmx512m -jar jca457.jar
コマンドで IBM Thread and Monitor Dump Analyzer for Java を起動して保存したスレッドダンプを読み込ませると以下のような感じで表示されます。
2つのタイミングの異なるスレッドダンプを読み込ませて比較表示することも出来るようです。
このツール、全然噂を聞いたことがありませんでした。そんなに有名なツールではないのかな?
/actuator/**
に IPアドレスでアクセス制限をかけるには?
src/main/java/ksbysample/webapp/bootnpmgeb/config/WebSecurityConfig.java に以下のように定義します。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // アクセス元のホストIPアドレスで指定する場合 .antMatchers(ACTUATOR_ANT_PATTERN).hasIpAddress("127.0.0.1") .antMatchers(ACTUATOR_ANT_PATTERN).hasIpAddress("192.168.56.1") // アクセス元のネットワークIPアドレスで指定する場合 .antMatchers(ACTUATOR_ANT_PATTERN).hasIpAddress("192.168.56.0/24") // アクセス元を複数指定する場合 .antMatchers(ACTUATOR_ANT_PATTERN) .access("hasIpAddress('127.0.0.1') or hasIpAddress('192.168.56.0/24')") ..........
最後に
Health , Loggers, Mappings 等の Endpoint も面白いのですが、Actuator で一番面白そうなのは Prometheus Endpoint を利用して Prometheus と連携してモニタリングすることですよね。他の人が書いたものを見る限りでは簡単に出来るようです。
Spring Boot ってどんどん便利になっていますが、覚えることが多くて大変です。。。 いや、本当に。
Spring Boot Actuator の導入まで終わりましたが、あと以下の点を記述して終わりにする予定です。
- Spring Session が生成している SESSION Cookie の domain 属性や httponly 属性の値を変更する方法の調査
- gradle-processes の Gradle 4.6 以降対応版が出ているようなので正式に導入する
- PMD を 6.6.0 にバージョンアップすると build タスク実行時のメッセージが減るような記述を見かけたので、その検証
履歴
2018/08/09
初版発行。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その75 )( コネクションプーリング用ライブラリを Tomcat connection pool → HikariCP に切り替える )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その74 )( FindBugs 3.0.1 → SpotBugs 3.1.3 に切り替える ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Spring Boot 2 からデフォルトのコネクションプーリング用ライブラリが Tomcat connection pool → HikariCP に変わりましたので、HikariCP に変更します。
参照したサイト・書籍
brettwooldridge/HikariCP
https://github.com/brettwooldridge/HikariCPSpring Boot + HikariCPでコネクションプールのMetricsを取得する
https://matsumana.info/blog/2016/02/06/spring-boot-hikaricp-metrics/Spring Boot 2.0でのHikariCPに関する変更
https://matsumana.info/blog/2017/07/04/spring-boot2-hikaricp/Unable to register MBean [HikariDataSource (HikariPool-0)] with key 'dataSource'
https://stackoverflow.com/questions/27440985/unable-to-register-mbean-hikaridatasource-hikaripool-0-with-key-datasourceSQL logging
https://github.com/brettwooldridge/HikariCP/issues/57
目次
- build.gradle を変更する
- application.properties を変更する
- logback-spring.xml を変更する
- dataSource Bean の実装を変更する
- clean タスク → Rebuild Project → build タスクを実行する
- JMX への登録状況を確認する
- Executable Jar ファイルから起動してみる
手順
build.gradle を変更する
build.gradle の dependencies block から implementation("org.apache.tomcat:tomcat-jdbc")
の行を削除します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
application.properties を変更する
Configuration を読んだのですが、おそらく HikariCP はデフォルトの設定で十分で個別に設定する必要がないと思います。よって jdbc-url, username, password, driver-class-name と気になった leak-detection-threshold だけ設定します(leak-detection-threshold もその心配がなければ削除して構わないと思います)。
また JMX への登録は Tomcat connection pool の時は spring.datasource.jmx-enabled=true
の設定で行いましたが、HikariCP では spring.datasource.hikari.register-mbeans=true
の設定で行います。
src/main/resources/application.properties を以下のように変更します。
doma.dialect=org.seasar.doma.jdbc.dialect.H2Dialect spring.datasource.hikari.jdbc-url=jdbc:h2:mem:bootnpmgebdb spring.datasource.hikari.username=sa spring.datasource.hikari.password= spring.datasource.hikari.driver-class-name=org.h2.Driver spring.datasource.hikari.leak-detection-threshold=5000 spring.datasource.hikari.register-mbeans=true spring.session.store-type=jdbc ..........
また src/main/resources/application-product.properties から以下の5行の設定を削除します。
slowquery.logging.file=${server.tomcat.basedir}/logs/slow-query.log
spring.datasource.tomcat.initialSize=2
spring.datasource.tomcat.maxActive=2
spring.datasource.tomcat.maxIdle=2
spring.datasource.tomcat.minIdle=2
logback-spring.xml を変更する
Tomcat connection pool の SlowQueryReport interceptor がなくなりましたので、<if condition='"${spring.profiles.active}" == "product" && "${slowquery.logging.file}" != ""'> ... </if>
の設定を削除します。
dataSource Bean の実装を変更する
src/main/java/ksbysample/webapp/bootnpmgeb/config/ApplicationConfig.java の以下の点を変更します。
@Configuration @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) public class ApplicationConfig { .......... /** * @return HikariCP の DataSource オブジェクト */ @Bean @ConfigurationProperties("spring.datasource.hikari") public DataSource dataSource() { return DataSourceBuilder.create() .type(HikariDataSource.class) .build(); } }
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
を追加します。@ConfigurationProperties("spring.datasource.tomcat")
→@ConfigurationProperties("spring.datasource.hikari")
に変更します。.type(org.apache.tomcat.jdbc.pool.DataSource.class)
→.type(HikariDataSource.class)
に変更します。
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
を付けていないと Executable Jar から起動しようとした時に以下の例外が発生して起動しません(IntelliJ IDEA の時は起動します)。
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [HikariDataSource (HikariPool-1)] with key 'dataSource'; nested exception is javax.management.InstanceAlreadyExistsException: MXBean already registered with name com.zaxxer.hikari:type=PoolConfig (HikariPool-1) at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:625) at org.springframework.jmx.export.MBeanExporter.lambda$registerBeans$2(MBeanExporter.java:551) at java.util.HashMap.forEach(HashMap.java:1289) at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:551) at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:434) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398) at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) at ksbysample.webapp.bootnpmgeb.Application.main(Application.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) Caused by: javax.management.InstanceAlreadyExistsException: MXBean already registered with name com.zaxxer.hikari:type=PoolConfig (HikariPool-1) at com.sun.jmx.mbeanserver.MXBeanLookup.addReference(MXBeanLookup.java:151) at com.sun.jmx.mbeanserver.MXBeanSupport.register(MXBeanSupport.java:160) at com.sun.jmx.mbeanserver.MBeanSupport.preRegister2(MBeanSupport.java:173) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:930) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324) at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:137) at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:671) at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:615) ... 22 common frames omitted
clean タスク → Rebuild Project → build タスクを実行する
clean タスク → Rebuild Project → build タスクを実行すると BUILD SUCCESSFUL が出力されました。問題ないようです。
JMX への登録状況を確認する
IntelliJ IDEA から Tomcat を起動した後、コマンドプロンプトから jconsole コマンドを実行します。
「JConsole: 新規接続」ダイアログが表示されますので、「ローカル・プロセス」の一覧から ksbysample.webapp.bootnpmgeb.Application を選択した後「接続」ボタンをクリックします。
JConsole の画面が表示されますので「MBeans」タグをクリックします。画面左側のツリーに「com.zaxxer.hikari」という項目で登録されていることが確認できます。
Executable Jar ファイルから起動してみる
生成された build/libs/boot-npm-geb-sample-1.0.2-RELEASE.jar を C:\webapps\boot-npm-geb-sample\lib の下にコピーした後、C:\webapps\boot-npm-geb-sample\bat\webapp_startup.bat をコマンドプロンプトから起動します。
入力画面1~3で入力して確認画面→送信画面まで進めても特にエラーは発生しませんでした。ただし、今回ログを見ていて気づきましたが、Spring Session が生成している SESSION Cookie の domain 属性が null? とか、httponly 属性が false?とかなんかいろいろ問題がありそうです。。。 次回以降で調査してみます。
[req][cookie] name = SESSION, value = MThlNDQ3NGUtNmQ0Mi00Y2Q2LTlmNTYtMDA4ZDZlYjg3NTQ3, domain = null, path = null, maxage = -1, secure = false, httponly = false
JMX の登録状況も確認します。コマンドプロンプトから jconsole コマンドを実行した後、「JConsole: 新規接続」ダイアログの「ローカル・プロセス」の一覧から boot-npm-geb-sample-1.0.2-RELEASE.jar を選択して「接続」ボタンをクリックします。
IntelliJ IDEA から起動した時と同様に「MBeans」タグの画面左側のツリーに「com.zaxxer.hikari」という項目で登録されていることが確認できます。
履歴
2018/08/05
初版発行。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その74 )( FindBugs 3.0.1 → SpotBugs 3.1.3 に切り替える )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( 番外編 )( IntelliJ IDEA に Rainbow Brackets をインストールする ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
参照したサイト・書籍
spotbugs/spotbugs
https://github.com/spotbugs/spotbugsSpotBugs マニュアル
http://spotbugs.readthedocs.io/ja/latest/index.htmlFindBugs 3.0 から SpotBugs 3.1 への移行ガイド
http://spotbugs.readthedocs.io/ja/latest/migration.htmlフィルタファイル
https://spotbugs.readthedocs.io/ja/latest/filter.html?highlight=excludeFilter@Nullable input in Google Guava Function interface triggers FindBugs warning
https://stackoverflow.com/questions/12422473/nullable-input-in-google-guava-function-interface-triggers-findbugs-warning
目次
- build.gradle を変更する
- config/findbugs/findbugs-exclude.xml → config/spotbugs/spotbugs-exclude-filter.xml に変更する
- clean タスク → Rebuild Project → build タスクを実行する
- 出力された警告を解消する
- 再び clean タスク → Rebuild Project → build タスクを実行する
- IntelliJ IDEA から FindBugs-IDEA Plugin をアンインストールする
手順
build.gradle を変更する
FindBugs 3.0 から SpotBugs 3.1 への移行ガイド を参考に build.gradle の以下の点を変更します。
plugins { .......... id "checkstyle" id "com.github.spotbugs" version "1.6.2" id "pmd" .......... } .......... spotbugs { toolVersion = '3.1.3' ignoreFailures = true effort = "max" excludeFilter = file("${rootProject.projectDir}/config/spotbugs/spotbugs-exclude-filter.xml") spotbugsTest.enabled = false } tasks.withType(com.github.spotbugs.SpotBugsTask) { reports { xml.enabled = false html.enabled = true } } .......... dependencies { def spockVersion = "1.1-groovy-2.4" def domaVersion = "2.19.2" def lombokVersion = "1.18.0" def errorproneVersion = "2.3.1" def powermockVersion = "2.0.0-beta.5" def seleniumVersion = "3.13.0" def spotbugsVersion = "3.1.3" .......... // for SpotBugs compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}") compileOnly("net.jcip:jcip-annotations:1.0") compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}") testImplementation("com.google.code.findbugs:jsr305:3.0.2") }
- plugins block の以下の点を変更します。
id "findbugs"
→id "com.github.spotbugs" version "1.6.2"
に変更します。
- タスク名を
findbugs
→spotbugs
に変更し、以下の点を変更します。toolVersion = '3.0.1'
→toolVersion = '3.1.3'
に変更します。excludeFilter = file("${rootProject.projectDir}/config/findbugs/findbugs-exclude.xml")
→excludeFilter = file("${rootProject.projectDir}/config/spotbugs/spotbugs-exclude-filter.xml")
に変更します。
tasks.withType(FindBugs)
→tasks.withType(com.github.spotbugs.SpotBugsTask)
に変更します。- dependencies block の以下の点を変更します。
- 以下の4行を追加します。
def spotbugsVersion = "3.1.3"
compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}")
compileOnly("net.jcip:jcip-annotations:1.0")
compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}")
- 以下の1行を SpotBugs のライブラリの記述の下に移動します。
testImplementation("com.google.code.findbugs:jsr305:3.0.2")
- 以下の4行を追加します。
変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
config/findbugs/findbugs-exclude.xml → config/spotbugs/spotbugs-exclude-filter.xml に変更する
config/findbugs/findbugs-exclude.xml → config/spotbugs/spotbugs-exclude-filter.xml にフォルダ名、ファイル名を変更します。また フィルタファイル を参考にファイルの内容の以下の点を変更します。
<?xml version="1.0" encoding="UTF-8"?> <FindBugsFilter xmlns="https://github.com/spotbugs/filter/3.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd"> <Match> <Class name="ksbysample.webapp.lending.web.lendingapp.LendingappService"/> <Bug pattern="DLS_DEAD_LOCAL_STORE"/> </Match> </FindBugsFilter>
<FindBugsFilter>
→<FindBugsFilter xmlns="https://github.com/spotbugs/filter/3.0.0" ...>
に変更します。
clean タスク → Rebuild Project → build タスクを実行する
clean タスク → Rebuild Project → build タスクを実行してみると BUILD SUCCESSFUL の文字が出力されました。ただし SpotBugs rule violations were found.
のメッセージが出るのは FindBugs の時と変わりませんでした。
レポートファイルは build/reports/spotbugs/main.html に作成されており、開いてみると FindBugs の時と同じく警告が5件出ています。
出力された警告を解消する
null になっている可能性があるメソッドの戻り値を利用しています。(Bug type NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE )
警告が出ている原因の箇所は src/main/java/ksbysample/webapp/bootnpmgeb/aspect/logging/RequestAndResponseLogger.java の以下の画像の赤線で囲んだところでした。RequestContextHolder.getRequestAttributes()
と .getResponse()
の戻り値が null の可能性があるので警告が出ています。
Optional を使って以下のように変更します。
target は,非 null でなければならないが null 可能としてマークされています。(Bug type NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE)
警告が出ている原因の箇所は src/main/java/ksbysample/webapp/bootnpmgeb/web/inquiry/form/InquiryInput02FormValidator.java の以下の画像の赤線で囲んだところでした。
これは validate メソッドの引数を Object target
→ @Nonnull Object target
に変更します。
再び clean タスク → Rebuild Project → build タスクを実行する
再び clean タスク → Rebuild Project → build タスクを実行すると、今度は SpotBugs の警告は出ずに BUILD SUCCESSFUL が出力されました。
修正した内容は Spring Boot 2系とは関係ないように思えるのですが、なぜバージョンアップしたら警告が出るようになったのかが分からないですね。。。
IntelliJ IDEA から FindBugs-IDEA Plugin をアンインストールする
FindBugs を使用しなくなったので FindBugs-IDEA Plugin をアンインストールします。
履歴
2018/08/04
初版発行。
2018/08/29
SpotBugs が正常に動作していなかったので build.gradle の spotbugs タスクの以下の点を修正した。
* sourceSets = [project.sourceSets.main] を削除した
* spotbugsTest.enabled = false を追加した
Java SE を 8u172 → 8u181 へバージョンアップ
※ksbysample-webapp-lending プロジェクトを開いた状態でバージョンアップしています。
Java SE を 8u172 → 8u181 へバージョンアップする
Oracle の Java SE Downloads を見ると 8u181 がダウンロードできるようになっていましたので、8u181 へバージョンアップします。
jdk-8u181-windows-x64.exe をダウンロードして C:\Java\jdk1.8.0_181 へインストールした後、環境変数 JAVA_HOME のパスを C:\Java\jdk1.8.0_181 へ変更します。
コマンドプロンプトから
java -version
を実行し、1.8.0_181
に変更されていることを確認します。開いているプロジェクトを閉じて「Welcome to IntelliJ IDEA」ダイアログを表示します。
ダイアログ下部の「Configure」-「Project Defaults」-「Project Structure」を選択します。メニューが増えていますね。。。
「Default Project Structure」ダイアログが表示されます。画面左側で「Project Settings」-「Project」を選択後、画面右側の「Project SDK」の「New...」ボタンをクリックし、表示されるメニューから「JDK」を選択します。
「Select Home Directory for JDK」ダイアログが表示されます。C:\Java\jdk1.8.0_181 を選択した後、「OK」ボタンをクリックします。
「Default Project Structure」ダイアログに戻るので、今度は「Project SDK」の「Edit」ボタンをクリックします。
画面左側で「Platform Settings」-「SDKs」が選択された状態になるので、画面右上の入力フィールドで "1.8" → "1.8.0_181" へ変更します。
次に中央のリストから「1.8.0_172」を選択した後、リストの上の「-」ボタンをクリックして削除します。
「OK」ボタンをクリックして「Default Project Structure」ダイアログを閉じます。
「Welcome to IntelliJ IDEA」ダイアログに戻ったら、ksbysample-webapp-lending プロジェクトを開きます。
IntelliJ IDEA のメイン画面が開いたら、メニューから「File」-「Project Structure...」を選択します。
「Project Structure」ダイアログが表示されます。以下の画像の状態になっているので、
「Project SDK」と「Project language level」を選択し直します。
「OK」ボタンをクリックして「Project Structure」ダイアログを閉じます。
メイン画面に戻ると画面右下に「Indexing...」の表示が出るので、終了するまで待ちます。
clean タスク実行 → Rebuild Project 実行 → build タスクを実行して、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。
Project Tool Window で src/test を選択した後、コンテキストメニューを表示して「Run ‘All Tests’ with Coverage」を選択し、テストが全て成功することを確認します。
特に問題は発生しませんでした。8u181 で開発を進めます。