I'm working through "Clojure in Action", and I have been instructed to create a file "in a folder named chapter08 within your source directory" and try to require it.
I created the following files (tried both - and _ delimited)
~/clojure-1.4.0$ ls src/chapter08/
date-operations-spec.clj date_operations.clj
date-operations.clj date_operations_spec.clj
I tried to require in the REPL using code from the book, but keep failing:
~/clojure-1.4.0$ java -cp clojure-1.4.0.jar clojure.main
Clojure 1.4.0
user=>
(ns chapter08.date-operations-spec
(:use chapter08.date-operations)
(:use clojure.test))
FileNotFoundException Could not locate chapter08/date_operations__init.class or chapter08/date_operations.clj on classpath: clojure.lang.RT.load (RT.java:432)
use leiningen which has become the ubiquitous tool for managing such things since Amit published that excellent book. I just spent longer writing this than the time required to setup leiningen.
then run lein new chapter8.
copy the file to chapter8/src/chapter8/
Run lein repl
Using plain java to start clojure is a pain in the neck. For instance, your java -cp ... call will not put ./src on the classpath . Please just use leiningen.
Related
I am using lein repl without a project so there is no project.clj.
I am running Leiningen 2.8.1 on Java 1.8.0_191 OpenJDK 64-Bit Server VM.
When I require a Clojure dependency that I assume should just work - like clojure.data.json - I notice that it is not in my .m2 directory. Is that why I am getting a FileNotFoundException Could not locate clojure/data/json__init.class or clojure/data/js
on.clj on classpath? I can't find my other Clojure dependencies there either so I don't know where they reside and if this dependancy should be in .m2 or not.
I understand the error message but without knowing its location or even knowing how to properly add it to the CLASSPATH for the REPL to see it, I remain stuck.
Is this a dependency that I still need to install? If so, how do I install it without going through a project?
I don't understand the JVM as I am new to it, so add a little extra information in your answer.
I have looked at this, this, this, this and this. I don't know if I am overlooking anything so your help will really be appreciated.
I am using lein run without a project so there is no project.clj.
If you're using Leiningen, this'll be much easier if you create a project.clj file that declares your dependencies. Leiningen will read project.clj and handle fetching any missing dependencies to your local Maven repository, and add them to your classpath when you start your REPL/application. (lein run doesn't work for me in a directory without a project.clj; I get an error: No :main namespace specified in project.clj.. Did you mean lein repl?)
When I require a Clojure dependency that I assume should just work - like clojure.data.json - I notice that it is not in my .m2 directory.
clojure.data.json doesn't ship with Clojure — it's a separate dependency that must be fetched and added to your classpath in order to use it. The classpath tells the JVM where to look when it loads class files. Leiningen will do both of these things for you if you declare the dependency in project.clj:
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/data.json "0.2.6"]]
You can also use the lein deps command if you only want to fetch dependencies.
You can create a new/blank Leiningen project with lein new project_name_goes_here. It will have a project.clj with a few boilerplate entries and a :dependencies key where you can declare dependencies.
I understand the error message but without knowing its location or even knowing how to properly add it to the CLASSPATH for the REPL to see it, I remain stuck. Is this a dependency that I still need to install? If so, how do I install it without going through a project?
You could manually download it from the internet, then manually add its path to your classpath, but if you're already using Leiningen it's much easier to add a line to a project.clj file and have Leiningen handle this for you.
If using a project.clj file w/Leiningen isn't an option, there are other ways to use Clojure and resolve dependencies/build a classpath at runtime. Boot accommodates this workflow, you can use Leiningen like this with a little added effort, as well as the newer tools.deps tooling. There are examples of each in this ClojureVerse thread, but note that some of these approaches are doing essentially the same thing as declaring the dependency in a file — instead declaring them as CLI arguments.
For example, using Clojure CLI tooling:
$ clj -Sdeps "{:deps {org.clojure/data.json {:mvn/version \"0.2.6\"}}}"
Clojure 1.9.0
user=> (require '[clojure.data.json :as json])
nil
user=> (json/write-str {:foo "bar"})
"{\"foo\":\"bar\"}"
user=> (System/getProperty "java.class.path")
"src:
/Users/me/.m2/repository/org/clojure/clojure/1.9.0/clojure-1.9.0.jar:
/Users/me/.m2/repository/org/clojure/data.json/0.2.6/data.json-0.2.6.jar:
/Users/me/.m2/repository/org/clojure/spec.alpha/0.1.143/spec.alpha-0.1.143.jar:
/Users/me/.m2/repository/org/clojure/core.specs.alpha/0.1.24/core.specs.alpha-0.1.24.jar"
You could create a deps.edn file containing {:deps {org.clojure/data.json {:mvn/version \"0.2.6\"}}} in the same directory, and clj would read that, resolve the dependencies if necessary, and build the classpath accordingly.
This is a great opportunity to use lein try. Once you add it to your ~/.lein/profiles.clj, you'd simply run: lein try org.clojure/data.json and you'll be greeted with a running REPL with that dependency just a require away.
I am reading the documention on clojure.org about compilation, the last part gen-class examples. I do the examples and then when trying to run it as java app with: java -cp ./classes:clojure.jar clojure.examples.hello Fred in the terminal i get : Error: Could not find or load main class clojure.examples.hello. Can someone help?
Can someone introduce where to learn about gen-class and :gen-class, i find not much documentation on web
The command java -cp ./classes:clojure.jar tst.core from your base+system+user+dave is almost correct. The java.lang.NoClassDefFoundError: clojure/lang/IFn error is because the JVM cannot find the Clojure classes as there is no clojure.jar file in the base+system+user+dave directory, so you need to specify the correct path for the clojure.jar file.
As you are using lein, it downloads your project dependencies to your local repository. One of the dependencies will be Clojure itself, so assuming you are on iOS/Linux and that your lein project.clj has a dependency with clojure 1.7.0, the command to run from the base+system+user+dave directory will be:
java -cp ./classes:~/.m2/repository/org/clojure/clojure/1.7.0/clojure-1.7.0.jar tst.core
As this gets quite annoying once you have more than one dependency, I would suggest to use lein uberjar that will create a file in the target directory called your-project-name-standalone.jar that will have all required classes, so to run it from the command line go to the target directory and run something like :
java -cp tst-standalone.jar tst.core
To understand more about how the classpath works in the JVM, you can start with Wikipedia
I'm trying out clojure on my second day and I don't understand almost anything yet. I am working with the Programming Clojure 2nd ed. and I am stuck with libraries.
I have Leiningen and have the REPL running. The book first tells the reader to run a simple
(require 'clojure.java.io)
which works just fine (I get a nil). Then it wants to load a file called introduction.clj by running another simple
(require 'examples.introduction)
where I get an error message
FileNotFoundException Could not locate clojure/java/introduction__init.class
or clojure/java/introduction.clj on classpath: clojure.lang.RT.load (RT.java:432)
I downloaded the introduction.clj file and looked where should I place it. The error and the book says the command will search in my classpath, but I have no idea where or what that is (after 1h of searching and reading I still don't get it, sorry). I ran a few commands and I had many classpaths listed (from which none contain a clojure/java/io.clj).
So I tried another approach - find the io.clj file on my disk and simply copy the file there and run it with a command
(require 'clojure.java.introduction)
This doesn't seem to work either. By the way, the io.clj file I found was in "C:\Program Files\clojure\src\clj\clojure\java". I tried running several other .clj files from the java folder as well from the clojure folder, like javadoc.clj or inspector.clj and all seem to work just fine with the above mentioned command. Only the new file doesn't seem to load this way.
Any help appreciated :)
Clojure runs on the Java Virtual Machine, so you will need to learn a bit about PATH and CLASSPATH concepts:
See: http://docs.oracle.com/javase/tutorial/essential/environment/paths.html
Regarding the error message, the Clojure runtime is expecting to find introduction.clj in the directory clojure\java\example\introduction.clj (not where it really should be - see below).
The convention for Clojure namespaces is that the last component is the file name, while any previous components are parent directories. So
clojure.java.introduction
would have to be in the directory (relative to your source "root" or classpath)
clojure\java\introduction.clj
(The lein REPL automatically adds your source root to the classpath).
Another concept you need to understand is where the "root" of your source code is located. For Leiningen (the build tool you are using) the default is either "src" or "src/main/clojure" - as documented in the Leiningen sample project file on GitHub).
Finally, if you get really stuck, it seems the complete project for the book is available on GitHub.
Looking at the project, I see that you should actually be placing the file under src\examples\introduction.clj
Are you reading the book "Programming Clojure"?
I have encountered the same problem. It ban be sovled as follows:
If you start clojure by java:
I work in windows, the clojure.jar is placed in D:\backup\clojure-1.5.1, and the source code of the book "Programming Clojure" is placed in D:\study\clojure\shcloj-code\code. You should first delete the user.clj file in folder D:\study\clojure\shcloj-code\code.
java -cp d:\backup\clojure-1.5.1\clojure-1.5.1.jar;d:\study\clojure\shcloj-code\code clojure.main -r
If you work in linux, replace the ";" with ":"
If you start clojure by lein
You should first cd to the D:\study\clojure\shcloj-code\code folder, and then
lein repl
You should also delete the user.clj file in folder D:\study\clojure\shcloj-code\code.
I have a plain project structure:
Base Dir
src ;; Pile of Clojure files
lib ;; Jar files
To export the classpath:
$ export CLASSPATH=$CLASSPATH:src:lib/*
Trying to run a Clojure file:
java -cp $CLASSPATH -jar lib/clojure.jar src/wizard-game.clj
But I got:
Exception in thread "main" java.io.FileNotFoundException: Could not locate clojure/contrib/trace_init.class or clojure/contrib/trace.clj on classpath:
Caused by: java.io.FileNotFoundException: Could not locate clojure/contrib/trace_init.class or clojure/contrib/trace.clj on classpath:
Ok, this is a classpath issue but what/where I'm doing wrong?
Is there a better way to try to run it?
UPDATE:
I tried this command:
java -classpath $CLASSPATH clojure.main src/wizard-game.clj
It runs ok now.
From the java man pages regarding the -jar option:
When you use this option, the JAR file
is the source of all user classes, and
other user class path settings are
ignored.
So that's a bit of a bummer, but the good news is that you can get around this by using a different launching syntax (referenced at clojure.org):
java -cp $CLASSPATH clojure.main src/wizard-game.clj
Alternatively, use a tool like Leiningen to manage your project's classpath and dependencies for you!
This is a response to your "How to run a standalone Clojure file in Lein?" you should look at into lein run. I'm not sure the current state but there was a standalone Lein plugin and now there is at least some (maybe all) of the functionality build into lein by default.
Try running a lein help run at the command line for a quick introduction.
Standalone lein-run project. Documentation may be useful. Not 100% sure if it matches up with the built-in lein run but I know from my own usage at least some of it does.
https://github.com/sids/lein-run
For some reason I can't get clojure REPL working with jline, what i did was git clone the clojure repository off github then run ant to build it, then i download jline-0.9.94.jar to the directory with clojure.jar, then run the following command:
java -cp jline-0.9.94.jar:clojure.jar jline.ConsoleRunner clojure.main
And get the following errors:
Exception in thread "main" java.lang.ClassNotFoundException: clojure.main
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:317)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:375)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at jline.ConsoleRunner.main(Unknown Source)
Here are the files in my current directory:
vvshs-macbook-2:clojure vvsh$ ls
build.xml clojure-sources-1.2.0-master-SNAPSHOT.jar epl-v10.html src
classes clojure-sources.jar jline-0.9.94.jar test
clojure-1.2.0-master-SNAPSHOT.jar clojure.iml pom-template.xml
clojure-slim-1.2.0-master-SNAPSHOT.jar clojure.jar pom.xml
clojure-slim.jar doc readme.txt
vvshs-macbook-2:clojure vvsh$
I got the same error on clojure 1.1 and lein repl(it seems lein maintain its own version of clojure).
By the way, this is on mac ox 10.5.8
java version "1.5.0_24"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_24-b02-357-9M3165)
Java HotSpot(TM) Client VM (build 1.5.0_24-149, mixed mode, sharing)
Anybody know what's wrong and how to fix it? As I really want to get lein repl working to start a project.
I solved the same problem today by removing a redundant jline*.jar from /Library/Java/Extensions, leaving just one jline installation in CLASSPATH.
Longer explanation: I was trying to build labrepl, which installs all its dependencies in subdirectory lib, but I had previously set up jline by copying the .jar file to /Library/Java/Extensions. Apparently, java.lang.ClassLoader couldn't handle two installations of jline, and as long as there were ones available in two places, the command line starting a Clojure REPL would fail finding the latter one of classes jline.ConsoleRunner and clojure.main, depending on the order they were given to the java command.
I hope this helps.
see my alternative instructions for install on my fork:
http://github.com/jedschneider/leiningen
I sent a pull request to update the readme, but didn't get a response on it. once you have lein installed, you can put the bin/leiningen.sh in your ~/bin and call it anywhere. i put a shortcut on my .bash_profile
alias lein="~/bin/leiningen.sh"
and then call lein repl to launch a shell
also checkout the labrepl which is a great learning tool.
http://github.com/relevance/labrepl
Your java ... command looks fine, I'd double check if all the jars are where you think they should be (and that they are the jars you think they are, i.e. clojure.jar is actually the one you built locally and not some super-outdated one).
If you want to use Leiningen for lein repl, that's possible too. Note that it isn't accurate to say that it "maintains its own version of Clojure"; Leiningen is a build tool, used as part of a project-oriented workflow, and the separate Clojure jars are project-specific. To create a sample project to play around in, say lein new foo someplace convenient. Then you'll need to cd foo, get your Clojure & contrib jars with lein deps (the project.clj skeleton provided by lein new already contains entries for both) and start a REPL with lein repl.
Finally, you could use the new cljr project; it has a comprehensive README which should get you started in no time, and with it you'll be able to say cljr repl to get a Clojure REPL anywhere, without the need to create a "project".
I met the same problem. jline.ConsoleRunner (at least about jline-0.9.5 which I use) seems not to be able to find class files in the path added to class search paths from -cp option of 'java' command. It means it can't find neither classes in your current directory. I solved this by copying clojure.main under /Library/Java/Extensions/ too.