lein instalar code bridal clojure leiningen

instalar - Recursos en aplicaciones Clojure



instalar clojure (7)

Estoy utilizando Leiningen en mi proyecto Clojure (una aplicación GUI) y creé un directorio de "recursos" en la raíz del proyecto para guardar las imágenes que usa mi aplicación.

Cuando ejecuto mi aplicación localmente durante las pruebas, recupero las imágenes usando la ruta relativa "resources / logo.png", y esto funciona bien. Pero cuando construyo un uberjar utilizando Leiningen, Leiningen coloca los archivos de la carpeta de recursos en la carpeta raíz del JAR, por lo que mis referencias a los archivos de recursos ya no funcionan.

¿Cuál es la forma correcta de acceder a recursos como este utilizando Leiningen?


Buena manera de hacerlo. Tenga en cuenta que io/file devuelve un objeto de File java, que luego se puede pasar a slurp , etc:

(ns rescue.core (:require [clojure.java.io :as io] )) (def data-file (io/file (io/resource "hello.txt" ))) (defn -main [] (println (slurp data-file)) )

Si luego ejecuta lo siguiente en su directorio de proyecto lein:

> echo "Hello Resources!" > resources/hello.txt > lein run Hello Resources!

y presto! Estás leyendo archivos de recursos a través del classpath.


El contestador anterior (skuro) señaló que necesito obtener el archivo desde el classpath. Después de un poco más de excavación, esta parece ser la solución que funciona para mi caso:

(.getFile (clojure.java.io/resource "foo.png"))


En nuestro caso, usar .getPath o .getFile fue útil. Simplemente utilizando input-stream lugar de resolverlo.

(defonce classifier (-> "machine_learning/classifier.model" resource input-stream helper/read))


Esto no es responder directamente a la pregunta del OP, pero skuro mencionó algo en su último párrafo que puede ser bastante útil, es decir, para hacer que los recursos estén disponibles en el classpath durante el desarrollo, pero no los incluya en la versión jar / uberjar.

El motivo es que puede colocar los recursos por separado fuera del contenedor (por ejemplo, colocar los archivos de configuración en /etc ) y luego vincularlos en tiempo de ejecución enumerando dichas carpetas de recursos en la ruta de clase.

Definiciones en project.clj

  • elimine las :resource-paths de :resource-paths nivel superior de su project.clj;
  • agregue las siguientes líneas en el project.clj en el nivel superior:

:profiles {:dev {:resource-paths ["src/main/resources"]}}

De esta manera, los recursos estarán disponibles en el classpath durante el desarrollo (compilación, prueba, respuesta), pero no se incluirán en los archivos de lanzamiento.

Como alternativa, es posible que desee agrupar algunos de los recursos con la versión de lanzamiento, como los iconos y gráficos de aplicaciones, pero no otros, como los archivos de configuración. En ese caso, podría dividir la carpeta de recursos en subdirectorios y declarar los que desea incluir en el nivel superior, mientras que el resto está bajo el perfil de desarrollo:

:resource-paths ["src/main/resources/icons" "src/main/resources/images"] :profiles {:dev {:resource-paths ["src/main/resources/config"]}}

Referencia de recursos en código

Usando el método anterior, puede hacer referencia a los recursos durante el desarrollo y la producción de manera uniforme al mirarlos en el classpath (como lo muestran Kevin y Valerii ), y no directamente en el sistema de archivos:

(require ''[clojure.java.io :as jio]) (jio/file (jio/resource "relative/path/to/resource.xml"))

Rutiempo classpath

Durante el desarrollo, Leiningen incluiría los recursos de perfil de nivel superior y de desarrollo en el classpath. Para el tiempo de ejecución publicado, deberá configurar el classpath para el JRE usted mismo:

java -cp "/etc/myapp:/usr/local/lib/myapp.jar" myapp.core $*

Además, también puede dejar todos los recursos incluidos en el frasco. De esa manera, los recursos incluidos se utilizarían como predeterminados. Si configura la ruta de clase para que el archivo .jar aparezca después de la carpeta de configuración ( /etc/myapp en el ejemplo), entonces los archivos de recursos con la misma ruta de recursos relativa debajo de la carpeta de configuración tendrán prioridad sobre los incluidos en la carpeta de configuración. tarro.


Leiningen toma prestada la convención de recursos de maven, con diseños de carpetas ligeramente diferentes. La regla establece que la carpeta de resources debe usarse como una raíz de classpath de tiempo de compilación, lo que significa que leiningen está en lo correcto al colocar todos los archivos dentro de resources carpeta de resources en la ubicación raíz dentro del contenedor.

El problema es que la ubicación física! = Ubicación classpath, de modo que mientras la primera cambia cuando empaquetas tu aplicación, la última permanece igual ( classpath:/ )

Será mejor que confíe en la ubicación del classpath para encontrar los recursos de su sistema de archivos, o que los saque del contenedor y los coloque en una carpeta predecible, ya sea estática o configurable.


Solo una sintaxis de azúcar para la respuesta de Kevin Albrecht:

(require ''[clojure.java.io :as io]) (-> "foo.png" io/resource io/file)


Tuve exactamente el mismo problema y la solución no está usando io/file en absoluto. Por ejemplo, este es un código de trabajo de mi aplicación:

(defn load-md [md] (-> md io/resource ;;clojure.java.io slurp mp to-hiccup html))