Classpath issue in leinigen - clojure

I've been striving to build a standalone .jar with leiningen. Though having gone through the examples on github and Alex Ott's Website and some related questions, I couldn't figure out how to correctly set up the project. After doing lein uberjar in the project it complains
Could not locate clojure/contrib/string__init.class or clojure/contrib/string.clj on classpath: (collision.clj:1)
My project directory looks like
.
├── classes
├── lib
│   ├── clojure-1.2.1.jar
│   └── clojure-contrib-1.1.0.jar
├── project.clj
└── src
   └── collision
   └── collision.clj
My project.clj:
(defproject collision "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.1.0"]]
:main collision.collision)
collision.clj:
(ns collision.collision
(:require
clojure.set
clojure.string
[clojure.contrib.string :as st]
[clojure.contrib.str-utils :as su]
[clojure.contrib.combinatorics :as cmbn]))
... defns ...
(defn -main []
(...))
(-main)
The code works on the REPL. How do I tell leiningen where to to find clojure-contrib-1.1.0.jar? I'm not a Java programmer and not really accustomed to the classpath issue; quick and dirty help is much appreciated.

try using [org.clojure/clojure-contrib "1.2.0"] instead [org.clojure/clojure-contrib "1.1.0"]
in the version 1.1.0 not exist the namespace clojure.contrib.string

Related

Leiningen not finding extra test files (CIDER does)

I have checked the referenced questions, and I am still puzzled. I have some tests that work in CIDER in emacs, but not via lein test. I need to make them work in lein test.
I have the following source layout in a Clojure project:
ClojureProjects002/asr (master ✖ ✹ ✭)──>
tree src
src
├── asr
│   ├── arithmetic.clj
│   ├── asr.clj
... many files ...
│   ├── core.clj <~~~~~~~ notice this one
... more files ...
│   └── utils.clj
└── stack_machine <~~~~~~~ notice underscore
└── stack.clj
5 directories, 23 files
ClojureProjects002/asr (master ✖ ✹ ✭)──>
tree test
test
├── asr
│   └── core_test.clj <~~~~~~~ this one works in lein
└── stack_machine <~~~~~~~ this one doesn't
└── sm_test.clj <~~~~~~~ notice underscores
The files src/stack_machine/stack.clj and test/stack_machine/sm_test.clj follow here:
stack.clj:
(ns stack-machine.stack ;; <~~~~~~~ notice dash
(:import java.util.concurrent.Executors))
;;; blah blah blah
(def thread-pool
(Executors/newFixedThreadPool
(+ 2 (.availableProcessors (Runtime/getRuntime)))))
;;; blah blah blah
sm_test.clj:
(ns sm-test ;; <~~~~~~~ notice dashes here
(:use [stack-machine.stack]) ;; ~~~~ and here
(:require [clojure.test :as t]))
(t/deftest test-test-itself
(t/testing "tests in the namespace 'stack machine.'"
(t/is (== 1 1.0))))
The test file works in CIDER when I do cider-test-run-ns-tests, but lein test produces the following error (gist: can't find sm_test.clj)
(it does the tests on asr namespace, then)
Execution error (FileNotFoundException) at user/eval227 (form-init3759808036021590492.clj:1).
Could not locate sm_test__init.class, sm_test.clj or sm_test.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
How can I make lein test work for this entire project?
I'd be grateful for any advice!
I am surprised that CIDER found the test, since the namespace in sm_test is wrong. It should be:
(ns stack-machine.sm-test ; added `stack-machine`
(:use stack-machine.stack clojure.test)) ; removed unneed square brackets
(deftest test-test-itself
(testing "tests in the namespace 'stack-machine.'"
(is (= 5 (+ 2 3))))) ; avoid int vs float comparisons!
P.S. It would be better to maintain symmetry between the names of the source & test file, eg:
src/stack_machine/stack.clj
test/stack_machine/stack_test.clj
P.S. I try to avoid using hyphens in a namespace so you don't have to translate to underscores in the file name & vice versa.

How to compile clojure modules that are not under "src" in a lein project

I built my project using lein new app hello, so I have this structure
.
└── src
└── hello
└── core.clj
└── project.clj
└── test
└── ..
I want to add another helper module to my project such that I can use the code in both the tests and the src modules as I wanted it decoupled from the src directory.
So I added a helpers module
.
└── src
└── hello
└── core.clj
└── project.clj
└── test
└── helpers
└──hello
└── helpers.clj
How can I change my project.clj file to make lein run compile. lein run does not compile and throws the following error when I try to require the helpers namespace.
Exception in thread "main" java.lang.ClassNotFoundException:
hello.helpers, compiling:(hello/core.clj:7:3)
My project.clj file looks like the default one :
(defproject hello "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"]]
:main ^:skip-aot hello.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
However in the IDE(IntelliJ) it works fine in the REPL, without throwing the class not found exception.
Add
:source-paths ["src" "helpers"]
to your project.clj file.

