2017-09-03 5 views
1

Dans notre Clojure codebase nous avons un protocole:lein uberjar ne peut pas trouver une implémentation définie dans DEFTYPE

(ns project.repository) 

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

Un type

(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)) 

Et une instanciation

(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) 

Cela fonctionne bien lorsqu'il est utilisé de manière interactive à partir de REPL ou lancé avec lein run, mais lein uberjar invariablement ws une exception:

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) 

La partie la plus étrange est que le problème disparaît lorsque (index) est appelé dans un (let):

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

Toute réflexion sur ce qui pourrait être la cause de la différence?

+0

Est-ce que vous essayez de faire AOT-compilation avec lein uberjar? –

+0

@akond Oui! Cette exigence a été perdue lors de la copie et du collage du code dans la question. Correction de la question – 0x60

+0

@minhtuannguyen C'est ce que nous faisons. Nous avons: aot: tout dans project.clj et l'exception est levée lors de la compilation d'aot. – 0x60

Répondre

0

Je suppose que c'est quelque chose à voir avec essayer de se connecter à MongoDB lors de la compilation de project.mongo ns, ou de project.users ns. Ces lignes devraient probablement être dans un appel de fonction qui est appelée au démarrage, plutôt que le code est chargé:

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

et

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