views:

60

answers:

2

I am trying to go through the process of creating a jar file from a simple clojure file. Below is my clojure code:

(ns app.first (:gen-class))  
(refer 'clojure.core)  
(defn -main [& args] (println "this program worked!"))  

I am using these instructions to create the jar file: http://en.wikibooks.org/wiki/Clojure_Programming/Tutorials_and_Tips

I see the error "java.io.FileNotFoundException: Could not locate app/hello__init.class or app/hello.clj on classpath: (NO_SOURCE_FILE:0)" when I try to complete the (compile 'app.first) step.

The only difference between my attempt and the link is the name of my file (first.clj instead of hello.clj).

Can anyone see where I am going wrong? Or for that matter, all I want to do is learn how to create a jar from a clojure file, so if anyone knows of a better/easier way to do that, let me know.

+1  A: 

I'm rusty on this, but I heard about other people with similar problems.

I think it's helpful to remember that the classpath you indicate points to the root of your class tree, and package names end up creating subdirectories within that tree. Awkwardly stated, but I hope you get the idea. Thus, I think you need to do some kind of gymnastics with creating directories to match the "app.first" -> "/app/first" hierarchy.

Sorry, that's as close as I come to a sensible and useful answer. Hope this helps you.


EDIT:

The Prime Directive of Computer Science: It only works if you do everything right! I spent almost 10 minutes fiddling with this but was finally successful.

Here's what I needed to do to get your program to compile:

  • created a directory app, and within that, first.clj with your code.
  • checked for the *compile-path* by doing (pr *compile-path) within Clojure. It said "classes".
  • created a second directory classes parallel to app.
  • in the shell, did export CLASSPATH=.:./classes
  • in Clojure, did (compile 'app.first)

... and I found a bunch of class files in classes. JARring those should be a snap.

I found it very helpful to run (doc compile) because that reminded me of the requirement to have a directory to satisfy the requirement for a *compile-path*.

Carl Smotricz
i think you are correct. i have my directories set up per the link above. project/app and project/classes and my file sits at project/app/first.clj . i think the problem might be where i am running clojure from perhaps? i tried running it from within project... but it cant see the app/first.clj for some reason.
Toddeman
Answer edited to show the HowTo. But, having busted my butt on this exercise, I'm tempted to agree with @Alex Ott :) My personal preference, though, is to work with a Clojure-capable IDE. There are plugins for Eclipse, NetBeans and IntelliJ Idea. The latter is perhaps the "best."
Carl Smotricz
i will try this now. just tried leiningen... worked fine until very end. lein uberjar command threw error "java.lang.Exception: Name conflict, can't def first because namespace: user refers to:#'clojure.core/first (project.clj:1)" . PS: used this link for tutorial on leiningen http://github.com/technomancy/leiningen/blob/master/TUTORIAL.md
Toddeman
Excellent! You are now officially Alex' problem! :) Hehe, good luck! Plenty of friendly Clojurians hopefully around to help with any other questions coming up.
Carl Smotricz
just tried this after failing with leiningen too. again i fail at the compile step. it cant find app/first.clj in the classpath. i think i am failing all of these attempts for the same reason... sure wish i knew what it was :) does it matter where i create app? for instance when i run my REPL i call java -jar path/to/clojure.jar... does app have to be in the same dir as clojure.jar?
Toddeman
Sorry to hear this. Time for questions! Which version of Clojure are you using, i.e. is there some kind of version number in the jar name? And which operating system, Windows or Linux?
Carl Smotricz
+1  A: 

It's better to use Leiningen for such tasks - it allows to maintain dependencies, and packs all necessary components into jar file

Alex Ott
this worked well until the lein uberjar step. my biggest problem is (not coming from Java) i have trouble understanding the errors and exceptions being thrown. i followed this tutorial http://github.com/technomancy/leiningen/blob/master/TUTORIAL.md . i got this exception "java.lang.Exception: Name conflict, can't def first because namespace: user refers to:#'clojure.core/first (project.clj:1)" . any ideas?
Toddeman
i marked this as accepted bc i did end up using leiningen, but i thought i should answer my own question in the comment above as to how i finally got it to work. the project name can not match the class name (as in the linked tutorial). i had to make the project First (in the project.clj) and the ns call first.core in the first/core.clj file. hope that helps if anyone else has the same issue...
Toddeman
Actually that's not true, you must have had some other project layout problem... (In fact, I'd be interested to know what it looked like when you where getting your exception -- I'm struggling to guess where it could have come from.) As long as you put your original code in `src/app/first.clj` and add `:main app.first` in your `project.clj`, everything should work regardless of the project name. In particular, it will work perfectly fine if the project is itself called `app.first`.
Michał Marczyk
Michał answered before me - he is right, you need to have proper project layout and specify entry point for uberjar
Alex Ott