Output of Clojure Compiler in SBT Project

tl;dr: Unexpected layout of .class files produced by clojure compiler invoked from scala code.
I have an SBT project (using playframework) that includes some clojure code. The clojure compiler is being called from an SBT task in the build.sbt file. Here is the scala code invoking the clojure compiler(credit to: sbt-clojure).
The compiler is outputting .class files, but not in the layout I expect( based on the ns definition).
If I define my clojure namespace as follows:
(ns api.datastore.foo
(:require [clojure.core.async :refer (<!!)]
[datomic.client :as client])
(:gen-class
:methods [#^{:static true} [bar [java.util.List] clojure.lang.ISeq]])
... and this clojure source is located in app/api/datastore, then the layout of files resulting from clojure compilation is this:
└── classes
├── foo__init.class
└── api
└── datastore
├── foo.class
├── foo$fn__3.class
├── foo$loading__5569__auto____1.class
└── foo$_bar.class
When I try to call any of this code (e.g. function bar), an error results:
...java.io.FileNotFoundException: Could not locate api/datastore/foo__init.class or api/datastore/foo.clj on classpath...
Changing the definition of my namespace (note :name key) to this:
(ns foo
(:require [clojure.core.async :refer (<!!)]
[datomic.client :as client])
(:gen-class
:name api.datastore.foo
:methods [#^{:static true} [bar [java.util.List] clojure.lang.ISeq]])
... and moving this clojure source to app/ produces output like this:
└── classes
├── foo__init.class
├── foo$fn__3.class
├── foo$loading__5569__auto____1.class
├── foo$_bar.class
└── api
└── datastore
└── foo.class
... and it works!
But, now I don't have any directory structure for my clojure sources(the all have to be in app/), which is a problem for a number of reasons. Is there anyway to do this without the :name key(i.e. get the target directory structure that works from the namespace definition that doesn't)?

gen-class not generating a class

I'm having difficulty referencing classes generated via :gen-class.
The smallest example I can show that demonstrates the problem is:
(defproject test-proj
:dependencies [[org.clojure/clojure "1.8.0"]]
:aot [test-proj.test])
(ns test-proj.test
(:gen-class))
(defn -main []
(println test_proj.test)) ; Error here
The problem is, this yields a ClassNotFoundException on the marked line.
(I tried all different combinations of - and _ in the above file and the project.clj. I still don't fully understand what requires an underscore and what tolerates a dash. Some things seem to roll with dashes and convert them as needed, whereas I know from messing around that in the -main, I need underscores to reference test_proj.test.)
If I go into the project root file, there's no target folder, so it's not generating the class. If I go into the terminal and run lein compile, it generates the needed classes under target, and the above code runs without error. This is a poor workaround though. What if I modify the file and forget to manually recompile it? It's also a pain to have to manually compile it after any time I do a clean.
As a shot in the dark, I tried using compile right underneath the ns macro:
(compile 'test-proj.test)
If I uses dashes, compile seems to do literally nothing. I may be misinterpreting its use, but it doesn't generate class files under target. If I use underscores, it gives an exception saying that the namespace isn't found.
Is there a way to have the classes generated automatically so I don't need to run lein compile everytime? I thought that that's what the :aot in the project.clj did.
With Leiningen, specify :aot settings. :all is the easiest.
project.clj
(defproject test-proj "0.1.0-SNAPSHOT"
:main test-proj.core
:aot :all
:dependencies [[org.clojure/clojure "1.8.0"]])
If you want, you can specify the exact namespaces in an array as seen below:
project.clj
(defproject test-proj "0.1.0-SNAPSHOT"
:main test-proj.core
:aot [test-proj.core]
:dependencies [[org.clojure/clojure "1.8.0"]])
Then the following lein command:
lein compile
Will generate the byte code and .class files as specified in the :aot settings above.
core.clj
(ns test-proj.core
(:gen-class))
(defn -main[]
(println test_proj.core)
(println "Hello, World!"))
You want to see something like the below:
NikoMacBook% lein compile
Compiling test-proj.core
Once this is done, check the target folder, contains the proper class file, here test_proj/core.class.
NikoMacBook% tree target
target
├── classes
│   ├── META-INF
│   │   └── maven
│   │   └── test-proj
│   │   └── test-proj
│   │   └── pom.properties
│   └── test_proj
│   ├── core$_main.class
│   ├── core$fn__38.class
│   ├── core$loading__5569__auto____36.class
│   ├── core.class
│   └── core__init.class
└── stale
└── leiningen.core.classpath.extract-native-dependencies
7 directories, 7 files
The following will run the :main namespace, so test-proj.core.
lein run
Will output
NikoMacBook% lein run
Compiling test-proj.core
Compiling test-proj.core
test_proj.core
Hello, World!
Note, that the class is calling itself. Note also that if you do not run lein compile beforehand , it will run by itself.

Create a war with boot-clj

I want to create a war that I can deploy with tomcat. Using lein uberwar did the job just fine, however doing the same with boot doesn't seem to work. I can build a jar and run it, but the war fails with
Dec 09, 2015 12:15:31 AM org.apache.catalina.loader.WebappClassLoader validateJarFile INFO:
validateJarFile(/var/lib/tomcat7/sites/geeknow.guru/DEBUG##0.1.7/WEB-INF/lib/javax.servlet-api-3.1.0.jar)
- jar not loaded. See Servlet Spec 3.0, section 10.7.2. Offending class: javax/servlet/Servlet.class
I'm using the following build.boot
(set-env!
:source-paths #{"src/clj"}
:resource-paths #{"resources" "src/clj"}
:dependencies '[[org.clojure/clojure "1.7.0"]
[clj-time "0.9.0"]
[org.clojure/java.jdbc "0.3.7"]
[org.postgresql/postgresql "9.4-1202-jdbc41"]
[yesql "0.5.1"]
[migratus "0.8.6"]
[markdown-clj "0.9.67"]
[jarohen/nomad "0.7.2"]
[com.draines/postal "1.11.3"]
[compojure "1.4.0"]
[ring/ring-core "1.4.0"]
[ring/ring-devel "1.4.0"]
[ring/ring-defaults "0.1.5"]
[ring/ring-jetty-adapter "1.4.0"]
[ring-refresh "0.1.1"]
[ring-logger-timbre "0.7.5"]
[com.taoensso/timbre "4.1.4"]
[hiccup "1.0.5"]
[garden "1.3.0"]
[danlentz/clj-uuid "0.1.6"]
[speclj "3.3.1" :scope "test"]
[pandeiro/boot-http "0.7.1-SNAPSHOT"]])
(require '[pandeiro.boot-http :as http])
(require '[ring.middleware.reload :refer [wrap-reload]])
(require '[ring.adapter.jetty :as jetty])
(require '[ring.middleware.refresh :refer [wrap-refresh]])
(require '[blog.handler])
;;;;taken from boot-http.util
(defn resolve-sym [sym]
(require (symbol (namespace sym)) :reload)
(resolve sym))
(deftask ring-server
[]
(comp (jetty/run-jetty (wrap-refresh (wrap-reload (resolve-sym 'blog.handler/app))) {:port 3000}) (wait)))
(deftask uberwar
[]
(comp (aot) (pom) (web) (uber) (war)))
(deftask uberjar
[]
(comp (aot) (pom) (uber) (jar)))
(task-options!
pom {:project 'geeknow
:version "0.1.7"}
;uber {:as-jars true}
aot {:all true}
jar {:main 'blog.core
:manifest {"Description" "blog"}}
web {:serve 'blog.handler/app}
war {:main 'blog.core
:manifest {"Description" "blog"}}
repl {:init-ns 'blog.core})
Tomcat is complaining because one of the jars included in your war file contains a class that only the container environment can provide. The offending jar in the war is WEB-INF/lib/javax.servlet-api-3.1.0.jar.
By default, the uber task adds all dependencies, direct and transitive, to the war at WEB-INF/lib when --as-jars is set to true. --as-jars is the preferred way of bundling dependencies for deployment to servlet containers.
The problem appears to be that one of your direct dependencies is bringing in javax.servlet-api and uber is packaging it, causing the Tomcat problem.
First we need to figure out which dependency is bringing in javax.servlet-api. boot show contains many options for diagnosing dependency problems like this. You can learn about them all with boot show -h. The one we want now is boot show -d, which prints the dependency tree.
Here is the fragment of relevant output:
[ring/ring-jetty-adapter "1.4.0"]
├── [org.eclipse.jetty/jetty-server "9.2.10.v20150310"]
│ ├── [javax.servlet/javax.servlet-api "3.1.0"]
│ ├── [org.eclipse.jetty/jetty-http "9.2.10.v20150310"]
│ │ └── [org.eclipse.jetty/jetty-util "9.2.10.v20150310"]
│ └── [org.eclipse.jetty/jetty-io "9.2.10.v20150310"]
└── [ring/ring-servlet "1.4.0"]
From this output, we know that our dependency on ring/ring-jetty-adapter is what's causing javax.servlet/javax.servlet-api to be brought in.
Because this dependency is necessary for local development we don't want to omit it entirely. Instead, we can add the dependency with "test" scope:
[ring/ring-jetty-adapter "1.4.0" :scope "test"]
Scopes are a Maven concept for limiting the transitivity of dependencies in scenarios such as these. Boot uses Maven for its underlying dependency resolution machinery. uber is sensitive to Maven scopes, and can be configured to include or exclude various scopes depending on your needs. See boot uber -h for more information.
By default, the uber task won't package dependencies in "test" scope. By marking ring/ring-jetty-adapter this way, we've excluded it from our uber war.
The "test" scope is also useful for dependencies you might use in tests (of course!), or for deployment, or for other tasks during which you need a dependency but don't want to distribute it with your artifact, whether it's a library jar or an uberwar web app.