views:

164

answers:

1

Hi,

I am trying to use clojure to implement a "plugin" for some vendor supplied software.

Here is a little background on the vendor supplied software. It expects me to implement a particular interface and then put the jar file containing that implementation into a directory on its server. Then when a client runs the software, my implemented class gets "sent" to the client from the server via RMI and then my implementation of the interface runs on the client. The client doesn't have my jar file (or the clojure jar file) in it's classpath. Only the server has those jar files. RMI seems to be smart enough to upload whatever dependencies are necessary.

I have successfully built a very simple implementation in clojure and it seems to work. The problem is, I would like to be able to update my implementation on the client on the fly. I embedded a repl-server in my class and I can successfully connect to it. Just to be clear, the repl-server is running on the client and I am able to connect to the repl getting a prompt "clojure.core=>". However, the repl seems to be quite crippled. If I enter (+ 1 1) I get the following error: "java.lang.ClassNotFoundException: clojure.lang.Numbers". If enter (str "kent") I get "java.lang.NoClassDefFoundError: clojure/lang/ AFunction". Most things I enter produce something similar. I can however do a simple def such as (def x 3) and x does get defined so the REPL does seem to be running in some sense.

It seems like it might be a classpath problem, but I'm not sure why my "compiled" code, running on the client would not have a classpath problem while the repl, running on the same client cant find core classes.

Any ideas?

Thanks. Kent.

+1  A: 

First of all, would it be possible to distribute clojure.jar as part of your RMI client? Based on your description of the vendor software, I'm guessing the answer is no.

Second, is the contents of clojure.jar and your RMI object in the same jar file on the server, or are both in their own jar files?

It seems very likely that it's a classloader issue. In Clojure each defined function generates its own class file that Clojure then load via a specific class loader. IIRC each function is loaded by its own classloader instance in order to allow that function to be garbage collected in case it is redefined. Similarly, I think, RMI uses its own class loader to load remote RMI objects over the network. So possibly the two class loaders interact badly.

Sorry I can't be of more help...

-- Lauri

liwp