【问题标题】:ClassNotFoundException when using instance? on a defrecord type in Clojure使用实例时出现 ClassNotFoundException? Clojure 中的 defrecord 类型
【发布时间】:2014-12-10 14:22:24
【问题描述】:

我编写了一个函数,它只选择在特定 schema 中命名的映射键:

(ns foo.schema
  (:require [schema.core :as s]))

(defn select-schema
  "Given a schema and a map m, selects only the keys of m that are named in the schema."
  [m schema]
  (let [optional? #(instance? schema.core.OptionalKey %)
        wildcard? #(= s/Keyword %)]
    (if (some wildcard? (keys schema))
      m  ; the schema allows any keyword as a key, so just return the map
      (let [ks (->> schema keys (map #(if (optional? %) (:k %) %)))]
        (select-keys m ks)))))

这在我的单元测试中效果很好:

(testing "Required key and wildcard"
    (let [schema {:foo s/Str, s/Keyword s/Any}]
      (is (= {:foo "Yup", :bar 42, :baz true} (select-schema {:foo "Yup", :bar 42, :baz true} schema)))
      (is (= {:foo "Yup", :bar 42} (select-schema {:foo "Yup", :bar 42} schema)))
      (is (= {:foo "Yup"} (select-schema {:foo "Yup"} schema)))))

但是,当我在一个完全独立的项目中使用 foo.schema/select-schema 时(即在我的 foo 项目中使用 lein install 来构建一个 jar 并将其粘贴到我的 ~/.m2/repository 中并将其命名为依赖项),我得到一个 @987654327 @:

Exception in thread "main" java.lang.ExceptionInInitializerError, compiling:(insurrection/test/handler.clj:1:1)
    at clojure.lang.Compiler.load(Compiler.java:7142)
    ...
Caused by: java.lang.ExceptionInInitializerError
    at foo.schema__init.load(Unknown Source)
    at foo.schema__init.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    ...
Caused by: java.lang.ClassNotFoundException: schema.core.OptionalKey
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    ...

我查看了 Prismatic Sc​​hema 源代码,发现 OptionalKey 是一个 defrecord 类型。一点谷歌搜索显示 defrecord 生成一个 Java 类,有时需要在需要定义它的命名空间后导入该类,但尝试在包含 foo.schema 的项目中执行此操作没有任何区别:它在单元中工作测试,但在使用 foo 作为依赖项的其他项目中不起作用。

【问题讨论】:

    标签: clojure plumatic-schema


    【解决方案1】:

    您将schema.core 导入为s。如果这正是您正在运行的代码,您可能应该使用 #(instance? s/OptionalKey %) 作为您的 optional? 函数。

    更不用说schemaselect-schema 中的局部变量(参数)。

    【讨论】:

    • instance? 适用于 Java 类型,因此它不知道 Clojure 命名空间和 require ... :as s 的别名。我不明白你关于schemaselect-schema 中的局部变量(AKA 绑定)的第二个陈述。这会导致问题吗?
    • 没关系,我是个白痴。在这种情况下,您的问题可能是任何 jar 定义 schema.core.OptionalKey 在运行单独的项目时不在您的类路径中。
    • 你知道为什么会这样吗?我将 prismatic/schema 定义为 foo 项目(包含上述函数)依赖于 foo 的单独项目中的依赖项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    相关资源
    最近更新 更多