I checked possible duplicates for this question, and I didn't find one that answers my problem. Most of them stop at naming the .jar file or the maven repo. I need help on looking inside a local repo and its jar to import classes. The SO answers I found that address import don't address local repos.
Consider the following project.clj, noting the two lines I added to a fresh leiningen project I created via lein app sc-tester:
(defproject sc-tester "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[local/scxml "2.2.0"]] ;;; <<<---=== local jar reference
:main ^:skip-aot sc-tester.core
:target-path "target/%s"
:repositories [["local" "file:local-repo"]] ;;; <<<---=== local repo reference
:profiles {:uberjar {:aot :all}})
I created the local jar reference with the following command:
lein deploy local local/scxml 2.2.0 ~/Documents/commons-scxml/target/commons-scxml2-2.0-SNAPSHOT.jar
That command resulted in the following contents of local_repo:
local-repo/
`-- local
`-- scxml
|-- 2.2.0
| |-- scxml-2.2.0.jar
| |-- scxml-2.2.0.jar.md5
| `-- scxml-2.2.0.jar.sha1
|-- maven-metadata.xml
|-- maven-metadata.xml.md5
`-- maven-metadata.xml.sha1
A call of lein deps does not fail (but that's not the same as succeeding!):
lein deps :tree
[clojure-complete "0.2.4" :exclusions [[org.clojure/clojure]]]
[local/scxml "2.2.0"]
[org.clojure/clojure "1.8.0"]
[org.clojure/tools.nrepl "0.2.12" :exclusions [[org.clojure/clojure]]]
The jar file contains a bunch of classes; here is an excerpt with a few for context, including a couple, SCXML and SCXMLExecutor, I'd like to import:
$ jar tvf local-repo/local/scxml/2.2.0/scxml-2.2.0.jar
...
2275 Mon ... 2016 org/apache/commons/scxml2/model/Script.class
5857 Mon ... 2016 org/apache/commons/scxml2/model/SCXML.class
8963 Mon ... 2016 org/apache/commons/scxml2/model/Send.class
...
12466 Mon ... 2016 org/apache/commons/scxml2/SCXMLExecutionContext.class
11358 Mon ... 2016 org/apache/commons/scxml2/SCXMLExecutor.class
848 Mon ... 2016 org/apache/commons/scxml2/SCXMLExpressionException.class
...
Now I fire up a repl and start guessing how to name those classes in a call of import:
$ lein repl
nREPL server started on port 60765 on host 127.0.0.1 - nrepl://127.0.0.1:60765
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_101-b13
...
sc-tester.core=> (import 'local/scxml.SCXML)
ClassNotFoundException scxml.SCXML java.net.URLClassLoader.findClass
(URLClassLoader.java:381)
sc-tester.core=> (import 'local/scxml/org/apache/commons/scxml2/model/SCXML)
ClassNotFoundException scxml/org/apache/commons/scxml2/model/SCXML
java.lang.Class.forName0 (Class.java:-2)
Hmmm. A different kind of error, but still no help in figuring out the right answer. Let's try a dot in a random place instead of a slash:
sc-tester.core=> (import 'local/scxml.org/apache/commons/scxml2/model/SCXML)
ClassNotFoundException scxml.org/apache/commons/scxml2/model/SCXML
java.lang.Class.forName0 (Class.java:-2)
Let's try almost-all-dots:
sc-tester.core=> (import 'local/scxml.org.apache.commons.scxml2.model.SCXML)
ClassNotFoundException scxml.org.apache.commons.scxml2.model.SCXML
java.net.URLClassLoader.findClass (URLClassLoader.java:381)
Let's try snipping off the name of the repo:
sc-tester.core=> (import 'org/apache/commons/scxml2/model/SCXML)
ClassNotFoundException apache/commons/scxml2/model/SCXML
java.lang.Class.forName0 (Class.java:-2)
etc. etc. etc. (tried many permutations and guesses).
Questions:
Did I set up the local repo correctly, in other words, is it even possible to name the classes correctly in a call of import with my set-up?
If so, how can I import the java classes into Clojure? What's the right syntax for naming these beasts?
You should be able to import classes from any jar on your classpath using just the classname and package:
(import 'org.apache.commons.scxml2.model.SCXML)
If that doesn't work, the jar is not on your classpath and you should fix that first.
Related
I am trying to run datomic's in-memory database with this tutorial https://clojureverse.org/t/a-quick-way-to-start-experimenting-with-datomic/5004 with the free version. I downloaded the .zip file and put it in program files. Then I created a project with leiningen and I did the other steps indicated in the tutorial, but when I want to evaluate the lines with the repl for creating the database and connection it throws:
"Error:
Syntax error compiling at (c:\Users\usuario\Desktop\clojure\datomic-shortcut\src\datomic_shortcut\core.clj:7:3).
No such namespace: d"
... and when I evaluate the entire file, the following:
Evaluating file: core.clj
Syntax error (FileNotFoundException) compiling at (c:\Users\usuario\Desktop\clojure\datomic-shortcut\src\datomic_shortcut\core.clj:1:1).
Could not locate datomic/api__init.class, datomic/api.clj or datomic/api.cljc on classpath.
Evaluation of file core.clj failed: class clojure.lang.Compiler$CompilerException
When checking the .m2 folder there is no datomic's dependency, even after trying 'lein deps'
I think it can be solved with lein pom/jar/install sequence but I dont find where or I dont know how to download the .jar file.
Any help or information is welcome.. thanks!
-------------EDIT--------------------
Im sorry, the .m2 folder contains the ...m2\repository\com\datomic\datomic-free\0.9.5697\datomic-free-0.9.5697.jar file indeed.
No errors with 'lein deps'
My project.clj:
(defproject datomic-shortcut "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.10.1"]
[com.datomic/datomic-free "0.9.5697"]]
:source-paths ["src"]
:repl-options {:init-ns datomic-shortcut.core})
My core.clj:
(ns datomic-shortcut.core
(:require [datomic.api :as d]))
(def db-uri "datomic:mem://foo")
(comment
(d/create-database db-uri)
(def conn (d/connect db-uri)))
I realized the classpath hasn't the .jar file in it.
C:\Users\usuario\Desktop\clojure\datomic-shortcut>lein classpath
=>
C:\Users\usuario\Desktop\clojure\datomic-shortcut\test;
C:\Users\usuario\Desktop\clojure\datomic-shortcut\src;
C:\Users\usuario\Desktop\clojure\datomic-shortcut\dev-resources;
C:\Users\usuario\Desktop\clojure\datomic-shortcut\resources;
C:\Users\usuario\Desktop\clojure\datomic-shortcut\target\classes;
C:\Users\usuario\.m2\repository\com\datomic\datomic-lucene-core\3.3.0\datomic-lucene-core-3.3.0.jar;
C:\Users\usuario\.m2\repository\com\google\guava\guava\18.0\guava-18.0.jar;
C:\Users\usuario\.m2\repository\com\h2database\h2\1.3.171\h2-1.3.171.jar;
C:\Users\usuario\.m2\repository\org\apache\activemq\artemis-commons\1.4.0\artemis-commons-1.4.0.jar;
C:\Users\usuario\.m2\repository\nrepl\nrepl\0.6.0\nrepl-0.6.0.jar;
C:\Users\usuario\.m2\repository\org\apache\tomcat\tomcat-juli\7.0.27\tomcat-juli-7.0.27.jar;
C:\Users\usuario\.m2\repository\clojure-complete\clojure-complete\0.2.5\clojure-complete-0.2.5.jar;
C:\Users\usuario\.m2\repository\org\slf4j\jul-to-slf4j\1.7.7\jul-to-slf4j-1.7.7.jar;
C:\Users\usuario\.m2\repository\leinjacker\leinjacker\0.4.1\leinjacker-0.4.1.jar;
C:\Users\usuario\.m2\repository\org\jboss\logging\jboss-logging\3.3.0.Final\jboss-logging-3.3.0.Final.jar;
C:\Users\usuario\.m2\repository\org\slf4j\jcl-over-slf4j\1.7.7\jcl-over-slf4j-1.7.7.jar;
C:\Users\usuario\.m2\repository\org\clojure\core.contracts\0.0.1\core.contracts-0.0.1.jar;
C:\Users\usuario\.m2\repository\org\codehaus\janino\commons-compiler\2.6.1\commons-compiler-2.6.1.jar;
C:\Users\usuario\.m2\repository\com\datomic\datomic-free\0.9.5697\datomic-free-0.9.5697.jar;
C:\Users\usuario\.m2\repository\org\clojure\core.unify\0.5.3\core.unify-0.5.3.jar;
C:\Users\usuario\.m2\repository\org\apache\johnzon\johnzon-core\0.9.4\johnzon-core-0.9.4.jar;
C:\Users\usuario\.m2\repository\commons-beanutils\commons-beanutils\1.9.2\commons-beanutils-1.9.2.jar;
C:\Users\usuario\.m2\repository\org\slf4j\log4j-over-slf4j\1.7.7\log4j-over-slf4j-1.7.7.jar;
C:\Users\usuario\.m2\repository\useful\useful\0.8.5-alpha2\useful-0.8.5-alpha2.jar;
C:\Users\usuario\.m2\repository\org\slf4j\slf4j-nop\1.7.7\slf4j-nop-1.7.7.jar;
C:\Users\usuario\.m2\repository\commons-collections\commons-collections\3.2.1\commons-collections-3.2.1.jar;
C:\Users\usuario\.m2\repository\org\clojure\tools.cli\0.3.5\tools.cli-0.3.5.jar;
C:\Users\usuario\.m2\repository\lein-datomic\lein-datomic\0.2.0\lein-datomic-0.2.0.jar;
C:\Users\usuario\.m2\repository\org\fressian\fressian\0.6.5\fressian-0.6.5.jar;
C:\Users\usuario\.m2\repository\org\apache\geronimo\specs\geronimo-json_1.0_spec\1.0-alpha-1\geronimo-json_1.0_spec-1.0-alpha-1.jar;
C:\Users\usuario\.m2\repository\me\raynes\conch\0.4.0\conch-0.4.0.jar;
C:\Users\usuario\.m2\repository\org\apache\activemq\artemis-core-client\1.4.0\artemis-core-client-1.4.0.jar;
C:\Users\usuario\.m2\repository\org\slf4j\slf4j-api\1.7.7\slf4j-api-1.7.7.jar;
C:\Users\usuario\.m2\repository\org\clojure\clojure\1.10.1\clojure-1.10.1.jar;
C:\Users\usuario\.m2\repository\io\netty\netty-all\4.0.39.Final\netty-all-4.0.39.Final.jar;
C:\Users\usuario\.m2\repository\org\clojure\core.specs.alpha\0.2.44\core.specs.alpha-0.2.44.jar;
C:\Users\usuario\.m2\repository\org\codehaus\janino\commons-compiler-jdk\2.6.1\commons-compiler-jdk-2.6.1.jar;
C:\Users\usuario\.m2\repository\org\clojure\tools.macro\0.1.1\tools.macro-0.1.1.jar;
C:\Users\usuario\.m2\repository\org\apache\tomcat\tomcat-jdbc\7.0.27\tomcat-jdbc-7.0.27.jar;
C:\Users\usuario\.m2\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;
C:\Users\usuario\.m2\repository\org\clojure\spec.alpha\0.2.176\spec.alpha-0.2.176.jar
So then I tried:
C:\Users\usuario\Desktop\clojure\datomic-shortcut>java -cp C:/Users/usuario/.m2/repository/com/datomic/datomic-free/0.9.5697/datomic-free-0.9.5697.jar clojure.main
Error: no se ha encontrado o cargado la clase principal clojure.main
I am trying my first run with ring and lein, and I am facing problems in getting it to run. I have taken this example from the book "Web development with Clojure", chapter 1, and also from https://quickleft.com/blog/your-first-clojure-web-app/ . The code from both these sites give me the same error - Class Not Found.
I have the following project.clj
(defproject myfirstwebapp "0.1.1"
:description "A hello world for a Ring based web app"
:dependencies [[org.clojure/clojure "1.8.0"]
[ring "1.4.0"]]
:plugins [[lein-ring "0.9.7"]]
:dev-dependencies [[lein-ring "0.9.7"]]
:ring {:handler myfirstwebapp.core/app})
And the following core.clj
(ns myfirstwebapp.core)
(defn app [req]
{:status 200
:headers {"content-Type" "text/html"}
:body "Hello World!"})
And the commands I ran were these:
lein new myfirstwebapp
edit project.clj as above
cd myfirstwebapp
lein deps
edit src/myfirstwebapp/core.clj as above
lein ring server
And now I am getting errors like:
Exception in thread "main" java.lang.ClassNotFoundException: leiningen.core.project$reduce_repo_step, compiling:(C:\Users\ROG\form-init7789757414629005682.clj:1:17608)
Is there some mismatch between the versions of different components that I am using? Or something else?
It is a bug in lein 2.6.0. Fixed in 2.6.1
I spent some time last night messing with my leinigen profiles.clj to get rid of all the errors that were being printed when starting cider in my project. Today I went to start a repl from the terminal (I like to keep one open while I work) but it didn't work. I thought it was a cider issue so I tried it from Emacs but even in Emacs if I'm not in a project the repl won't start.
Here's the error:
Error loading refactor-nrepl.middleware: clojure.lang.ArityException: Wrong number of args (4) passed to: StringReader, compiling:(abnf.clj:186:28)
Exception in thread "Thread-4" java.lang.RuntimeException: Unable to resolve var: refactor-nrepl.middleware/wrap-refactor in this context, compiling:(NO_SOURCE_PATH:0:0)
...
Caused by: java.lang.RuntimeException: Unable to resolve var: refactor-nrepl.middleware/wrap-refactor in this context
My ~/.lein/profiles.clj
{:user {:plugins [[lein-try "0.4.3"]
[refactor-nrepl "1.1.0"]
[cider/cider-nrepl "0.9.1"]]
:dependencies [[org.clojure/tools.nrepl "0.2.12"]
[acyclic/squiggly-clojure "0.1.4"]
^:replace [org.clojure/tools.nrepl "0.2.12"]
[refactor-nrepl "1.1.0"]]}}
The versions of things when cider starts in a project
; CIDER 0.9.1 (Java 1.8.0_45, Clojure 1.7.0, nREPL 0.2.12)
I'm still pretty new to Clojure, Leinigen, Emacs, etc so I'm not sure why everything above made made my cider errors go away but it did. The cider errors I was getting were having to do with the nrepl version being too low and not having certain things installed (like refactor-nrepl).
When starting a repl from lein using lein repl, it really wants to run in a lein project dir. I keep an empty lein project named clj around in my home dir for this purpose. That way, my common dependencies are already there in the project.clj file, and lein is pre-configured just the way I like it.
You can start lein repl in an empty dir, but you get 10-20 error messages each time before it starts.
Another way is to use the plain repl built into the clojure jar file:
~/dummy > cp /home/alan/.m2/repository/org/clojure/clojure/1.8.0-RC1/clojure-1.8.0-RC1.jar .
~/dummy > d *
-rw-rw-r-- 1 alan alan 3935726 Nov 19 14:11 clojure-1.8.0-RC1.jar
~/dummy > java -jar clojure-1.8.0-RC1.jar
Clojure 1.8.0-RC1
user=>
As you can see, I created an empty directory named dummy and copied in the clojure-*.jar file. You can then run it with the syntax java -jar xxx.jar and it will fire up a repl completely independently of lein.
I also just keep a scratch project which I use for quick/simple repl sessions. There is a lien-oneoff plugin which is supposed to make it easy to work with simple single file lein projects which might be useful.
The other thing you could do is setup a boot config for basically getting a repl up to work with
what is your lein version, I am use 2.5.3, I can start lein repl anywhere.
Shell:~ >: lein repl
nREPL server started on port 52343 on host 127.0.0.1 - nrepl://127.0.0.1:52343
REPL-y 0.3.7, nREPL 0.2.10
Clojure 1.7.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_60-b27
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> Bye for now!
Shell:~ >: lein version
Leiningen 2.5.3 on Java 1.8.0_60 Java HotSpot(TM) 64-Bit Server VM
Shell:~ >: cat .lein/profiles.clj
{:1.2 {:dependencies [[org.clojure/clojure "1.2.0"]]}
:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]}
:1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]}
:user {:plugins [[lein-immutant "2.0.0-alpha2"]
[lein-clojars "0.9.1"]
[lein-ancient "0.5.5"]
[lein-kibit "0.0.8"]
[lein-try "0.4.3"]
[venantius/ultra "0.2.0"]]
:ultra {:color-scheme :solarized_dark}}}
I'm trying to build the hello-world example for compojure and it's failing to start the ring task.
$ lein version
Leiningen 1.7.1 on Java 1.7.0_65 OpenJDK 64-Bit Server VM
$ lein new compojure test
Created new project in: /home/myaccount/test
Look over project.clj and start coding in compojure/core.clj
$ cd test/
$ lein ring server
That's not a task. Use "lein help" to list all tasks.
I've also tried using the hello-world on the luminous site, which also says it can't find that task or other examples, where lein complains that I'm using the wrong number of arguments even if I pull the line straight from their tutorial.
$ lein new luminus guestbook +h2
Wrong number of arguments to new task.
Expected ([project-name] [project-name project-dir])
I quess you are missing the ring and compjure plugins in the project.clj file:
(defproject compojure "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.3.0"]]
:plugins [[lein-ring "0.8.8"]
[compojure "1.1.6"]]
;; once you have the above, you'll see that you need
;; to configure ring. This is the most simple example:
:ring {:handler compojure.core/handler})
Of course you have to define a handler function in src/compojure/core.clj! See here or here for a very nice introduction.
I've been trying to follow a number of tutorials on building a web app in Clojure, but I keep running into the same problem. To take the simplest case, I tried following this tutorial: http://drtom.ch/posts/2012-12-10/An_Introduction_to_Webprogramming_in_Clojure_-_Ring_and_Middleware/
When I get to the step that starts the server (run-jetty handler {:port 8383}), I get the following error:
NoSuchMethodError org.slf4j.helpers.MessageFormatter.arrayFormat(Ljava/lang/String;[Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple; org.eclipse.jetty.util.log.JettyAwareLogger.log (JettyAwareLogger.java:613)
I asked lien to show me the classpath, and sure enough, org.slf4j.helpers.MessageFormatter isn't in there anywhere.
I've run into this on pretty much every ring-based web tutorial I've tried, so either I've got something configured weird (I updated and reinstalled lein, blew away my ~/.m2 and rebuilt, etc), or something has changed in the myriad dependencies that get put together to make the classpath.
Any ideas what's going on here?
EDIT
I've got further information -- I created a VM in virtualbox, installed OpenJDK and lein, and created a project there. It worked fine. Since I had created it in a directory shared with the host, I then tried doing "lein ring server" in the same directory from the host, and it failed with the above error.
So I did "lein classpath" both in the vm and in the host and compared the results -- they're identical. I also checked that they're running the same build of the same JVM (OpenJDK 64-bit build 24.51-b03).
So, if they're running the same JVM with identical classpaths, what's left?
Can you try updating the dependencies like the following?
(defproject ..........
:dependencies [[org.clojure/clojure "1.5.1"]
[ring/ring-core "1.1.8"]
[ring/ring-jetty-adapter "1.1.8"]
[compojure "1.1.3"]]
:main quickstart.core
:min-lein-version "2.0.0"
:plugins [[lein-ring "0.8.10"]]
:ring {:handler quickstart.core/handler})
If you use the lein ring plugin as configured above, you can start the application like:
lein ring server