LoginSignup
2
1

More than 3 years have passed since last update.

Gradleの依存関係解決がSpringBootプラグインのせいでなんだかいうことを聞いてくれない時の一例

Last updated at Posted at 2019-12-12

概要

このエントリでは、Gradleを使っているときに、依存性解決がなんだかうまくいかない時の一例、について紹介します。

Enterprise電卓を作る Advent Calendar 2019の12/3のエントリです。

想定読者

  • Gradleを使っていて、SpringBootを使っているときに、依存性解決において、サードパーティーのライブラリがなんだか古いバージョンが使用されるんだが、という経験がある方。

  • JLine3をSpringBootで使うとき、WindowsプラットフォームでJNAで起動しようとしているときに困っている方。

事象

ログ

Javaでコンソールでのキー入力を1文字ずつハンドルしたいときにJLineを使うのエントリを書いていた際、下記のようなエラーが出ました。こういった事象に対応するための手段の一つを紹介します。

JNA_error.png

このログを見るに、

        Suppressed: java.lang.NoSuchMethodError: com.sun.jna.Native.load(Ljava/lang/String;Ljava/lang/Class;Ljava/util/Map;)Lcom/sun/jna/Library;

ということで、利用しているライブラリの中で、特定のクラスにメソッドがないんだけど、という風に読めます。

Gradleを使って依存性解決をお任せしているのになんじゃこれ、ということになりますが、そういうことになっているので仕方がありません。

確認

Gradleで、プロジェクトが利用しているライブラリの確認コマンドは、下記です。

gradle dependencies 

例えば、下図のようなシンプルなbuild.gradleを用意して、


plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation group: 'org.jline', name: 'jline', version: '3.12.1'
    implementation group: 'org.jline', name: 'jline-terminal-jna', version: '3.12.1'
}

実行すると、下図のようなツリーが表示されます。それぞれのタスクにおいて使用されるライブラリがわかります。


> Task :dependencies

------------------------------------------------------------
Root project
------------------------------------------------------------

annotationProcessor - Annotation processors and their dependencies for source set 'main'.
No dependencies

apiElements - API elements for main. (n)
No dependencies

archives - Configuration for archive artifacts.
No dependencies

compile - Dependencies for source set 'main' (deprecated, use 'implementation' instead).
No dependencies

compileClasspath - Compile classpath for source set 'main'.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1
     \--- org.jline:jline-terminal:3.12.1

compileOnly - Compile only dependencies for source set 'main'.
No dependencies

default - Configuration for default artifacts.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1
     \--- org.jline:jline-terminal:3.12.1

implementation - Implementation only dependencies for source set 'main'. (n)
+--- org.jline:jline:3.12.1 (n)
\--- org.jline:jline-terminal-jna:3.12.1 (n)

runtime - Runtime dependencies for source set 'main' (deprecated, use 'runtimeOnly' instead).
No dependencies

runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1
     \--- org.jline:jline-terminal:3.12.1

runtimeElements - Elements of runtime for main. (n)
No dependencies

runtimeOnly - Runtime only dependencies for source set 'main'. (n)
No dependencies

testAnnotationProcessor - Annotation processors and their dependencies for source set 'test'.
No dependencies

testCompile - Dependencies for source set 'test' (deprecated, use 'testImplementation' instead).
No dependencies

testCompileClasspath - Compile classpath for source set 'test'.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1
     \--- org.jline:jline-terminal:3.12.1

testCompileOnly - Compile only dependencies for source set 'test'.
No dependencies

testImplementation - Implementation only dependencies for source set 'test'. (n)
No dependencies

testRuntime - Runtime dependencies for source set 'test' (deprecated, use 'testRuntimeOnly' instead).
No dependencies

testRuntimeClasspath - Runtime classpath of source set 'test'.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1
     \--- org.jline:jline-terminal:3.12.1

testRuntimeOnly - Runtime only dependencies for source set 'test'. (n)
No dependencies

(n) - Not resolved (configuration is not meant to be resolved)

A web-based, searchable dependency report is available by adding the --scan option.

BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed

これを見ると、org.jline:jline-terminal-jna:3.12.1がnet.java.dev.jna:jna:5.3.1に依存しているので、それをGradleが使えるようにしてくれることを示します。

目の前の事象

さて、ここでプラグインを2つ追加してみます。SpringInitializrでSpringBootのプロジェクトを作った時に追加されているものです。
build.gradleの全体は下図のようになります。


plugins {
    id 'org.springframework.boot' version '2.2.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation group: 'org.jline', name: 'jline', version: '3.12.1'
    implementation group: 'org.jline', name: 'jline-terminal-jna', version: '3.12.1'
}

依存関係を確認してみましょう。

default - Configuration for default artifacts.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1 -> 4.5.2
     \--- org.jline:jline-terminal:3.12.1


runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.jline:jline:3.12.1
\--- org.jline:jline-terminal-jna:3.12.1
     +--- net.java.dev.jna:jna:5.3.1 -> 4.5.2
     \--- org.jline:jline-terminal:3.12.1

あれ、、、net.java.dev.jna:jna:5.3.1 -> 4.5.2となり、古いバージョンのものを参照してしまっています。

この状況はプラグインの動作のためらしく、Gradleのコミュニティサイトでもやり取りがありました。以下引用。

However, as you already suspected, Spring Gradle plugins do configure the dependency resolution by providing their own dependency management plugin:
https://github.com/spring-gradle-plugins/dependency-management-plugin 84.
Using the spring boot plugin, you need to use that, but you can reconfigure dependencies there

暫定対策

将来はこのあたりもうまくいってくれることを願いつつ、暫定対策で自分でdependencyを一つ追加します。build.gradleは下図のようになります。

plugins {
    id 'org.springframework.boot' version '2.2.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation group: 'org.jline', name: 'jline', version: '3.12.1'
    implementation group: 'org.jline', name: 'jline-terminal-jna', version: '3.12.1'
    implementation group: 'net.java.dev.jna', name: 'jna', version: '5.3.1'

}

これにより、意図したバージョンのライブラリが使われるようになりました。

default - Configuration for default artifacts.
+--- org.jline:jline:3.12.1
+--- org.jline:jline-terminal-jna:3.12.1
|    +--- net.java.dev.jna:jna:5.3.1
|    \--- org.jline:jline-terminal:3.12.1
\--- net.java.dev.jna:jna:5.3.1

これで冒頭のエラーがなくなりました。

おわりに

このエントリでは、Gradleの依存解決で、うまくいかないときの対処の一例として、依存関係の確認の仕方と、利用ライブラリを上書きでしていするやりかたをご紹介しました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1