Pot produit avec lein uberjar échoue sur NoClassDefFoundError
Question
Je simple application web avec ce project.clj:
(defproject squirrel-money "1.0.0-SNAPSHOT"
:description "Squirrel Money"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[compojure "0.5.3"]
[ring/ring-jetty-adapter "0.3.5"]
[hiccup "0.3.1"]
[postgresql "8.4-701.jdbc4"]
[clj-time "0.2.0-SNAPSHOT"]]
:dev-dependencies [[lein-eclipse "1.0.0"]]
:main squirrel-money.main
:repl-init-script "src/squirrel_money/init_repl.clj")
Mon principal ressemble à ceci:
(ns squirrel-money.main
(:gen-class)
(:use
[compojure.core]
[ring.adapter.jetty])
(:require
[compojure.route :as route]
[squirrel-money.savings :as savings]))
(defn launch [routedef]
(run-jetty routedef {:port 17080}))
(defroutes money-routes
(GET "/savings" [] (savings/render))
(route/not-found "Page not found"))
(defn -main [& args] (launch money-routes))
Avec REPL fonctionne très bien. Cependant, quand je produis un pot avec lein uberjar
et essayer de l'exécuter comme:
java -jar squirrel-money-1.0.0-SNAPSHOT-standalone.jar
Il meurt à cette exception:
Exception in thread "main" java.lang.NoClassDefFoundError: compojure/response/Renderable
at squirrel_money.main$fn__1067.invoke(main.clj:18)
at squirrel_money.main__init.load(Unknown Source)
at squirrel_money.main__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:1578)
at clojure.lang.RT.load(RT.java:399)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4511.invoke(core.clj:4905)
at clojure.core$load.doInvoke(core.clj:4904)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.lang.Var.invoke(Var.java:365)
at squirrel_money.main.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: compojure.response.Renderable
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
... 13 more
Qu'est-ce que je fais mal? Comment faire fonctionner?
Je ne sais pas si cette question, mais je remarque que l'intérieur du pot mes fichiers, Clojure lui-même et Java libs sont déballés sous forme de fichiers .class, alors que tous les libs Clojure ne sont présents que sous forme de fichiers .clj simples.
La solution
Cela semble être un bug leinigen 1.4.0. Vous voudrez peut-être essayer de créer un uberjar avec Leiningen 1.3.1.
Modifier :
Leiningen 1.4.0 supprime les fichiers .class
non-projet de travail autour d'un bug Clojure (voir CLJ-322 ). Apparemment, ce comportement peut parfois causer des problèmes.
Vous pouvez garder Leiningen 1.4.0 de supprimer les fichiers .class
non-projet en mettant à :keep-non-project-classes
true
dans votre project.clj
.
Voir la leinigen question pour plus d'informations.