2

Trying to use the approach described here I eventually came to the following simplified , narrow-down code that still exhibits the exception:

import clojure.lang.RT;

public class FooMain {

    public static void main(String [] args) {
        RT.var("clojure.core", "read-string").invoke("(+ 1 2)"); // line-6
    }
}

Which fails at runtime with the trace I append at the end of the post. I've tried that with either Clojure 1.4 or 1.5 Ivy deps:

<dependency org="org.clojure" name="clojure" rev="1.4.0"/> 

or:

<dependency org="org.clojure" name="clojure" rev="1.5.1"/>

trace

 run:
 [echo] ant.java.version=1.7
 [echo] running the app with classpath = /home/mperdikeas/esavo-reg/playground/calling-clojure-from-Java/lib-ivy/clojure-1.4.0-javadoc.jar:/home/mperdikeas/esavo-reg/playground/calling-clojure-from-Java/lib-ivy/clojure-1.4.0-sources.jar:/home/mperdikeas/esavo-reg/playground/calling-clojure-from-Java/lib-ivy/clojure-1.4.0.jar:/home/mperdikeas/esavo-reg/playground/calling-clojure-from-Java/dist/foo.jar
 [java] java.lang.ExceptionInInitializerError
 [java]     at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:194)
 [java]     at org.apache.tools.ant.taskdefs.Java.run(Java.java:771)
 [java]     at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:221)
 [java]     at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:135)
 [java]     at org.apache.tools.ant.taskdefs.Java.execute(Java.java:108)
 [java]     at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
 [java]     at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 [java]     at java.lang.reflect.Method.invoke(Method.java:601)
 [java]     at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 [java]     at org.apache.tools.ant.Task.perform(Task.java:348)
 [java]     at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
 [java]     at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
 [java]     at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 [java]     at java.lang.reflect.Method.invoke(Method.java:601)
 [java]     at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 [java]     at org.apache.tools.ant.Task.perform(Task.java:348)
 [java]     at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:398)
 [java]     at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
 [java]     at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 [java]     at java.lang.reflect.Method.invoke(Method.java:601)
 [java]     at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 [java]     at org.apache.tools.ant.Task.perform(Task.java:348)
 [java]     at org.apache.tools.ant.Target.execute(Target.java:390)
 [java]     at org.apache.tools.ant.Target.performTasks(Target.java:411)
 [java]     at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
 [java]     at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
 [java]     at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
 [java]     at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
 [java]     at org.apache.tools.ant.Main.runBuild(Main.java:809)
 [java]     at org.apache.tools.ant.Main.startAnt(Main.java:217)
 [java]     at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
 [java]     at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
 [java] Caused by: java.lang.ExceptionInInitializerError
 [java]     at java.lang.Class.forName0(Native Method)
 [java]     at java.lang.Class.forName(Class.java:266)
 [java]     at clojure.lang.RT.loadClassForName(RT.java:2056)
 [java]     at clojure.lang.RT.load(RT.java:419)
 [java]     at clojure.lang.RT.load(RT.java:400)
 [java]     at clojure.lang.RT.doInit(RT.java:436)
 [java]     at clojure.lang.RT.<clinit>(RT.java:318)
 [java]     at FooMain.main(FooMain.java:6)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 [java]     at java.lang.reflect.Method.invoke(Method.java:601)
 [java]     at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217)
 [java]     at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:152)
 [java]     ... 34 more
 [java] Caused by: java.lang.NumberFormatException: null
 [java]     at java.lang.Integer.parseInt(Integer.java:454)
 [java]     at java.lang.Integer.valueOf(Integer.java:582)
 [java]     at clojure.core$fn__6145.invoke(core.clj:6247)
 [java]     at clojure.core__init.load(Unknown Source)
 [java]     at clojure.core__init.<clinit>(Unknown Source)
 [java]     ... 48 more
 [java] Java Result: -1
Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331

2 Answers2

3

The exception you're seeing is thrown while the Clojure runtime is attempting to load the clojure.core namespace, before any of your code gets executed. Specifically, it appears that the exception is thrown while trying to parse a version number from the clojure/version.properties resource on the classpath.

  • Ensure that this resource does in fact exist.
  • Ensure that the resource is accessible from the classloader that you're using.
Alex
  • 13,811
  • 1
  • 37
  • 50
  • clojure/version.properties lives in clojure-1.4.0.jar which is on the classpath, should I by any chance need to go through the arcana of: http://stackoverflow.com/questions/13423048/why-does-clojure-use-the-context-classloader-by-default ? – Marcus Junius Brutus Jun 27 '13 at 20:08
  • 1
    You might - it could be that Clojure isn't playing very nicely with whatever classloader Ant is using. My first thought would be to add `Thread.currentThread().setContextClassLoader(RT.class.getClassLoader());` at the beginning of your method. Good luck - Clojure classloading issues are very difficult to track down in my experience. – Alex Jun 27 '13 at 21:01
  • You are right on the messed-up interplay between Clojure and Ant. Invoking it directly from the command line (not through Ant's `java` task) works fine and doesn't even need the `setContextClassLoader`. I can live with that. – Marcus Junius Brutus Jun 27 '13 at 22:01
  • I think I stumbled on the answer sometime later by accident. See my answer below. It indeed has to do with `version.properties` but is not a Clojure / Ant classloader thing. – Marcus Junius Brutus Oct 16 '13 at 16:03
0

I think I found the answer thanks to Alex's answer.

Both:

  • clojure-1.5.1.jar

    and

  • clojure-1.5.1-sources.jar

include a clojure/version.properties file. However, the one in clojure-1.5.1-sources.jar doesn't contain a parsable version, but instead has the following contents:

version=${version}

Simply removing clojure-1.5.1-sources.jar from the CLASSPATH (or, in my case setting the type="jar" in the <ivy:retrieve> Ant task) fixes the issue.

Community
  • 1
  • 1
Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331