Hello! I'm trying to build an uberjar of my app using depstar and I get this error...
Exception in thread "main" Syntax error compiling at (calculators/web.clj:1:1).
...
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.server.handler.gzip.GzipHandler
The calculators.web namespace has this...
(:import org.eclipse.jetty.server.handler.gzip.GzipHandler)
I'm using ring-jetty-server 1.9.2, which includes jetty-server 9.4.38.v20210224 , where the GzipHandler
class is defined. Moreover, when I start the app from the REPL, there are no issues, the GzipHandler
class is found and I get gzipped responses from the server.
Any idea on why depstar doesn't find the class?@xavi when you run your app from the REPL do you add any aliases that cause Ring to be added?
No. I have Ring directly in :deps...
{:deps
{ring/ring-core {:mvn/version "1.9.2"}
ring/ring-jetty-adapter {:mvn/version "1.9.2"}
...}
}
OTOH, I tried removing the references to GzipHandler and now it doesn't find Stuart Sierra's Component, which the app also depends on.It seems it doesn't find any dependency?
I tried changing the :replace-deps
in the depstar alias with :extra-deps
(I know that according to the depstar README I have to use :replace-deps
, but I'm exploring the problem š , then it fails with...
Execution error (NullPointerException) at hf.depstar.uberjar/compile-arguments (uberjar.clj:545).
Cannot invoke "clojure.lang.Named.getName()" because "x" is null
Also, I had a dev/user.clj
and I had "dev" in paths...
:paths ["dev" "resources" "src/clj" "src/cljs" "src/cljc"]
I removed "dev" from paths and now...
clojure -X:uberjar :jar app.jar
returns...
Execution error (NullPointerException) at hf.depstar.uberjar/compile-arguments (uberjar.clj:545).
Cannot invoke "clojure.lang.Named.getName()" because "x" is null
(So the same error I got after changing :replace-deps
with :extra-deps
)ah, just before that "Execution error...", there's...
[main] INFO hf.depstar.uberjar - Compiling nil ...
Oops, sorry... I wasn't specifying the namespace to compile. It worked after specifying :main-class
clojure -X:uberjar :aot true :jar app.jar :main-class calculators.main
...and that works even after adding back the GzipHandler
, but not if I also add back "dev" to :paths
Ok, no problem, I don't need dev/user.clj in the uberjar, but I still wonder why that breaks it
Well, if something is dev-only, it should not be on your paths/deps by default ā you should put it behind an alias.
right... just wondering why that breaks the uberjar build
Iām curious too. I donāt know if you can share your deps.edn
file and the contents of your dev
folder?
/dev
only has user.clj
...
; <https://github.com/jasongilman/proto-repl-demo/blob/master/dev/user.clj>
(ns user
(:require [clojure.tools.namespace.repl :refer (refresh)]
[calculators.main :as main]
[com.stuartsierra.component :as component]
[clojure.repl :refer (apropos dir doc find-doc pst source)]
;[prc]
;[proto-repl.saved-values]
))
(def system
"A Var containing an object representing the application under
development."
nil)
(defn init
"Creates and initializes the system under development in the Var
#'system."
[]
(println "init")
(alter-var-root #'system
(-> {:web-port 8080}
main/system
constantly)))
(defn start
"Starts the system running, updates the Var #'system."
[]
(println "start")
(alter-var-root #'system component/start))
(defn stop
"Stops the system if it is currently running, updates the Var
#'system."
[]
(alter-var-root #'system #(when % (component/stop %))))
(defn reset []
;(tnr/refresh :after 'user/start)
(println "reset called")
(stop)
(refresh :after 'user/go))
(defn go []
(println "go")
(init)
(start))
(println "dev/user.clj loaded.")
deps.edn
{:deps
{org.clojure/clojure {:mvn/version "1.10.3"}
org.clojure/clojurescript {:mvn/version "1.10.773"}
org.clojure/core.async {:mvn/version "0.3.442"}
com.stuartsierra/component {:mvn/version "1.0.0"}
compojure {:mvn/version "1.6.2"}
ring/ring-core {:mvn/version "1.9.2"}
ring/ring-jetty-adapter {:mvn/version "1.9.2"}
hiccup {:mvn/version "1.0.5"}
optimus {:mvn/version "0.19.2"}
rum {:mvn/version "0.10.8" :exclusions [sablono]}
sablono {:mvn/version "0.8.0"}
org.clojure/tools.namespace {:mvn/version "1.1.0"}
}
:paths
["resources" "src/clj" "src/cljs" "src/cljc"]
:aliases
{:dev {:main-opts ["-m" "cljs.main"
"--compile-opts" "dev.cljs.edn"
"--compile" "calculators.frontend.core"
"--repl"]}
:uberjar
{:replace-deps {com.github.seancorfield/depstar {:mvn/version "2.0.211"}}
:exec-fn hf.depstar/uberjar
:exec-args {:aot true}}}}
OK, so I think itās a bug that it tries to use the main class when :aot true
and :main-class
not specified (thatās the āCompiling nilā issue). I donāt know why adding dev
causes problems but it gives me something to look at.
https://github.com/seancorfield/depstar/issues/76 and https://github.com/seancorfield/depstar/issues/77
For now you have a workaround and youāre able to continue @xavi?
I think I figured out the issue @xavi: because dev/user.clj
is on your default path, Clojure itself runs it when you try to start depstar
ā so :replace-deps
wonāt work here because that removes Component etc from the classpath and dev/user.clj
will not evaluate without it. Iām not sure why you didnāt get a full exception trying to run depstar
in that situation ā hereās what I got:
(! 1137)-> clojure -X:uberjar
Exception in thread "main" Syntax error compiling at (user.clj:1:1).
...
Caused by: java.io.FileNotFoundException: Could not locate com/stuartsierra/component__init.class, com/stuartsierra/component.clj or com/stuartsierra/component.cljc on classpath.
..
at user$eval138$loading__6737__auto____139.invoke(user.clj:2)
When I switched to :extra-deps
, that worked (with the caveat about trying to compile nil
without :main-class
provided).Also, what version of the Clojure CLI are you using? clojure -Sdescribe
Iām on a recent version so I get lots of deprecation warnings about the unqualified lib names:
(! 1148)-> clojure -Sdeps '{:deps {com.github.seancorfield/depstar {:local/root "/Developer/workspace/depstar"}}}' -X hf.depstar/uberjar :aot true :jar test.jar :main-class calculators.main
dev/user.clj loaded.
DEPRECATED: Libs must be qualified, change compojure => compojure/compojure (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change rum => rum/rum (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono => sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono => sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change optimus => optimus/optimus (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change hiccup => hiccup/hiccup (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change compojure => compojure/compojure (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change rum => rum/rum (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono => sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono => sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change optimus => optimus/optimus (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change hiccup => hiccup/hiccup (/Users/sean/clojure/issue-77/deps.edn)
[main] INFO hf.depstar.uberjar - Compiling calculators.main ...
[main] INFO hf.depstar.uberjar - Building uber jar: test.jar
...
Note the dev/user.clj loaded.
message before the rest of the CLI output.
Iāve fixed #76 on develop (the default branch) and Iāve addressed #77 by adding a note to the README about user.clj
and :replace-paths []
(see notes in that ticket for more details).
You mean why i didn't get an exception saying that the error was in user.clj
like you did?
In my case the error is reported in calculators/web.clj
, which you don't have, and also references GzipHandler and Component. I guess the compiler tried to compile that before user.clj and that's why I got the error there instead.
{:version "1.10.3.814"
...
OK, cool. Just wanted to verify youāre on a recent version, to eliminate other possible weirdness.
Ah, yes, that makes sense.
In my case I don't see it, because for me the exception happens in calculators/web.clj
, which seems to be compiled before user.clj
like we said before
I meant, when the process is successful.
I think just adding :replace-paths []
(per the notes in the GH issue) should solve the problem.
(youāll still end up with dev/user.clj
in your JAR ā and itāll still run in the compilation process inside depstar
ā but that would stop it running in the main depstar
process, which has no other dependencies than depstar
itself, due to :replace-deps
ā does that make sense?)
Yes, :replace-paths []
works ... although like you said before, dev/user.clj
shouldn't be in paths/deps by default, so i'll remove it from there and then there's no need to use :replace-paths []
And yes, although i don't know the full details of how depstar
works, your explanation makes sense to me
Great! Thanks Sean for digging into this, and for all your contributions to the Clojure ecosystem!
1š