4 Stimmen

Wie kann ich von meinem Clojure-Programm aus auf JAR-Klassen zugreifen?

Ich stecke schon seit einigen Tagen in einer Sache fest, die ich wissen Ich bin schon einmal zur Arbeit gegangen. Wahrscheinlich übersehe ich etwas Offensichtliches. Für jede Hilfe wäre ich dankbar.

In meinem Clojure-Programm möchte ich auf Methoden von Klassen zugreifen, die ursprünglich in Java geschrieben wurden. Nehmen wir ein konkretes Beispiel: org.infoml.jaxb.ObjectFactory. Diese Klassen befinden sich in einer .jar-Datei ( infoml-classes-1.0.jar ), die eine doppelklickbare Java-Anwendung ist. Wenn Sie die jar-Datei öffnen, sehen Sie den Ordner für das oberste Segment des Pakets der Java-Klassen:

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$

In meinem Clojure-Programm importiere ich es (aus der Datei 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)))

Wenn ich den Klassenpfad ausdrucke, den die REPL sieht, ist es dort (als 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>

Wenn ich jedoch versuche, die Datei cardmaker.clj zu kompilieren (entweder mit C-c C-k oder (load-file "src/infwb/cardmaker.clj") erhalte ich die folgende Ausnahme:

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

Ich bin sogar so weit gegangen, meinen Rechner neu zu starten, um zu versuchen, versehentliche Verschmutzungen als Ursache des Problems auszuschließen. Ich habe verschiedene Dinge im Internet recherchiert - ohne Erfolg. Ich habe in der Datei MANIFEST.MF nach Hinweisen gesucht und die jar-Datei auf die Klassen reduziert, die ich brauche. Ich habe jetzt zweimal über Nacht darüber geschlafen - immer noch keine Lösung.

Die Verwendung vorhandener Java-Klassen in Clojure ist eine nützliche Sache. Ich wäre dankbar für die Hilfe, die mir jemand geben kann. Danke!


ADDENDUM: Mein Problem wurde durch eine Reihe von Faktoren verursacht, darunter eine fehlende jar-Datei. Die Antwort von @kotarak war genau richtig. Danke.

3voto

Julien Chastang Punkte 17256

Ich bin nicht 100 % sicher, dass ich Ihre Frage vollständig verstehe, aber wenn Sie einfach versuchen, Ihre Java-Klassen von einem Clojure-Programm zuzugreifen, würde ich leiningen . Hier ist ungefähr, was Sie tun, sobald Sie leiningen installiert haben:

lein new cardmaker
cd cardmaker
lein deps

Legen Sie Ihre jar-Datei in das lib-Verzeichnis.

Danach erhalten Sie eine Verzeichnisstruktur, die wie folgt aussieht:

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

Jetzt können Sie Ihre Java-Klassen in Ihr Clojure-Programm importieren und haben über Clojure-Java-Interop Zugriff auf sie. Hier ist ein Beispiel

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

Um dieses Programm auszuführen, haben Sie eine Reihe von Möglichkeiten. Siehe die leiningen docs . Es sieht so aus, als ob Sie emacs verwenden, siehe protziger Clojure . Die Verwendung von leiningen auf diese Weise sollte Ihre Klassenpfadprobleme lösen.

1voto

mikera Punkte 103423

Ich verwende den folgenden Code, um Java-Klassen zu importieren:

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

Dies sollte funktionieren, vorausgesetzt, die entsprechenden Java-Klassen befinden sich auf dem Klassenpfad (es ist in Ordnung, wenn sie in einer .jar-Datei enthalten sind).

Um zu testen, ob sich diese im Klassenpfad befinden, können Sie auch Folgendes in der REPL tun:

  (import 'my.package.MyClassOne)

1voto

kotarak Punkte 16848

Die Art, wie Sie import die Klassen sind in Ordnung. Offensichtlich ist die ObjectFactory Klasse kann nicht initialisiert werden, weil eine andere Klasse, die sie benötigt, nicht im Klassenpfad liegt. Schauen Sie sich den vollständigen Stacktrace an, um herauszufinden, welche Klasse fehlt für ObjectFactory zur Arbeit. Wie @mikera vorgeschlagen hat, können Sie Folgendes verwenden (import 'org.infoml.jaxb.ObjectFactory) in der Replik, um das zu tun. (Es sei denn, Emacs frisst Ihren Stacktrace...)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X