2011-06-07 25 views
2

我已經堅持了幾天的事情,我知道我已經開始工作過一次。我可能錯過了一些明顯的東西。任何幫助,將不勝感激。如何從Clojure程序中訪問JAR類?

在我的Clojure程序中,我想從最初用Java編寫的類訪問方法。我們使用一個具體的例子:org.infoml.jaxb.ObjectFactory。這些類位於.jar文件(infoml-classes-1.0.jar)中,該文件是一個雙擊Java應用程序。如果你打開jar文件,你會看到該文件夾​​的Java類包的最高級別會議:

macscooter:infoml-classes-1.0 folder gw$ find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g' 
. 
|____META-INF 
| |____MANIFEST.MF 
|____org 
| |____infoml 
| | |____infocardOrganizer <<<<<< Java application's classes 
| | | |____AFileFilter.class 

     | ... many classes omitted here 

| | | |____UniqueContentListener.class 
| | | |____UniqueContentModel.class 
| | |____jaxb 
| | | |____AgentContainerLocationType.class 
| | | |____AgentType.class 

     | ... many classes omitted here 

| | | |____ObjectFactory.class <<<<<< HERE IT IS 

     | ... many classes omitted here 

| | | |____TableRowType.class 
| | | |____TableType.class 
macscooter:infoml-classes-1.0 folder gw$ 

在我的Clojure程序,我將其導入(從文件cardmaker.clj):

(ns infwb.cardmaker 
    (:gen-class) 
    (:import 
    (javax.xml.bind JAXBContext JAXBException Marshaller 
      Unmarshaller) 
    (org.infoml.jaxb  ContentAgentContainerLocationType 
      InfomlFile InfomlType ObjectFactory PType <<<<<< HERE IT IS 
      RichTextWithExactType 
      SelectorsType 
      SimpleRichTextType) 
    (java.io ByteArrayOutputStream IOException))) 

當我打印出來的REPL看到classpath中,它的存在(如infoml-classes-1.0.jar):

infwb.cardmaker> (doseq [p (.getURLs (java.lang.ClassLoader/getSystemClassLoader))] (println (.getPath p))) 
/Users/gw/tech/clojurestuff/cljprojects/infwb/src/ 
/Users/gw/tech/clojurestuff/cljprojects/infwb/test/ 
/Users/gw/tech/clojurestuff/cljprojects/infwb/classes/ 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/clojure-1.3.0-SNAPSHOT.jar 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/clojure-contrib-1.2.0.jar 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/infoml-classes-1.0.jar <<<<<< HERE IT IS 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/piccolo2dcore-1.3.jar 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/piccolo2dextras-1.3.jar 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/sxqj-beta2.jar 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/dev/clojure-1.2.0.jar 
/Users/gw/tech/clojurestuff/cljprojects/infwb/lib/dev/swank-clojure-1.3.0-20110104.084027-21.jar 
nil 
infwb.cardmaker> 

然而,當我試圖編譯文件cardmaker.clj(通過C- C C-K或(load-file "src/infwb/cardmaker.clj"),我得到以下異常:

Could not initialize class org.infoml.jaxb.ObjectFactory 
    [Thrown class java.lang.NoClassDefFoundError] 

我作爲走得更遠,重新啓動我的機器,試圖消除無意污物作爲問題的來源。我在互聯網上研究了幾件事情 - 沒有運氣。我查看了MANIFEST.MF文件中的線索,並將jar文件拆分爲我需要的類。我現在一夜間睡了兩次 - 仍然沒有解決辦法。

在Clojure中使用現有的Java類是非常有用的。我會很感激任何人都可以給我的幫助。謝謝。


附錄:我的問題是由許多因素造成的,包括丟失的jar文件。 @ kotarak的答案是現貨。謝謝。

+1

你有沒有嘗試另一種符號導入java類?例如: (import'(packagename ClassName)) – 2011-06-07 05:21:16

+0

'import'很好。您是否試圖超越emacs所說的內容?也許'ObjectFactory'本身需要另一個類,這是找不到?嘗試將代碼加載到普通的repl中以查看完整的堆棧跟蹤。 – kotarak 2011-06-07 08:24:14

回答

1

這就是你import類是罰款。顯然ObjectFactory類不能被初始化,因爲它需要的其他類不在類路徑中。查找完整的堆棧跟蹤,找出ObjectFactory工作時丟失哪個類。正如@mikera建議的那樣,您可以在Repl中使用(import 'org.infoml.jaxb.ObjectFactory)來完成此操作。 (除非emacs吃你的堆棧跟蹤...)

2

我不完全確定你的問題,但如果你只是試圖從Clojure程序訪問你的Java類,我會使用leiningen。這裏大致是你安裝了leiningen後你要做的:

lein new cardmaker 
cd cardmaker 
lein deps 

把你的jar文件放在lib目錄下。

此之後,你會得到像這樣的目錄結構:

├── README 
├── classes 
├── lib 
│   ├── clojure-1.2.1.jar 
│   └── infoml-classes-1.0.jar 
├── project.clj 
├── src 
│   └── cardmaker 
│    └── core.clj 
└── test 
    └── cardmaker 
     └── test 
      └── core.clj 

現在你可以導入你的Java類中您的Clojure程序,並必須通過Clojure的Java的互操作對它們的訪問。這裏是一個例子

(ns cardmaker.core 
    (:import [java.util Blah Blah])) 

要運行這個程序,你有一堆不同的選項。請參閱leiningen docs。看起來您正在使用emacs,所以請參閱swank clojure。以這種方式使用leiningen應該解決您的類路徑問題。

1

我用下面的代碼導入Java類:

(ns my.namespace 
    (:import [java.io DataInputStream File FileInputStream BufferedInputStream]) 
    (:import [my.package MyClassOne MyClassTwo]) 
    .... 

這應該提供相關的Java類的類路徑上(這是罰款,如果他們是在一個.jar)。

爲了測試這些是否你也可以做類路徑在REPL如下:

(import 'my.package.MyClassOne) 
相關問題