タイガー!タイガー!じれったいぞー!(SE編)

AS400, Java, JavaEE, JSF等の開発、習慣など。日々の気づきをまとめたブログ(備忘録)

【Java】Java共通ライブラリー内でSLF4J+logbackを使ってハマったこと

組織独自のユーティリティ系のJava共通ライブラリを使って、開発を行っているのですが、そのJavaライブラリー内でのロギングでハマったことをまとめておこうと思います。

2つありました。

(1)SLF4J: Class path contains multiple SLF4J bindings.

MainのJavaアプリをbuildした際に出てきたエラー・メッセージです。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/develops/java-commons/build/libs/java-commons-1.0.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/gradle/gradle-5.6.1/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.2.3/7c4f3c474fb2c041d8028740440937705ebb473a/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

配布パッケージの依存先からlogbackを取り除けばいいことを知り、独自のユーティリティ系のJavaライブラリー(commons)側の build.gradleを下記のように修正したら、エラーメッセージが出力されなくなりました。

configurations {
    provided
}

sourceSets {
    main.compileClasspath += configurations.provided
    test.compileClasspath += configurations.provided
    test.runtimeClasspath += configurations.provided
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.28'
    //compile 'ch.qos.logback:logback-classic:1.2.3'
    //  ↓
    provided 'ch.qos.logback:logback-classic:1.2.3'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

ビルドシステムについての理解が足りていない証拠でしょう。

(2)Resource [logback.xml] occurs multiple times on the classpath.

次の壁は、MainのJavaアプリとJavaライブラリーのそれぞれに、「logback.xml」が存在しているため、次のような警告が出力されました。

> Task :Main.main()
INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/C:/develops/JavaMainApp/build/resources/main/logback.xml]
WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the classpath.
WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [file:/C:/develops/JavaMainApp/build/resources/main/logback.xml]
WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [jar:file:/C:/develops/java-commons/build/libs/java-commons-1.0.0.jar!/logback.xml]
INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]

期待する動きは、JavaMainAppを動かしたときに、JavaMainAppから吐き出されるログも、java-commonsから吐き出されるログも、すべてJavaMainAppのlogback.xmlで設定したファイルに出力させることでした。

警告ログからもわかるように、logback設定ファイルの検索順序は次の通りであるので、それぞれのプロジェクトごとにlogbackファイル名を変更して、挙動を試してみました。

  1. logback-test.xml
  2. logback.groovy
  3. logback.xml
選択肢 java-commons JavaMainApp java-commons実行 JavaMainApp実行
A logback.xml logback.xml java-commons設定のlog出力 JavaMainApp設定のlog出力
※WARN:Resource [logback.xml] occurs multiple times on the classpath.
B logback2.xml logback.xml log出力なし→ NG JavaMainApp設定のlog出力
C logback-test.xml logback.xml java-commons設定のlog出力 java-commons設定のlog出力→ NG

何か解決方法があるかもしれませんが、選択肢Aであれば期待する動きになるので(警告は毎回出ますが・・・)、とりあえずはこちらの設定で進めていこうと思っています。

また、新手のエラーが発生するかもしれませんが、「壁」は大いに結構です!!!

その壁を超える度に、強くなっていくつもりなので。


とりあえず、Gradleの勉強もやっていきましょうか。