Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure classpath issue within an Eclipse plugin

(I'm aware this is related to How can I embed Clojure in an RCP application, but that thread is old and my setup is somewhat different)

I'm using Eclipse 3.7.1 and for days now have been trying to write an Eclipse/RCP app in Clojure (as much as possible). I've tried building the source version of clojure.osgi and CCW, have tried the RCPClojure demo project and several other things. Each one of them didnt work (mainly seemingly "unfixable" build/classpath errors, lack of up-to-date docs/response, version conflicts etc...)

My own steps to bring me at least 50% success:

  1. Create a new plugin project wrapping the Clojure 1.3.0 jar file, set plugin ID org.clojure.v1.3.0

  2. Create a new plugin project org.cljtest42 using RCP Hello template

    1. Adding org.clojure plugin dependency
    2. Adding CCW project nature (to enable AOT compiling), this step adds the /classes folder
    3. Edit plugin.xml to add /classes folder to runtime classpath, also add org.cljtest42 to exported packages.
  3. Add two simple Clojure files in the org.cljtest42 package/namespace:

    TestClass.clj:

    (ns org.cljtest42.TestClass
    (:gen-class))
    
    (defn -main [greet] (println greet))
    

    compile.clj

    (ns org.cljtest42.compile)
    (dorun (map compile ['org.cljtest42.TestClass]))
    
  4. Trigger AOT compilation by selecting project node and choose Run > Clojure application (the /classes folder should now be populated with compiled clojure classes).

  5. Reference TestClass from the Activator class (e.g. in start() - also tried in Perspective.createInitialLayout())

So far so good. However, trying to run this project as an Eclipse application always fails with this:

java.io.FileNotFoundException: Could not locate org/cljtest42/TestClass__init.class or org/cljtest42/TestClass.clj on classpath:
at clojure.lang.RT.load(RT.java:430)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:401)
at com.pspctclr.cljtest42.TestClass.<clinit>(Unknown Source)

It would be outstanding if someone more knowledgable could share some pointers on how this issue could be overcome. Could it be that it's either because the AOT compiled classes don't actually end up in the classpath (not sure why?, /classes is explicitly added) or that the separate Clojure plugin can't access them due to the way Equinox/OSGI works?

Thanks!

like image 877
toxi Avatar asked Nov 13 '22 15:11

toxi


1 Answers

The problem seems that the Clojure bundle doesn't see your bundle's classes, although you've exported them. This is, because, in OSGi (as you probably know), in order for a bundle to be able to see a class, its package needs to be imported.

But what about cases, where a bundle needs to load a class from a bundle, which has called it. In order for this to work, Eclipse has implemented buddy policies, which are designed exactly for this case:

  1. Your Clojure bundle needs to have manifest header Eclipse-BuddyPolicy: [dependent|registered].
  2. If you've added Eclipse-BuddyPolicy: registered, you'll need to add manifest header to the bundles, which uses Clojure: Eclipse-RegisterBuddy: <clojure-bundle-name>

Disclaimer: I don't have any experience with Clojure, but I wanted to take a shot at this.

like image 55
Danail Nachev Avatar answered Dec 15 '22 03:12

Danail Nachev