In my project.cli I have a dependency on clj-http that is used for tests only, with clj-http.client.
When I look at the uberjar file created for that project, I see that the class fils associated with this dependency are included. That makes the jar file bigger than it need be.
So, is there a way to define a dependency in clojure such that it is only used during tests, and is not included in the uberjar?
I know that I could do this in a pom.xml, but the pom.xml is generated when using clojure, so I only have recourse to something that works in the project.clj file.
To add more colour, my project.clj looks like this
(defproject aproject "0.1.0-SNAPSHOT"
:description "A project"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/data.json "0.2.6"]
[compojure "1.5.0"]
[hiccup "1.0.5"]
[http-kit "2.1.18"]
[org.clojure/tools.logging "0.3.1"]
[ch.qos.logback/logback-classic "1.1.7"]
[ring/ring-devel "1.4.0"]]
:plugins [[lein-ring "0.9.7"]]
:ring {:handler aproject.core/app-routes}
:main ^:skip-aot aproject.core
:target-path "target/%s"
:resources-paths ["resources/"]
:profiles {:uberjar {:aot :all}
:dev {:dependencies [[peridot "0.4.3"]
[midje "1.8.3"]]
:plugins [[lein-midje "3.2.1"]]
:aliases {"test" ["midje"]}}
:test {:dependencies [[clj-http "3.5.0"]
[midje "1.8.3"]]
:plugins [[lein-midje "3.2.1"]]}
})
I am running the tests like this:
lein with-profile test midje :filters dt
What I am seeing is:
Exception in thread "main" java.io.FileNotFoundException: Could not locate midje/util/ecosystem__init.class or midje/util/ecosystem.clj on classpath., compiling:(/private/var/folders/7l/0fwd_7ls1m19q3_z1_tgg1w80000gn/T/form-init7253661442775183594.clj:1:125)
at clojure.lang.Compiler.load(Compiler.java:7391)
The filter probably does not affect this, but just in case the test looks like this:
(ns aproject.deployment.core
(:require [midje.sweet :refer :all]
[clj-http.client :as client]
[peridot.core :as p]
[clojure.data.json :as json]
[front-end.core :as fe]))
(facts "'aproject' deployed" :dt
(let [response (client/get "http://localhost:8080/ping")]
(response :status) => 200
))
I can see that the test profile is being triggered, and I seem to have the dependency for midje, and the plugin, but ...?
Thanks
Nathan
Add it to the :test profile, then run your tests with lein with-profile test midje :filters dt. Generate your uberjar as usual, lein uberjar and it shouldn't include the extra files.
Related
On a fresh lein new re-frame bc +handler app, if I lein uberjar or lein jar it doesnt seem to set the main class correctly. At the end of the compillation it tells me
Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.
Here is the server.clj and project.clj that is created using the re-frame +handler template:
server.clj:
(ns bc.server
(:require [bc.handler :refer [handler]]
[config.core :refer [env]]
[ring.adapter.jetty :refer [run-jetty]])
(:gen-class))
(defn -main [& args]
(let [port (Integer/parseInt (or (env :port) "3000"))]
(run-jetty handler {:port port :join? false})))
project.clj:
(defproject bc "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.10.1"]
[org.clojure/clojurescript "1.10.597"
:exclusions [com.google.javascript/closure-compiler-unshaded
org.clojure/google-closure-library
org.clojure/google-closure-library-third-party]]
[thheller/shadow-cljs "2.8.83"]
[reagent "0.8.1"]
[re-frame "0.10.9"]
[compojure "1.6.1"]
[yogthos/config "1.1.7"]
[ring "1.7.1"]]
:plugins [
[lein-shell "0.5.0"]]
:min-lein-version "2.5.3"
:source-paths ["src/clj" "src/cljs"]
:clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
:shell {:commands {"open" {:windows ["cmd" "/c" "start"]
:macosx "open"
:linux "xdg-open"}}}
:aliases {"dev" ["with-profile" "dev" "do"
["clean"]
["run" "-m" "shadow.cljs.devtools.cli" "watch" "app"]]
"prod" ["with-profile" "prod" "do"
["clean"]
["run" "-m" "shadow.cljs.devtools.cli" "release" "app"]]
"build-report" ["with-profile" "prod" "do"
["clean"]
["run" "-m" "shadow.cljs.devtools.cli" "run" "shadow.cljs.build-report" "app" "target/build-report.html"]
["shell" "open" "target/build-report.html"]]
"karma" ["with-profile" "prod" "do"
["clean"]
["run" "-m" "shadow.cljs.devtools.cli" "compile" "karma-test"]
["shell" "karma" "start" "--single-run" "--reporters" "junit,dots"]]}
:profiles
{:dev
{:dependencies [[binaryage/devtools "0.9.11"]]}
:prod { }
:uberjar {:source-paths ["env/prod/clj"]
:omit-source true
:main bc.server
:aot [bc.server]
:uberjar-name "bc.jar"
:prep-tasks ["compile" ["prod"]]}
})
It does generate a jar file when I lein uberjar but when I try to run it it errors out telling me that it does not include a main class.
What am I doing incorrectly?
Your uberjar profile calls ["compile" ["prod"]] in :prep-tasks. Your "prod" alias calls "clean" and "target" is listed in :clean-targets.
In essence, your uberjar deletes your compiled Clojure code.
You need to tell leiningen what namespace has your main function. In project.clj:
:main my.service.runner
from:
https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L222
I would like to use cloverage so I can check how much of my code base is tested by speclj. However after installing cloverage as a lein plugin and running: lein cloverage I see the following exception:
Exception in thread "main" java.io.FileNotFoundException:
Could not locate app/unit/core_spec__init.class or app/unit/core_spec.clj on classpath.
Please check that namespaces with dashes use underscores in the Clojure file name.,
compiling:(/private/var/folders/w_/yt926bqs21g44f257yz05ctsjbv948/T/form-init4597524674545750330.clj:1:125)
Caused by: java.io.FileNotFoundException: Could not locate app/component/core_spec__init.class or app/component/core_spec.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
I've not used cloverage before so what to check if I'm using it correctly, has anyone come across this issue before?
This is what my project.clj looks like:
(defproject app version
:dependencies [
[org.clojure/clojure "1.8.0"]
[org.clojure/tools.logging "0.4.0"]
[org.clojure/tools.cli "0.3.5"]
[org.clojure/data.json "0.2.6"]
[org.postgresql/postgresql "9.4-1201-jdbc41"]
[org.slf4j/slf4j-log4j12 "1.7.25"]
[log4j/log4j "1.2.17" :exclusions [javax.mail/mail
javax.jms/jms
com.sun.jmdk/jmxtools
com.sun.jmx/jmxri]]
[metosin/compojure-api "1.1.11"]
[metosin/ring-swagger "0.24.3"]
[compojure "1.6.0"]
[cheshire "5.8.0"]
[ring "1.6.3"]
[ring/ring-json "0.4.0"]
[ring-logger "0.7.7"]
[environ "1.1.0"]
[korma "0.4.3"]
[blackwater "0.0.9"]
[prismatic/schema "1.1.7"]
[siili/humanize "0.1.1"]
[amazonica "0.3.117"]
]
:main app.cli.core
:plugins [
[lein-ring "0.12.1"]
[lein-cloverage "1.0.10"]
[speclj "3.3.2"]
]
:test-paths ["spec"]
:profiles {
:uberjar {:aot :all}
:user {
:plugins
[[cider/cider-nrepl "0.16.0"]
[lein-kibit "0.1.6"]
[nightlight/lein-nightlight "1.0.0"]
[lein-cloverage "1.0.6"]
[jonase/eastwood "0.2.3"]
[lein-cloverage "1.0.9"]
[speclj "3.3.2"]]
}
:dev {
:dependencies [
[ring-mock "0.1.3"]
[clj-http "3.7.0"]
[org.clojure/data.json "0.2.6"]
[speclj "3.3.2"]
[clj-time "0.14.2"]
[listora/again "0.1.0"]
[environ "1.1.0"]
]
}
}
)
spec/app/component/core_spec.clj
(ns app.component.core_spec
(:require [speclj.core :refer :all]
[clojure.data.json :as json]
[clj-http.client :as client]
[clj-time.core :as t]
[again.core :as again]
[clj-time.format :as f]
[environ.core :refer [env]]))
(describe "app"
; tests and things...
)
Your problem is probably unrelated to Cloverage specifically. It looks like you're trying to require app.unit.core-spec, and that file either doesn't exist or hasn't been properly named (don't forget source files should have underscores, not dashes!)
I have a Clojure library that has two gen-class directives. When I run lein run, there are no issues. However, when I run lein uberjar, I get errors:
$ lein uberjar
Compiling 6 source files to /Users/frank/src/user/target/uberjar/classes
Compiling user.common
Compiling user.core
java.lang.ClassNotFoundException: user.server.UserAuthenticationServer, compiling:(user/core.clj:15:30)
Exception in thread "main" java.lang.ClassNotFoundException: user.server.UserAuthenticationServer, compiling:(user/core.clj:15:30)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6926)
.....
at clojure.lang.Compiler.analyze(Compiler.java:6701)
Caused by: java.lang.ClassNotFoundException: user.server.UserAuthenticationServer
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
...
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6919)
... 86 more
In addition to the generated java files, there is the project.clj, server.clj, and core.clj.
project.clj
(defproject user "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.9.0-alpha14"]
[io.grpc/grpc-core "1.7.0"]
[io.grpc/grpc-netty "1.7.0"
:exclusions [io.grpc/grpc-core]]
[io.grpc/grpc-protobuf "1.7.0"]
[io.grpc/grpc-stub "1.7.0"]]
:main ^:skip-aot user.core
:aot [user.server]
:target-path "target/%s"
:source-paths ["src/clj"]
:java-source-paths ["src/generated/proto"
"src/generated/grpc"]
:profiles {:uberjar {:aot :all}})
core.clj
(ns user.core
(:import [io.grpc Server ServerBuilder])
(:gen-class))
(defonce start-server-atom (atom nil))
(def port 8080)
(defn start-server []
(when-not #start-server-atom
(reset! start-server-atom
(-> (ServerBuilder/forPort port)
(.addService (new user.server.UserAuthenticationServer))
.build
.start
.awaitTermination))))
(defn -main
[& args]
(start-server))
server.clj
(ns user.server
(:gen-class
:main false
:name user.server.UserAuthenticationServer
:extends xyz.skroo.user.UserAuthenticationGrpc$UserAuthenticationImplBase))
(defn -startUserAuthentication [this req res]
(.onNext res req)
(.onCompleted res))
It's weird because this was working and I think the compile-time order changed and now I cannot generate a standalone jar.
:profiles {:uberjar {:aot :all}} means that when you run uberjar it will try to compile all Namespaces. When you do lein run it only compiles the namespace in the :aot key.
Try to update the uberjar profile to only aot the server namespace and see if that works.
I am following the tutorial from the below URL:
http://www.xuan-wu.com/2013-09-21-Basic-Web-Application-in-Clojure
but i received one error when i execute :
lein ring uberwar
The error is:
Caused by: java.io.FileNotFoundException: Could not locate hiccup/core__init.class or hiccup/core.clj on classpath:...
What I read on another stackoverflow thread :
Hiccup not working : FileNotFoundException: Could not locate ../as__init.class or ../as.clj on classpath
is related to the required namespace without the :as.
(ns myblog.views
(:require [hiccup.core :refer (html)]
.......
Also I tried to simple 'use' it:
(ns myblog.views
(:use hiccup.core)
(:require [hiccup.form :as f]
.......
but i received the same error.
What is wrong in my code? Thanks in advance for any hint/url!
I am copying below the project.clj file:
(defproject dgblog "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.6.0"]
[compojure "1.1.9"]
[org.clojure/java.jdbc "0.3.0-alpha5"]
[mysql/mysql-connector-java "5.1.25"]
[ring-basic-authentication "1.0.2"]]
:plugins [[lein-ring "0.8.12"]]
:ring {:handler dgblog.handler/app}
:profiles
{:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
[ring-mock "0.1.5"]]}})
and the views.clj header :
(ns dgblog.views
(:use hiccup.core)
(:require
;; (:require [hiccup.core :refer (html)]
[hiccup.form :as f]
[dgblog.posts :as posts]))
Exception: Exception in thread "main" java.io.FileNotFoundException: Could not locate hiccup/form_helpers__init.class or hiccup/form_helpers.clj on classpath:
I'm trying to get a toy compojure app up and running. The original app was from CloudBees and their ClickStart app for Clojure/Compojure. I'm trying to add a simple form (that won't persist anything yet) using hiccup form_helpers but I'm getting a ClassNotFound exception. Here's what I've done:
project.clj:
(defproject mywebapp "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[org.clojure/clojure "1.4.0"]
[compojure "1.1.1"]
[hiccup "1.0.1"]]
:plugins [[lein-ring "0.7.3"]]
:ring {:handler mywebapp.routes/app}
:profiles
{:dev {:dependencies [[ring-mock "0.1.3"]]}})
views.clj:
(ns mywebapp.views
(:use [hiccup core page]
[hiccup form-helpers :only [form-to label text-area submit-button]]))
...
(defn shout-form []
[:div {:id "shout-form" }
(form-to [:post "/form"]
(label "shout" "What do you want to SHOUT?")
[:br]
(text-area "shout")
[:br]
(submit-button "SHOUT!"))])
...
Ah, looks like I just had an old example of forms in hiccup. form_helpers was from a previous version.
if I change my views.clj file from this:
(:use [hiccup form-helpers])
to look like this:
(:use [hiccup form])
(and presumably this would work though i haven't tested it):
(:use [hiccup form :only [form-to label text-area submit-button]])
I don't get the error anymore.
To clarify: the package used to be called "form_helpers" and is now simply called "form".