Thursday, October 26, 2017

Multiple bindings were found on the class path

最近在使用 clojure 來開發和 Apache spark 相關的程式,有使用到 org.apache.spark/spark-core_2.10 這個 library 。但是,等到我要測試的時候,一啟動 lein repl 之後,問題就出現了,

vagrant@owl-docker:~/workspace/src/github.com/clo/october/intowow$ lein repl
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/vagrant/.m2/repository/org/slf4j/slf4j-log4j12/1.7.5/slf4j-lo
g4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/vagrant/.m2/repository/ch/qos/logback/logback-classic/1.1.3/l
ogback-classic-1.1.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 [org.slf4j.impl.Log4jLoggerFactory]
nREPL server started on port 37442 on host 127.0.0.1 - nrepl://127.0.0.1:37442

這個問題是這樣子,我的 clojure 專案因為是套用 luminus ,所以預設使用的 log library 是 logback 。但是不知道引入了什麼 library 之後,classpath 裡又多了一個 org.slf4j/slf4j-log4j12 。而這個又很不巧地先被引入了。所以最後專案使用的 log library 就變成使用 org.slf4j/slf4j-log4j12 而不是 logback 了。

這個問題,我研究了一陣子之後,想了一個解法:
(1) 先準備 lein-deps-tree 這個 leiningen plugin
(2) 執行之後,就可以看到專案的 dependency graph 。

果然,跟我預想的相差不遠,我最後引入的 library 不小心包含了 org.slf4j/slf4j-log4j12
最後,我的 project.clj 的其中一行修改成這樣子:
[org.apache.spark/spark-core_2.10  "1.1.0" :exclusions  [org.slf4j/slf4j-log4j12]]

引入 spark 的同時,不要引入它自帶的 log library