Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Compiler by
edited by

Given a Java application already having Clojure's .jar on classpath. And a file directory /home/me/clojure-extensions/ which contains .clj files, structured like an usual clojure source directory, which is not on the applications classpath and can not be added to the classpath, because it is configurable and not part of the application.

How to call the function myns.core/myfn from Java Code? So that /home/me/clojure/extensions/myns/core.clj and all dependent files are loaded? So that these files are reloaded if changed when the Java call is invoked again?

1 Answer

0 votes

From the scenario you describe, you'll want /home/me/clojure-extensions/ on your classpath.

For calling Clojure from Java, you can use the Java API:


For reloading, you'll need to make that explicit by calling (via Java API)

(require 'whatever :reload-all)

which will look something like:

// this can be done once, statically
IFn require = Clojure.var("clojure.core", "require");

// to reload
require.invoke(Clojure.read("whatever"), Clojure.read(":reload-all"));

then use the same facilities to invoke a function in whatever.

What if `/home/me/clojure-extensions/` can not be added to the classpath? Because it is not part of the application. It is also configurable in the application. And the application is released as droppable .war without the extensions directory, which is meant to be provided by the admin.
I have seen this already. But I need to load a file and all dependent files on the same path. It seams, I have to extend the Java classpath when the JVM process is already running and then use the Clojure API.
You can't change the classpath, but you can create a new classloader context to run within your app that includes additional directories (see URLClassLoader). Doing this will require some care in how you first instantiate the Clojure runtime (via the Clojure class in the Java API) and the classes of objects returned from the Clojure API (as the app context needs access to any classes you return). In particular, if you're expecting anything other than built-in Java interfaces (Collection, List, Map, String, etc), I would recommend creating Java interfaces and returning reified instances of those.