2012-08-27 18 views
5

Tengo una aplicación de Java existente que se ejecuta en Tomcat a la que estoy agregando algún soporte Clojure primitivo. Por el momento, solo incluyo los archivos fuente de Clojure como recursos en el classpath y lo invoco a través del clojure.lang.RT. Es primitivo, pero funciona bien.Recarga del código de Clojure en Tomcat

Sin embargo, me he dado cuenta de que Tomcat's WebappClassLoader almacena en caché los recursos recuperados a través de getResourceAsInputStream() que Clojure usa para recuperar y compilar el código fuente. Es decir, al hacer (require 'my-ns :reload), simplemente vuelve a cargar la versión almacenada en caché del archivo, aunque hay uno actualizado disponible en el disco. ¿Hay alguna forma de eludir o evitar este almacenamiento en caché de los archivos de Clojure?

Lo mejor que he encontrado después de mucho infructuoso Google es utilizar la reflexión para eliminar manualmente la entrada de WebappClassLoader.resourceEntries que es horrible.

Me falta algo.

Respuestas como "use Jetty/Glassfish/JBoss", "reiniciar Tomcat", etc. no son lo que estoy buscando.

Respuesta

2

No se puede evitar el comportamiento WebappClassLoader allí. Lo que puede do es mover el código que se está cargando fuera de su jurisdicción; p.ej. hasta $CATALINA_HOME/lib, como se describe here.

Tendrá que mover todas sus dependencias allí también, dejando el archivo .war que implementa como una aplicación web como un pequeño shell que espera que todo el código ya esté disponible en otro lugar.

Esto lo sacará de la jurisdicción de WebappClassLoader, y con suerte su semántica también. (Si almacena en caché las cosas cargadas de los cargadores de clase originales, eso parecería completamente descompuesto.)

+0

Gracias Chas. Tendré que pensar un poco sobre esto. Poner cosas en 'lib' no es tan conveniente. Me pregunto si '* use-context-classloader *' tendría un efecto sin atornillar otras cosas. –

+0

@DaveRay '* use-context-classloader *' es verdadero por defecto. Si se establece en falso, las cargas se enrutarán a través del ClassLoader que cargó Clojure, lo que no tendrá ningún efecto (si Clojure se cargó desde la aplicación web) o causará la rotura (es decir, si coloca clojure.jar en '$ CATALINA_HOME/lib 'pero intente cargar el código de una aplicación web). P: ¿por qué no acaba de iniciar un servidor REPL desde la aplicación web, conectarse a él y cargar el código con abandono de esa manera? – cemerick

+0

Gracias. Tal vez no soy lo suficientemente creativo sobre cómo usaría un servidor REPL para esto :) Digamos que tengo un montón de código en varios archivos en el disco.Arranco Tomcat con el servidor de réplica en ejecución, ¿cómo consigo todo ese código allí? –

0

¿Puede colocar los archivos fuente de Clojure en WEB-INF? A continuación, puede leerlos usando http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletContext.html#getResourceAsStream(java.lang.String)

servletContext.getResourceAsStream("/WEB-INF/foo/core.clj");

Esto funcionó para mí en el pasado para cargar las clases Groovy-un caché de la fuente de Tomcat.

+0

Parece que eso funcionaría si pudiera obtener 'clojure.lang.RT' para cargar archivos de esa manera. De lo contrario, '(require 'foo: reload)' continuaría usando el cargador de clases de contexto. –

0

¿Está relacionado con la bandera cachingAllowed como se describe here? Solo disparando al azul.

0

o utilizar una versión parcheada de clojure el que hace algo en la línea:

(io/input-stream (io/resource "bla.clj")) 

me encontré con una observación en la red que no se almacena en caché.

+0

'(io/resource)' usa el cargador de clases de contexto, por lo que pasará por Tomcat y se almacenará en caché. :( –

+0

@ dave-ray He encontrado afirmaciones de que '.getResource' (utilizado por' io/resource') no está almacenado en la memoria caché. No conozco a Tomcat. Por mi parte, todo esto está adivinando de todos modos. – kotarak

Cuestiones relacionadas