satch5150
satch5150

Reputation: 51

Getting Runtime Access to Clojure version number

From this so question I developed the code below. For now its only purpose (compiled as an uberjar) is to print its version number and exit.

; core.clj

(ns clojure-test-vnum.core
   (:gen-class))

(defn implementation-version []
  (-> (eval 'clojure-test-vnum.core) .getPackage .getImplementationVersion))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  ;; work around dangerous default behaviour in Clojure
  (alter-var-root #'*read-eval* (constantly false))

  (println (implementation-version)))



  ;project.clj

  (def version "0.1.0-SNAPSHOT")

  (defproject clojure-test-vnum version
     :manifest {"Implementation-Version" ~version}
     :description "Test to see if I can get a version number from an uberjar." 
     :url "http://example.com/FIXME"
     :license {:name "Eclipse Public License"
     :url "http://www.eclipse.org/legal/epl-v10.html"}
     :dependencies [[org.clojure/clojure "1.5.1"]]
     :main clojure-test-vnum.core
     :aot [clojure-test-vnum.core])

While this code compiles fine, I am getting a ClassNotFoundException at runtime. The problem seems to be with (eval 'clojure-test-vnum.core).

Following is the full stack trace:

  Exception in thread "main" java.lang.ClassNotFoundException: clojure-test-vnum.core, compiling:(NO_SOURCE_PATH:0:0)
     at clojure.lang.Compiler.analyze(Compiler.java:6380)
     at clojure.lang.Compiler.analyze(Compiler.java:6322)
     at clojure.lang.Compiler.eval(Compiler.java:6623)
     at clojure.lang.Compiler.eval(Compiler.java:6582)
     at clojure.core$eval.invoke(core.clj:2852)
     at clojure_test_vnum.core$implementation_version.invoke(core.clj:5)
     at clojure_test_vnum.core$_main.doInvoke(core.clj:14)
     at clojure.lang.RestFn.invoke(RestFn.java:397)
     at clojure.lang.AFn.applyToHelper(AFn.java:159)
     at clojure.lang.RestFn.applyTo(RestFn.java:132)
     at clojure_test_vnum.core.main(Unknown Source)
 Caused by: java.lang.ClassNotFoundException: clojure-test-vnum.core
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:61)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:266)
    at clojure.lang.RT.classForName(RT.java:2070)
    at clojure.lang.Compiler.resolveIn(Compiler.java:6855)
    at clojure.lang.Compiler.resolve(Compiler.java:6818)
    at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6779)
    at clojure.lang.Compiler.analyze(Compiler.java:6343)
    ... 10 more

What am I doing wrong ?

Upvotes: 2

Views: 595

Answers (1)

Michał Marczyk
Michał Marczyk

Reputation: 84331

You'll need to change

(eval 'clojure-test-vnum.core)

to

clojure_test_vnum.core

since the generated class will have underscores in its name in place of the hyphens in the name of the Clojure entity it is based on. No eval is necessary, the symbol will simply resolve to the class.

Upvotes: 3

Related Questions