Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reloading Clojure code in Tomcat

Tags:

clojure

tomcat

I have an existing Java webapp running in Tomcat to which I'm adding some primitive Clojure support. For the time being, I'm just including Clojure source files as resources on the classpath and invoking it through clojure.lang.RT. It's primitive, but works fine.

However, I've noticed that Tomcat's WebappClassLoader caches resources retrieved through getResourceAsInputStream() which Clojure uses to retrieve and compile source code. That is, doing (require 'my-ns :reload) just reloads the cached version of the file even though an updated one is available on disk. Is there a way to circumvent or avoid this caching for Clojure files?

The best I've come up with after much fruitless googling is to use reflection to manually remove the entry from WebappClassLoader.resourceEntries which is awful.

I must be missing something.

Answers like "use Jetty/Glassfish/JBoss", "restart Tomcat", etc aren't what I'm looking for.

like image 312
Dave Ray Avatar asked Nov 04 '22 17:11

Dave Ray


1 Answers

You're not going to be able to circumvent WebappClassLoader's behaviour there. What you can do is move the code that's being loaded outside of its jurisdiction; e.g. up to $CATALINA_HOME/lib, as described here.

You'll need to move all of your dependencies there as well, leaving the .war file you actually deploy as a webapp as a small shell that expects all the code to already be available elsewhere.

This will get you out of WebappClassLoader's jurisdiction, and hopefully its semantics as well. (If it caches things loaded from parent classloaders, that would seem thoroughly broken IMO.)

like image 179
cemerick Avatar answered Nov 09 '22 14:11

cemerick