views:

78

answers:

1

This is a follow-up for this question.

After running 'lein jar', I get 'myproject-1.0.0-SNAPSHOT.jar', which doesn't contain the clojure-1.2.0-beta1.jar and clojure-contrib-1.2.0-beta1.jar.

And running 'lein uberjar' gives me two jar files. The first one (that ends with -standalone.jar) is the jar contains everything, and the second one is the same as the jar generated with 'lein jar'.

This is the question of the jar with the second one. There's no problem running with the first jar, as I explained in the previous post.

When I run

java -cp PATH_TO_THE_CLOJURE_AND_CONTRIB.jar:$CLASSPATH -jar myproject-1.0.0-SNAPSHOT.jar'

, I get the following error.

Caused by: java.lang.ClassNotFoundException: clojure.lang.IFn
        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)

What might be wrong, I thought I can use the 'myproject-1.0.0-SNAPSHOT.jar the same way with 'myproject-1.0.0-SNAPSHOT-standalone.jar' if I point to the jar files using -cp option.

Is there anything more that I had to do?

ADDED

java -cp ALLTHE_JAR_PATH myproject.core

solves the problem.

+2  A: 

If you're using Leiningen 1.2, you are probably being hit by a bug whereby dependencies would get deleted prior to the creation of an uberjar (obviously defeating the point of uberjar). Please either downgrade to 1.1 and wait for the new release (which should be arriving shortly) or use a checkout of lein's HEAD (as described in the section on hacking Leiningen in lein's README).

Once you do that, you should be able to produce a standalone jar with lein uberjar and say java -jar name-of-your-standalone.jar to launch your app.

As an alternative, you can create a regular jar with lein jar and say something like java -cp '$PROJECT_ROOT/lib/*:your-app.jar' your-app.main (where your-app.main is your application's main class; also, replace $PROJECT_ROOT with the appropriate path and supply a path to your-app.jar, of course). The lib/* thing will only work on JDK 1.6; with 1.5 you'd have to include every jar separately. Note that when using -jar, -cp and $CLASSPATH are ignored; only the classpath specified in the jar's manifest (if any) is taken into account.

Michał Marczyk
@Michał Marczyk : My uberjar works without any problem, I wanted to know why the jar that I get from 'lein jar' doesn't work with 'java -cp $PROJECT_ROOT/lib*' -jar your-app.jar. Did I have to put your-app.jar into the -cp? Then, what's the other command that I have to call?
prosseek
If you specify `-jar`, `-cp` is ignored (and so is `$CLASSPATH`). You'll have to use `-cp` and specify the main class by hand (if it's called `your-app.main`, say `java -cp ... your-app.main`, with any arguments to your `main` method (= the Clojure function `-main`) at the end). I should have noticed this reading the question... will edit it into the answer.
Michał Marczyk
Incidentally, if uberjar creates jars which do not include the contents of `clojure.jar` and `clojure-contrib.jar` for you, then it is not working without problem. Including the dependencies is the whole point of uberjar! (And it makes the use of `java -jar` possible.)
Michał Marczyk
Another workaround for the 1.2 bug is to include a :main namespace in project.clj; if you're building an uberjar for distribution, you probably want a -main function anyway. Including AOT in the process avoids the jar clearing bug.
technomancy
Ah, right. And I guess it's needed for `-jar` anyway. Thanks for pointing this out!
Michał Marczyk