lein uberjar找不到deftype中定义的实现

时间:2017-09-03 18:18:01

标签: clojure leiningen uberjar

在我们的Clojure代码库中,我们有一个协议:

(ns project.repository)

(defprotocol Repository
  (index [this fields unique]))

一种类型

(ns project.mongo (:require 
  [monger.collection :as mc] 
  [monger.core :as mg]
  [project.repository :refer :all]))  

(deftype MongoRepository [db collection-name]
  Repository
  (index [this fields unique]
    (mc/ensure-index db collection-name fields {:unique unique})))

(defn mongo-repository [db coll] (MongoRepository. db coll))

(def mongo-db ((mg/connect-via-uri "mongodb://127.0.0.1/bots") :db))

实例化

(ns project.users (:require 
  [lp-bots.storages.repository :refer :all]
  [lp-bots.storages.mongo :refer [mongo-repository mongo-db]]))

(def users-storage (mongo-repository mongo-db "users"))
(index users-storage [:key1 :key2] true)

从REPL以交互方式使用或使用lein run启动时,此方法正常,但lein uberjar总是抛出异常:

Exception in thread "main" java.lang.ExceptionInInitializerError, compiling:(/tmp/form-init118199196859405970.clj:1:72)
    ...
Caused by: java.lang.ExceptionInInitializerError
    ... 
Caused by: java.lang.IllegalArgumentException: No implementation of method: :index of protocol: #'project.repository/Repository found for class: project.mongo.MongoRepository
    at clojure.core$_cache_protocol_fn.invokeStatic(core_deftype.clj:568)
    at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:560)
    at project.repository$fn__557$G__514__566.invoke(repository.clj)
    at project.users__init.load(Unknown Source)
    at project.users__init.<clinit>(Unknown Source)

最奇怪的是,在(index)中调用(let)时,问题就会消失:

(def users-storage
  (let [u (mongo-repository mongo-db "leads")]
    (index u [:key1 :key2] true)
    u))

对可能造成这种差异的原因有什么看法?

1 个答案:

答案 0 :(得分:0)

我怀疑在编译project.mongo ns或project.users ns时尝试连接到MongoDB是有意义的。这些行可能应该在启动时调用的函数调用中,而不是在代码加载时调用:

(def mongo-db ((mg/connect-via-uri "mongodb://127.0.0.1/bots") :db))

(index users-storage [:key1 :key2] true)