Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jar produced with lein uberjar fails on NoClassDefFoundError

I have a simple web app with this 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")

My main looks like this:

(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))

With REPL works just fine. However, when I generate a jar with lein uberjar and try to execute it as:

java -jar squirrel-money-1.0.0-SNAPSHOT-standalone.jar

It dies with this 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

What am I doing wrong? How to get it to work?

Not sure if that matters, but I noticed that inside the jar my files, clojure itself and Java libs are unpacked as .class files, while all clojure libs are present only as plain .clj files.

like image 984
Konrad Garus Avatar asked Dec 04 '10 15:12

Konrad Garus


1 Answers

This seems to be a leinigen 1.4.0 bug. You might want to try creating an uberjar with leiningen 1.3.1.

Edit:

Leiningen 1.4.0 deletes non-project .class files to work around a Clojure bug (see CLJ-322). Apparently this behavior can sometimes cause problems.

You can keep leiningen 1.4.0 from deleting non-project .class files by setting :keep-non-project-classes to true in your project.clj.

See the related leinigen issue for more info.

like image 190
mtyaka Avatar answered Sep 30 '22 06:09

mtyaka