depstar

Discussion around https://github.com/seancorfield/depstar
2021-04-02T11:12:44.042700Z

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?

seancorfield 2021-04-02T15:38:25.043Z

@xavi when you run your app from the REPL do you add any aliases that cause Ring to be added?

2021-04-02T15:55:41.045400Z

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.

2021-04-02T15:57:53.045700Z

It seems it doesn't find any dependency?

2021-04-02T16:02:29.048500Z

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

2021-04-02T16:11:46.051300Z

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)

2021-04-02T16:20:25.052Z

ah, just before that "Execution error...", there's...

[main] INFO hf.depstar.uberjar - Compiling nil ...

2021-04-02T16:25:55.053400Z

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

2021-04-02T16:31:09.054900Z

...and that works even after adding back the GzipHandler, but not if I also add back "dev" to :paths

2021-04-02T16:31:47.056300Z

Ok, no problem, I don't need dev/user.clj in the uberjar, but I still wonder why that breaks it

seancorfield 2021-04-02T16:31:53.056500Z

Well, if something is dev-only, it should not be on your paths/deps by default ā€” you should put it behind an alias.

2021-04-02T16:32:30.057Z

right... just wondering why that breaks the uberjar build

seancorfield 2021-04-02T16:33:03.057600Z

Iā€™m curious too. I donā€™t know if you can share your deps.edn file and the contents of your dev folder?

2021-04-02T16:37:09.057900Z

/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
                  (-&gt; {: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}}}}

seancorfield 2021-04-02T16:58:37.059300Z

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.

seancorfield 2021-04-02T17:01:41.060100Z

For now you have a workaround and youā€™re able to continue @xavi?

seancorfield 2021-04-02T17:40:47.063500Z

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)-&gt; 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).

seancorfield 2021-04-02T17:41:16.064Z

Also, what version of the Clojure CLI are you using? clojure -Sdescribe

seancorfield 2021-04-02T17:42:15.064700Z

Iā€™m on a recent version so I get lots of deprecation warnings about the unqualified lib names:

(! 1148)-&gt; 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 =&gt; compojure/compojure (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change rum =&gt; rum/rum (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono =&gt; sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono =&gt; sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change optimus =&gt; optimus/optimus (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change hiccup =&gt; hiccup/hiccup (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change compojure =&gt; compojure/compojure (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change rum =&gt; rum/rum (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono =&gt; sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change sablono =&gt; sablono/sablono (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change optimus =&gt; optimus/optimus (/Users/sean/clojure/issue-77/deps.edn)
DEPRECATED: Libs must be qualified, change hiccup =&gt; 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
  ...

seancorfield 2021-04-02T17:43:07.065600Z

Note the dev/user.clj loaded. message before the rest of the CLI output.

seancorfield 2021-04-02T17:57:28.066700Z

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).

2021-04-02T18:16:40.067100Z

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.

2021-04-02T18:17:43.067300Z

{:version "1.10.3.814"
...

seancorfield 2021-04-02T18:19:36.067500Z

OK, cool. Just wanted to verify youā€™re on a recent version, to eliminate other possible weirdness.

seancorfield 2021-04-02T18:19:47.067700Z

Ah, yes, that makes sense.

2021-04-02T18:26:31.067900Z

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

seancorfield 2021-04-02T18:29:35.068100Z

I meant, when the process is successful.

seancorfield 2021-04-02T18:30:38.068300Z

I think just adding :replace-paths [] (per the notes in the GH issue) should solve the problem.

seancorfield 2021-04-02T18:32:04.068500Z

(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?)

2021-04-02T18:42:36.068700Z

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

1
2021-04-02T18:45:12.069100Z

Great! Thanks Sean for digging into this, and for all your contributions to the Clojure ecosystem!

1šŸ˜Š