かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 2.1.x の Web アプリを 2.2.x へバージョンアップする ( その9 )( SpotBugs を 3.1.11 → 4.0.0-beta4 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.1.x の Web アプリを 2.2.x へバージョンアップする ( その8 )( Error Prone を 2.3.3 → 2.3.4 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • SpotBugs を 3.1.11 → 4.0.0-beta4 へバージョンアップします。
    • https://mvnrepository.com/artifact/com.github.spotbugs/spotbugs を見ると安定版?(beta が付いていないもの)の最新版が 3.1.12(Mar, 2019)、その後 4.0.0 が beta で開発が進んでいて最新版が 4.0.0-beta4(Sep, 2019)でした。今回は 4.0.0-beta4 にバージョンアップします。

参照したサイト・書籍

  1. default.xsl declares it is a 2.0 stylesheet, but it appears to have issues with a 2.0 processor
    https://github.com/spotbugs/spotbugs/issues/958

目次

  1. build.gradle を変更する
  2. 警告の原因を取り除く(かもしれない)
    1. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    2. Warning at xsl:variable on line 348 column 57 of default.xsl: SXWN9001: A variable with no following sibling instructions has no effect
  3. 各スタイルシートの HTML のレポートファイルのサンプルを作成してみる
    1. color.xsl
    2. fancy.xsl
    3. fancy-hist.xsl
    4. plain.xsl
    5. summary.xsl

手順

build.gradle を変更する

コメントアウトしていた SpotBugs の設定を元に戻した後、以下の点を変更します。

plugins {
    ..........
    id "com.github.spotbugs" version "3.0.0"
    ..........
}

..........

spotbugs {
    toolVersion = "4.0.0-beta4"
    ignoreFailures = true
    effort = "max"
    spotbugsTest.enabled = false
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
    reports {
        xml.enabled = false
        html.enabled = true
    }
}

..........

dependencies {
    ..........
    def spotbugsVersion = "4.0.0-beta4"
  • plugins block の以下の点を変更します。
    • id "com.github.spotbugs" version "1.6.9"id "com.github.spotbugs" version "3.0.0"
  • spotbugs block の以下の点を変更します。
    • toolVersion = "3.1.11"toolVersion = "4.0.0-beta4"
  • dependencies block の以下の点を変更します。
    • def spotbugsVersion = "3.1.11"def spotbugsVersion = "4.0.0-beta4"

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージは出力されますが2種類の警告も出力されました。

f:id:ksby:20200102164715p:plain

> Task :spotbugsMain
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Warning at xsl:variable on line 348 column 57 of default.xsl:
  SXWN9001: A variable with no following sibling instructions has no effect
Warning at xsl:variable on line 351 column 57 of default.xsl:
  SXWN9001: A variable with no following sibling instructions has no effect

警告の原因を取り除く(かもしれない)

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".

ログに出力されている http://www.slf4j.org/codes.html#StaticLoggerBinder を見ると slf4j-nop.jar slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar or logback-classic.jar のいずれかの jar ファイルが classpath に含まれていればこのメッセージは出力されなくなると書かれています。

が、build.gradle の dependencies block に以下のいずれかを追加しても SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". のメッセージは消えず、testJUnit4AndSpock タスクまで java.lang.IllegalArgumentException が発生してテストが多数失敗しました。compileOnly → implementation に変更しても結果は同じでした。

  • compileOnly("org.slf4j:slf4j-nop")
  • compileOnly("org.slf4j:slf4j-simple")
  • compileOnly("org.slf4j:slf4j-log4j12")
  • compileOnly("org.slf4j:slf4j-jdk14")
  • compileOnly("ch.qos.logback:logback-classic")

f:id:ksby:20200102190137p:plain

分からない。。。と思って Web で検索したところ、spotbugs/spotbugs-gradle-plugin の Issue に SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" があり、まだ Open の状態でした。

動作には支障がないようなので、このメッセージは出したままにします。

Warning at xsl:variable on line 348 column 57 of default.xsl: SXWN9001: A variable with no following sibling instructions has no effect

default.xsl declares it is a 2.0 stylesheet, but it appears to have issues with a 2.0 processor に対応方法のサンプルが書かれているので、これを参考に変更します。

build.gradle を以下のように変更して、SpotBugs の HTML のレポートファイルが使用するスタイルシートを default.xsl → color.xsl に変更します。

configurations {
    ..........

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}

..........

spotbugs {
    toolVersion = "4.0.0-beta4"
    ignoreFailures = true
    effort = "max"
    spotbugsTest.enabled = false
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
    reports {
        xml.enabled = false
        html.enabled = true
        html.stylesheet = resources.text.fromArchiveEntry(configurations.spotbugsStylesheets, "color.xsl")
    }
}

..........

dependencies {
    ..........

    // 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")
    spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}")
}
  • configurations block の以下の点を変更します。
    • spotbugsStylesheets { transitive = false } を追加します。
  • tasks.withType(com.github.spotbugs.SpotBugsTask) { ... } の以下の点を変更します。
    • html.stylesheet = resources.text.fromArchiveEntry(configurations.spotbugsStylesheets, "color.xsl") を追加します。
  • dependencies block の以下の点を変更します。
    • spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}") を追加します。

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると メッセージは消えて "BUILD SUCCESSFUL" のメッセージも出力されました。

f:id:ksby:20200104111318p:plain

com.github.spotbugs:spotbugs:4.0.0-beta4 の中を見ると、スタイルシートは default.xsl 以外に以下のものがあります。

f:id:ksby:20200104110138p:plain

スタイルシートでどのようなレポートファイルが出力されるのかサンプルを作成してみます。SpotBugs の 検知可能なバグの詳細 を見て SpotBugs に検知されるバグを含んだソースを作成します。

src/main/java/ksbysample/webapp/lending/BugSample.java を新規作成し、以下の内容を記述します。NP: 戻り型が Boolean のメソッドが明示的に null を返している (NP_BOOLEAN_RETURN_NULL) の bug を含んだサンプルです。

package ksbysample.webapp.lending;

public class BugSample {

    public Boolean func() {
        return null;
    }

}

スタイルシートの HTML のレポートファイルのサンプルを作成してみる

作成してみた感想としては、bug の数が少ないならば1ページにすべて表示できる color.xsl が使い勝手が良さそうで、数が出そうなら fancy.xsl、fancy-hist.xsl の方が便利でしょうか? summary.xsl は普段は使用しない気がします。

個人的には color.xsl が好みですね。

color.xsl

f:id:ksby:20200104115941p:plain f:id:ksby:20200104120231p:plain

fancy.xsl

f:id:ksby:20200104120605p:plain f:id:ksby:20200104120704p:plain

fancy-hist.xsl

f:id:ksby:20200104121811p:plain f:id:ksby:20200104122142p:plain

plain.xsl

plain.xsl は以下のエラーが出て使えませんでした。

Warning at xsl:variable on line 277 column 56 of plain.xsl:
  SXWN9001: A variable with no following sibling instructions has no effect
Warning at xsl:variable on line 280 column 59 of plain.xsl:
  SXWN9001: A variable with no following sibling instructions has no effect
Error evaluating ((<head {(<title {text{"SpotBugs Report"}}/>, ...)}/>, ...)) on line 44 column 8 of plain.xsl:
  SEPM0009: Values of 'standalone' and 'omit-xml-declaration' conflict
  In template rule with match="/" on line 42 of plain.xsl
The following errors occurred during analysis:
  Could not generate HTML output
    net.sf.saxon.trans.XPathException: Values of 'standalone' and 'omit-xml-declaration' conflict
      At net.sf.saxon.serialize.XMLEmitter.writeDeclaration(XMLEmitter.java:271)
      At net.sf.saxon.serialize.XMLEmitter.openDocument(XMLEmitter.java:188)
      At net.sf.saxon.serialize.XMLEmitter.characters(XMLEmitter.java:644)
      At net.sf.saxon.serialize.XMLIndenter.indent(XMLIndenter.java:327)
      At net.sf.saxon.serialize.XMLIndenter.startElement(XMLIndenter.java:115)
      At net.sf.saxon.event.ProxyReceiver.startElement(ProxyReceiver.java:132)
      At net.sf.saxon.event.SequenceNormalizer.startElement(SequenceNormalizer.java:88)
      At net.sf.saxon.event.NamespaceReducer.startElement(NamespaceReducer.java:75)
      At net.sf.saxon.event.ComplexContentOutputter.startContent(ComplexContentOutputter.java:640)
      At net.sf.saxon.event.ComplexContentOutputter.startElement(ComplexContentOutputter.java:271)
      At net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:345)
      At net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:299)
      At net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:735)
      At net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:132)
      At net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:352)
      At net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:299)
      At net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:352)
      At net.sf.saxon.trans.Mode.applyTemplates(Mode.java:532)
      At net.sf.saxon.trans.XsltController.applyTemplates(XsltController.java:747)
      At net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(AbstractXsltTransformer.java:347)
      At net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:349)
      At net.sf.saxon.jaxp.TransformerImpl.transform(TransformerImpl.java:71)
      At edu.umd.cs.findbugs.HTMLBugReporter.finish(HTMLBugReporter.java:73)
      At edu.umd.cs.findbugs.DelegatingBugReporter.finish(DelegatingBugReporter.java:89)
      At edu.umd.cs.findbugs.DelegatingBugReporter.finish(DelegatingBugReporter.java:89)
      At edu.umd.cs.findbugs.FindBugs2.analyzeApplication(FindBugs2.java:1165)
      At edu.umd.cs.findbugs.FindBugs2.execute(FindBugs2.java:309)
      At com.github.spotbugs.internal.spotbugs.SpotBugsExecutor.runSpotbugs(SpotBugsExecutor.java:23)
      At java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      At java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      At java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      At java.base/java.lang.reflect.Method.invoke(Method.java:566)
      At org.gradle.process.internal.worker.request.WorkerAction$1.call(WorkerAction.java:129)
      At org.gradle.process.internal.worker.child.WorkerLogEventListener.withWorkerLoggingProtocol(WorkerLogEventListener.java:41)
      At org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:126)
      At org.gradle.process.internal.worker.request.WorkerAction.runThenStop(WorkerAction.java:105)
      At java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      At java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      At java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      At java.base/java.lang.reflect.Method.invoke(Method.java:566)
      At org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
      At org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
      At org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
      At org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
      At org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
      At org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
      At org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
      At java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
      At java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
      At org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
      At java.base/java.lang.Thread.run(Thread.java:834)

summary.xsl

f:id:ksby:20200104123203p:plain

このレポートは「Bugs By Package」の下にパッケージ毎の結果が出力されるので、かなり長いです。

履歴

2020/01/04
初版発行。