I'm new to clojure. I have a jar file I want to play with in a clojure repl, but I've failed to do so with leiningen 2.
I have tried placing the jar file in src/myjar.jar and also in src/org/mydomain/myjar.jar
When I run lein repl I get errors stating that leiningen can not find my artifact, and a reference to a page about repeatability which I do not understand.
Here is my project.clj (with the real name of myjar)
(defproject cljliveordead "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.3.0"]
[org.allen.temporalintervalrelationships/time "0.2" :extension "jar"]])
You can use local jars using the lein-localrepo plugin. Add this line to your project.clj
:plugins [[lein-localrepo "0.4.0"]]
Then install the jar to the local repository using
lein localrepo install <path-to-jar> org.allen.temporalintervalrelationships/time 0.2
You can check that the file is installed by running lein localrepo list and check that lein can resolve the project dependencies using lein deps. If all is well then you can start playing with the jar using lein repl.
Leiningen doesn't like local jars due to its goal of repeatable builds. If this was a real project using a third party closed source jar then the best thing to do is install it in a local Nexus repository and add a reference to that repository to your project.
However, this all seems a bit heavyweight for what you are trying to achieve. If all you want to do is play with the jar in the REPL then create a simple project like this
(defproject clojure-time "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.4.0"]
[com.cemerick/pomegranate "0.0.13"]])
and use the pomegranate library to add the jar to your classpath manually
(require '[cemerick.pomegranate :as p])
(p/add-classpath "jsr-310-ri-0.6.3.jar")
(javax.time.Instant/now)
and play away.
the hackish way is to just put it into /proiject/path/lib/ and the 'proper' way is to:
add a dependency for it to your project
run lein deps which will print the command for installing the jar to your local maven repo
run the command leiningen gives you with the path to your jar
run lein deps again
I use clojure-csv in a lot of my applications, so make sure the modules referencing clojure-csv were able to build with it, this is what I did:
0) Ran lein new bene-csv
1) Added this to project.clj (after enter lein new bene-csv). The pertinent line is [clojure-csv/clojure-csv "1.3.2"], but it makes sense to show you the whole project.clj for good example's sake.
(defproject bene-csv "1.0.4-SNAPSHOT"
:description "A csv parsing library"
:dependencies [[org.clojure/clojure "1.3.0"]
[clojure-csv/clojure-csv "1.3.2"]
[util "1.0.2-SNAPSHOT"]]
:aot [bene-csv.core]
:omit-source true)
2) Made sure my bene-csv/src/bene_csv/core.clj references clojure-csv.
(ns bene-csv.core
^{:author "Charles M. Norton",
:doc "bene-csv is a small library to parse a .csv file.
Created on March 8, 2012"}
(:require [clojure.string :as cstr])
(:require [util.core :as utl])
(:use clojure-csv.core))
Finally, I ran these commands, so that my main project could reference bene-csv's functions and defs.
lein deps
lein install
Related
I have a project where I want certain parts of the code to be able to run on a local environment, and other parts which depend on libraries that only run on a remote environment. E.g.
src/app/core.clj <- can run anywhere
src/app/sandbox/remote_only.clj <- depnds on libs that only function in remote environ
where src/app/core.clj is
(ns app.core
(:gen-class))
(defn -main [] (println "Hello, World!"))
and src/app/sandbox/remote_only.clj is
(ns app.sandbox.remote-only
(:require
[uncomplicate.commons.core :refer [with-release]]
[uncomplicate.neanderthal
[native :refer [dv dge]]
[core :refer [mv mv!]]]))
I want to be able to uberjar and run the code located in core.clj on my local machine without pulling in remote_only.clj which will cause the program to fail locally. According to the docs, Leiningen should be able to accomplish this using profiles and uberjar exclusions e.g.:
(defproject app "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.10.1"]]
:profiles {:uberjar {:main app.core
:init-ns app.core
:aot :all}
:remote {:init-ns app.sandbox.remote_only
:dependencies [[uncomplicate/neanderthal "0.43.1"]]}} ; these deps will fail locally
:uberjar-exclusions [#".*sandbox.*"]
:repl-options {:init-ns app.core})
compiling the uberjar here will result in:
❯ lein uberjar
Compiling app.core
Compiling app.sandbox.remote-only
Syntax error macroexpanding at (remote_only.clj:1:1).
Execution error (FileNotFoundException) at app.sandbox.remote-only/loading (remote_only.clj:1).
Could not locate uncomplicate/commons/core__init.class, uncomplicate/commons/core.clj or uncomplicate/commons/core.cljc on classpath.
So, explicitly its trying to compile the class that was specifically excluded.
I thought that this kind of problem could be avoided by removing the :all tag from :aot compilation. E.g.:
(defproject app "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.10.1"]]
:profiles {:uberjar {:main app.core
:init-ns app.core
:aot [app.core]}
:remote {:init-ns app.sandbox.remote_only
:dependencies [[uncomplicate/neanderthal "0.43.1"]]}} ; these deps will fail locally
:uberjar-exclusions [#".*sandbox.*"]
:repl-options {:init-ns app.core})
which causes other problems:
❯ lein uberjar
Compiling app.core
Created /Users/warrenronsiek/Projects/app/target/app-0.1.0-SNAPSHOT.jar
Created /Users/warrenronsiek/Projects/app/target/app-0.1.0-SNAPSHOT-standalone.jar
~/Projects/app 5s 15:47:37
❯ java -jar ./target/app-0.1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
I've tried playing around with all kinds of :exclusions, :jar-exclusions and regexes. Variations of this question have been asked multiple times (1, 2) Nothing works.
How do I get Leiningen to compile uberjars and ignore the specified file(s)?
You are on the right track with changing :aot :all to :aot [app.core] but when you tried to run the JAR, you are running the library version instead of the whole application version:
java -jar ./target/app-0.1.0-SNAPSHOT.jar
That doesn't include Clojure or any dependencies. You want:
java -jar ./target/app-0.1.0-SNAPSHOT-standalone.jar
I haven't tried this particular setup with the "exclusions" features.
One workaround would be to create sub-projects for the "local" & "remote" parts of your app, which could then be used by a higher-level "total" project.
app
app-local
app-remote
where each of the 3 is a separate Lein project. app-local and app-remote could be developed in isolation. The top-level app project then uses has the 2 sub-projects as dependencies (and therefore only works in the remote/full environment).
The Lein feature checkouts allows you to develop in all 3 repos simultaneously, which is a huge help. It is much faster than the alternative of using lein install, which is slow, manual, repetitive, and error-prone.
P.S. Did you experiment with using lein jar instead of lein uberjar?
How to add the necessary jar file for the classpath used by the project?
The project.clj is copied below:
1 (defproject hbase01 "0.1.0-SNAPSHOT"
2 :description "FIXME: write description"
3 :url "http://example.com/FIXME"
4 :license {:name "Eclipse Public License"
5 :url "http://www.eclipse.org/legal/epl-v10.html"}
6 :dependencies [[org.clojure/clojure "1.6.0"]
7 [clojure-hbase "0.92.4"]])
At the REPL I tried:
user=> (require '[clojure-hbase.core :as hb])
and it answered back:
CompilerException java.lang.NoClassDefFoundError:
org/apache/hadoop/conf/Configuration, compiling:(clojure_hbase/core.clj:1:1)
I found one jar file /usr/local/hbase/lib/hadoop-common-2.2.0.jar where the class is an inner class... but how to add this path to the project?
I have read and tried the lein-localrepo but it did not get installed in the right location, the jar file get installed into the $username/.m2/repository/hadoop-common folder.
You may have already figured this out, but in case anyone else comes looking for this error. You need to include a jar from the Hadoop project with the Configuration class, as HBase has a dependency on it from what I've found.
I had this error with Clojure 1.6.0 and HBase 94.26.
My project.clj includes:
[org.apache.hbase/hbase "0.94.26"]
[org.apache.hadoop/hadoop-core "1.2.1"]
Just run lein deps and you're off to the races.
First thing to note here is that you have conflicting versions of clojure. You specify 1.6.0 and clojure-hbase still requires 1.5.1. This could probably cause the issue you're seeing.
This is a case of a failure to launch. Namely I am attempting to work through the Enlive tutorial, but have run into the following issue of FileNotFoundException while typing (load "tutorial/scrape1") into the REPL.
I am using the following dependencies
:dependencies [[org.clojure/clojure "1.5.1"]
[enlive "1.1.1"]]
I do the classic steps of lein deps then open the REPL and typing the aforementioned line as the tutorial asks. This is all part of the "Your First Scrape with Enlive..." section of https://github.com/swannodette/enlive-tutorial
Well that are not the only dependencies you need to add to your project.clj. This file needs to look like:
(defproject enlive-tutorial "0.1.0"
:description "Enlive Tutorial"
:dependencies [[org.clojure/clojure "1.5.1"]
[enlive "1.1.1"]
[ring "1.2.0"]
[net.cgrand/moustache "1.1.0"]])
So running lein deps will cause in a long term of downloading dependencies. After this you can just start with the tutorial as presented in the link you just posted.
Maybe it is a good idea just to clone the git repository and follow the instructions they give you to start coding with it:
1. git clone git://github.com/swannodette/enlive-tutorial.git
2. cd enlive-tutorial
3. lein deps
4. lein repl
I've just started with Clojure and have never used Java
I understood how to create and run a leiningen project from terminal, but I can't understand how to load libraries in REPL before running commands.
I'm trying to build a simple web scrapler with clj-webdriver; my original file looks like this
(ns prova.core (:gen-class))
(use 'clj-webdriver.taxi)
(set-driver! {:browser :firefox})
(defn -main
[& args]
(to "https://github.com/login")
(input-text "#login_field" "email")
(input-text "#password" "psw")
(click "input[name='commit']")
)
The closest I (think) have got to achieve it was going into the webdriver src folder and try this command
penta#laptop:~/clj-webdriver-master/src/clj_webdriver$ clojure
Clojure 1.4.0
user=> (use 'taxi)
but it returned
FileNotFoundException Could not locate taxi__init.class or taxi.clj on classpath: clojure.lang.RT.load (RT.java:432)
even thou in the same folder the file taxy.clj was indeed present.
So, what is the procedure to run a REPL that can make use of a library functions?
Many thanks
Take a look at the leiningen build tool, install it according to the website's instructions and make a new project.
lein new myproject
cd myproject
Then edit project.clj in which you add clj-webdriver as a dependency:
(defproject myproject "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.5.1"]
[clj-webdriver "0.6.0"]])
Then type lein repl and a REPL will spin up with clj-webdriver on the classpath. You should now be able to continue as you did in your example.
Here's my project.clj:
(defproject hello-world "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.3.0"]]
:dev-dependencies [[swank-clojure "1.5.0-SNAPSHOT"]]
:plugins [[lein-swank "1.4.3"]])
Leiningen downloads swank-clojure 1.4.0 every time I run lein swank.
(I'm using leiningen 1.7.0)
I don't think you need both the :plugins swank and the :dev-dependencies one.
try with just the dev-dependencies
Assuming you want to always use the same version of swank-clojure (which is also lein-swank),
you can run (for leiningen 1.x):
lein plugin install swank-clojure "1.5.0-SNAPSHOT"
For leiningen 2.x you can add the following to :plugins in the profile.clj file of your lein directory:
[lein-swank "1.5.0-SNAPSHOT"]
and the plugin will be usable from all of your leiningen projects without having to specify the requirement in the project file.