【问题标题】:Clojure interop with Java: how to call a class?Clojure 与 Java 互操作:如何调用一个类?
【发布时间】:2015-06-22 01:39:41
【问题描述】:

我有一个 Java 应用程序,它在这个地址有一个类,在标准 Maven 布局内:

src/main/java/com/ollio/nlp/Transformer.java 

我想要的类和方法如下所示:

package com.ollio.nlp;

public class Transformer {
    public String transform(String JSONInput) {

我将 jar 工件本地存储在我的 Clojure 应用程序中,地址为:

maven_repository/local/nlp/1.0-SNAPSHOT/nlp-1.0-SNAPSHOT.jar 

我尝试了十几种变体将其导入到我的 Clojure 应用程序中,例如:

 (:import
    [com.ollio.nlp.Transformer])

但我不断收到错误消息“没有这样的命名空间”。

导入这个的正确方法是什么?

已编辑:

这是我目前尝试执行导入语句的方式:

(ns slick.query
  (:import
    [nlp.*])

我也试过了:

(ns slick.query
  (:import
    [com.ollio.nlp.*])

我尝试了其他一些变体。

project.clj 文件如下所示:

(defproject slick "0.1"
  :description "slick is  an API for other ollio services, such as our mobile app."
  :dependencies [[org.clojure/clojure "1.6.0"]
             [com.taoensso/timbre "3.2.1"]
             [dire "0.5.1"]
             [slingshot "0.10.3"]
             [ring "1.4.0-RC1"]
             [clj-time "0.6.0"]
             [org.clojure/data.json "0.2.5"]
             [compojure "1.3.4"]
             [com.novemberain/monger "2.0.1"]
             [org.clojure/tools.namespace "0.2.4"]
             [manifold "0.1.0"]
             [me.raynes/fs "1.4.4"]
             [org.clojure/core.incubator "0.1.3"]
             [clj-stacktrace "0.2.7"]
             [overtone/at-at "1.2.0"]
             [ring/ring-json "0.3.1"]
             [clj-http "1.1.2"]
             [org.clojure/core.cache "0.6.4"]
             [cheshire "5.5.0"]
             [org.clojure/core.match "0.3.0-alpha4"]
             [local/nlp "1.0-SNAPSHOT"]]
  :repositories {"local" ~(str (.toURI (java.io.File. "maven_repository")))}
  :disable-implicit-clean true
  :source-paths      ["src/clojure"]
  :java-source-paths ["src/java"]
  :main slick.core
  :aot :all
  :jvm-opts ["-Xms100m" "-Xmx1000m" "-XX:-UseCompressedOops"])

【问题讨论】:

  • 您在ns 表单中使用:import 吗?因为如果你不小心在ns 之外使用了:import,你会得到那个错误。最好的办法是使用 (ns .... (:import ...))(import ...) 在顶层工作(通常对 repl 有用)。
  • 另外,你如何将 maven dep 添加到你的类路径中?您是否使用 maven 来运行 Clojure?使用莱宁根?使用引导?
  • 您的项目是如何设置的? java源码树相对于clojure源码树在哪里?
  • 艾伦,Java 项目是完全独立的。它保存在标准的默认 Maven 目录结构中。我使用您在上面看到的命令复制了 jar 工件。
  • 仍然没有足够的信息来诊断问题。包含“没有这样的命名空间”的完整错误是什么?这真的是错误信息吗? (我试图通过在我的一个项目中创建问题来准确生成该错误消息,但到目前为止还没有成功。)它什么时候发生?有行号吗?那里的源代码发生了什么?您可以使用lein compile 使错误发生吗?你能在 REPL 上使用require 实现它吗? requireing 什么?它可能与 Java lib 无关。

标签: java maven clojure interop leiningen


【解决方案1】:

如果您在一个项目中混合使用 java 和 clojure 源代码,您应该首先查看 lein 文档:https://github.com/technomancy/leiningen/blob/master/doc/MIXED_PROJECTS.md

此外,如果您发布了 project.clj 和 java/clojure 源的布局,则更容易发现缺少的内容。

【讨论】:

  • 我不想在一个项目中混合使用 java 和 clojure 源代码。
【解决方案2】:

您可能希望将 :import 语句中的最后一个句点更改为空格:

(ns mynamespace
  (:import [com.ollio.nlp Transformer]))

(编辑:您不能在此处使用通配符。com.ollio.nlp 中的每个类都必须明确列出,用空格分隔。)这将允许您使用不合格的Transformer

(.transform (Transformer. <add constructor args here>) my-json-input)

正如@noisesmith 所说,:import 语句应该是ns 声明的一部分。

项目的设置方式也很有可能存在问题。你没有给出任何迹象表明这很可能,但我相信它经常发生在人们开始使用 Java 互操作时。 (无论如何,它发生在我身上。)所以@AlanThompson 的建议可能是相关的。

您也可以简单地删除 :import 语句,并以完全限定的形式使用 Java 类名,例如:

(.transform (com.ollio.nlp.Transformer. <add constructor args here>) my-json-input)

如果您在执行此操作时遇到错误,则可能是设置有问题(除非您错误地使用了该类)。

(我不确定这有多大帮助。Alan Thompson 的回答可能是合适的。)

【讨论】:

  • 我不想在一个项目中混合java源代码和clojure源代码,所以Alan Thompson的回答有点误导。我有一个 jar 工件,我正试图将其包含在我的项目中。
  • 鉴于您最初写的内容,这是一个合理的猜测。无论您是否包含源代码,都会出现一些相同的问题。查看我关于通配符的最新编辑。
  • 这有效:"(.transform (com.ollio.nlp.Transformer.) my-json-input)"
  • 太棒了!在这种情况下,在 import 语句中在 com.olllio.nlp 之后明确列出用空格分隔的类应该允许您使用 Transformer. 而不使用其名称的其余部分,但这是您的选择。需要说明的是,要让类的源代码在使用时完全明确。
猜你喜欢
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多