エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

NullAwayをGradleプロジェクトに導入してみた

きっかけ

JJUG CCC Spring 2024で見かけたライブラリで、有用そうだったので導入してみたくなった。

suzaku-tec.hatenadiary.jp

関連する各種リンク

GitHub - uber/NullAway: A tool to help eliminate NullPointerExceptions (NPEs) in your Java code with low build-time overhead

https://mvnrepository.com/artifact/com.google.errorprone/error_prone_core

環境情報

gradle利用を前提としてます。mavenは、きっかけとなった @making さんのgithubリポジトリを参照してなんとかしてください。※他人に任せられるところは任せるスタイル
とりあえず、導入するだけで、コンパイルエラーにするとかはしない。
あと、警告内容も、今回、調査しない。
あくまで動かすところまで。
最初から全部やろうとすると、ブログがかけないからな。。。

開発環境

IntelliJ IDEA 2024.1.3 (Community Edition) Build #IC-241.17890.1, built on June 4, 2024 Runtime version: 17.0.11+1-b1207.24 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Windows 11.0 GC: G1 Young Generation, G1 Old Generation Memory: 2048M Cores: 32

導入プロジェクト情報

  • spring Version:"3.2.4"
  • Java Version: "17"
  • Gradle Version: "8.4"

導入方法

公式サイトを見ると、導入には前提条件があるらしい。

  • バージョン2.14.0以上のError Proneでコードをビルドする必要がある
  • Androidは想定してない
  • Java9以降が安心(8もサポートしているはずだが、安定してない)

設定内容

基本的には、build.gradleイジるだけでなんとかなる。
修正した箇所は、下記の通り※修正箇所のみ抜粋
まぁ、公式サイトに書かれていることに自分の環境向けに追記したくらいだが。。。

plugins {
  // we assume you are already using the Java plugin
  id "net.ltgt.errorprone" version "4.0.0"
}

allprojects {
    ext {
        nullAwayVersion = "0.11.0"
        errorProneVersion = "2.28.0"
    }
}

dependencies {
    errorprone "com.uber.nullaway:nullaway:$nullAwayVersion"

    // Optional, some source of nullability annotations.
    // Not required on Android if you use the support
    // library nullability annotations.
    compileOnly "com.google.code.findbugs:jsr305:3.0.2"

    errorprone "com.google.errorprone:error_prone_core:$errorProneVersion"
}

import net.ltgt.gradle.errorprone.CheckSeverity

tasks.withType(JavaCompile) {
  // remove the if condition if you want to run NullAway on test code
  if (!name.toLowerCase().contains("test")) {
    options.errorprone {
      check("NullAway", CheckSeverity.ERROR)
      option("NullAway:AnnotatedPackages", "com.uber")
    }
  }
}

苦労したこと

Could not get unknown property 'errorProneVersion' for object of type

Could not get unknown property 'errorProneVersion' for object of type org.gradle.plugin.use.internal.PluginRequestCollector$PluginDependenciesSpecImpl.

意訳:プラグインが見つかりませーん

原因と対策

おそらく、バージョン指定をしていなかったのが原因。
id "net.ltgt.errorprone" version "4.0.0" と記述してリフレッシュしたら、プラグインのダウンロードっぽいのが走った。

ErrorProneInjector$ProvisionException

Caused by: com.google.errorprone.scanner.ErrorProneInjector$ProvisionException: Failed to initialize com.uber.nullaway.NullAway

意訳:初期化に失敗だバカヤロー

原因と対策

公式サイトに書かれてた、下記のコンパイル時のタスクが抜けていたからだと思われる。
追記したら動いた。

import net.ltgt.gradle.errorprone.CheckSeverity

tasks.withType(JavaCompile) {
    // remove the if condition if you want to run NullAway on test code
    if (!name.toLowerCase().contains("test")) {
        options.errorprone {
            check("NullAway", CheckSeverity.ERROR)
            option("NullAway:AnnotatedPackages", "com.uber")
        }
    }
}

動かしてみると

導入したwebアプリのプロジェクトを動かしてみると、下記の感じだった。

実行結果

とりあえず、なんか警告出てくる。
一番上で言われているのは、たぶん、@Autowiredをフィールドインジェクションでやっているからだと思う。
コンストラクタから入れれば、たぶん問題ないんじゃないかと思われる。

再ビルドすると警告されるんだけど、そういうもん?
gradleの知識が足りないせいか、どういうきっかけでチェックが走ってるのか、よう分からん。。。
gradleの内容を正しく理解して、想定したタイミングで処理ができるようにさせるのは、今後の課題だな。

感想

思ったより簡単に導入できた。
gradleの知識が足りてないなと感じた。
公式サイトに言われるがまま記載したら、プラグインがないだの初期化がおかしいだのいわれて、悩んでしまった。

指摘はいくつかあるけど、対応しきれないほどではないな。
ある程度、nullを考慮した実装ができていると思いたい。

とりあえず導入して動かしてみて、あまりにも指摘内容の精度が悪いのなら、外そうと思う。