Friday, December 23, 2011

lein uberjar ClassNotFoundException

This is probably documented somewhere, but it didn't come up in my searches and it took me forever to find out the cause of the problem so I'm posting it here for the greater good, general advancement of humankind and other worthy reasons.

I had a normal leiningen project with the :main attribute set in project.clj

(defproject clojure-diff "1.0.0-SNAPSHOT"
  ; Dependencies etc omitted for clarity
  :main clojure-diff.server
)

It runs fine using lein run but when I ran lein uberjar and then executed the jar file, I got a class not found error.

$ java -jar clojure-diff-1.0.0-SNAPSHOT-standalone.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure_diff/server
Caused by: java.lang.ClassNotFoundException: clojure_diff.server
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:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)


The solution is to specify :gen-class when defining the main namespace.  This means a .class file will be generate ahead of time when compiling the jar.  Obvious when you know how!

(ns clojure-diff.server
  (:gen-class)
  ; more namespace setup)

; .. stuff

(defn -main []
  (run-jetty #'clojure-diff.server/app {:port 8080}))