Fork me on GitHub
#clojure
<
2023-08-01
>
Aman Gupta08:08:30

Hello! I'm a beginner but I need expert Clojure advise so posting the question here. I'm trying to run a Clojure web app that uses the ring server. It was created in a windows Environment. I'm trying to run this in a WSL environment and I get errors which I think is related to my environment being Headless. Question: How do I make this work in a WSL setup. Here's the console output, it's very long unfortunately but the error is right at the end.

Daniel Tan08:08:21

> No X11 DISPLAY variable was set, but this program performed an operation which requires it.

p-himik08:08:24

Figure out the stacktrace of that error, then see what requires X11 in that stacktrace.

Aman Gupta08:08:52

okay so , I think java.awt.HeadlessException is the issue here.

p-himik08:08:56

That's not the issue, it's the symptom.

Aman Gupta08:08:17

yes it seems like I need to figure out how to get this app access to a graphics display since it's running from a headless terminal 😓 . Also trying to figure out the origin of the error

thheller08:08:46

first of all you probably want to tune down the logging. looking at jetty debug logs is just distracting not helping

thheller08:08:17

my guess would be that the server starts just fine but then something else likely is trying to open a browser for you

p-himik08:08:37

Ah, good guess.

thheller08:08:38

and that part fails with an uncaught exception and crashes everything

thheller08:08:29

check the command that starts the server. could be as simple as something trying to call clojure.java.browse/browse-url

thheller08:08:13

just searching for browse-url might get a hit

thheller08:08:37

jetty itself will not open any UI things and only runs "headless"

thheller08:08:18

java.awt.HeadlessException:
No X11 DISPLAY variable was set,
but this program performed an operation which requires it.
        at java.desktop/java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:166)
        at java.desktop/java.awt.Window.<init>(Window.java:553)
        at java.desktop/java.awt.Frame.<init>(Frame.java:428)
        at java.desktop/java.awt.Frame.<init>(Frame.java:393)
        at java.desktop/javax.swing.JFrame.<init>(JFrame.java:180)
        at clojure.java.browse_ui$open_url_in_swing.invokeStatic(browse_ui.clj:19)
        at clojure.java.browse_ui$open_url_in_swing.invoke(browse_ui.clj:15)
        at clojure.lang.Var.invoke(Var.java:384)
        at clojure.java.browse$open_url_in_swing.invokeStatic(browse.clj:66)
        at clojure.java.browse$browse_url.invokeStatic(browse.clj:76)
        at clojure.java.browse$browse_url.invoke(browse.clj:68)
        at shadow.cljs.devtools.api$browser_repl$fn__18913.invoke(api.clj:528)
        at shadow.cljs.devtools.api$browser_repl.invokeStatic(api.clj:527)
        at shadow.cljs.devtools.api$browser_repl.invoke(api.clj:490)

thheller08:08:39

thats what the trace looks like when shadow-cljs tries to open a browser in wsl, so seems to fit

thheller08:08:54

could also be a tool attempting to open, I know figwheel has that option. not sure if it properly handles failures though.

Aman Gupta09:08:28

hey thanks for that @U05224H0W! yes it looks like the ring-server package is trying to open a browser. Not sure how to disable this so i'll have to spend some more time digging in the code. But, when I really think about it .. webpack ( unrelated to this project ) is able to open a browser just fine within the same env :thinking_face:

Aman Gupta09:08:53

okay so I found a simpler solution: the ring server has a server-headless command. Used this and the Project was able to run. Thank you all for your help! learnt quite a bit today

thheller09:08:53

webpack probably just has a fallback for that

Aman Gupta09:08:40

one last question .. since this is a very old project. based on this project file what upgrades / migrations would you recommend ?

(defproject portal "1.6.4"
  :description "xxx xxxPortal"
  :url ""
  :min-lein-version "2.8.1"
  :dependencies [[org.clojure/clojure "1.10.1"] ;; "1.9.0"
                 [org.clojure/tools.reader "1.3.3"] ; "1.3.2"
                 [org.clojure/core.async "1.3.610" ;; "1.2.603" ;; "0.5.527"
                  :exclusions [org.clojure/tools.reader]]
                 [commons-io "2.8.0"] ; "2.7"
                 [ring/ring-core "1.8.1"] ;; "1.8.0"
                 [compojure "1.6.1"
                  :exclusions [ring/ring-core]] ;; "1.6.0"
                 [clj-time "0.15.2"]  ;; "0.14.2"
                 [ring/ring-defaults "0.3.2"] ;; "0.3.1"
                 [ring-cors "0.1.13"] ;; "0.1.11"
                 [ring-middleware-format "0.7.4" ;; "0.7.2"
                  :exclusions [ring/ring-core
                               org.clojure/core.memoize]]
                 [buddy "2.0.0"] ;1.3.0
                 [clj-http "3.10.1"] ;; "3.10.0"
                 [http-kit "2.5.0"] ; "2.3.0"
                 [com.novemberain/monger "3.5.0" ;; "3.1.0"
                  :exclusions [org.mongodb/mongodb-driver]]
                 [org.mongodb/mongodb-driver "3.12.6"] ;; "3.11.2"
                 [org.eclipse.jgit/org.eclipse.jgit "4.6.0.201612231935-r"]
                 [org.slf4j/slf4j-api "1.7.30"] ;; "1.7.29"
                 [com.fzakaria/slf4j-timbre "0.3.19"] ;; "0.3.14"
                 [com.taoensso/timbre "5.0.1"] ; "4.10.0"
                 [org.clojure/tools.nrepl "0.2.13"] ;0.2.12
                 [danlentz/clj-uuid "0.1.9"] ;; "0.1.7"
                 [cheshire "5.10.0"] ;; "5.9.0"
                 [clojurewerkz/mailer "1.3.0"
                  :exclusions [org.clojure/core.cache]]
                 [com.draines/postal "2.0.3"] ;; "2.0.2"
                 [com.sun.mail/mailapi "1.6.5"] ;; "1.6.4"
                 [com.sun.mail/smtp "1.6.5"] ;; "1.6.4"
                 [com.sun.mail/javax.mail "1.6.2"]
                 ;; app insights sdk
                 [com.microsoft.azure/applicationinsights-core "2.6.2"]]

  :aliases {"build" ["do"
                     ["clean"]
                     ["run" "-m" "build/execute"]
                     ["codox"]
                     ["ring" "uberwar"]]}

  ;; !!CAUTION!! lein may hang while starting if repo is not accessible
  ;; keep the repository commented out after downloading once.
  :repositories [;; for jgit ;;
                 #_["jgit-repository"
                    ""]]

  :codox {:source-paths ["src"]
          :metadata {:doc/format :markdown}
          :output-path "resources/doc/reference"}

  :repl-options {:host "0.0.0.0"
                 :init-ns xxx.portal.core
                 :timeout 380000
                 :init (init)}

  :plugins [[lein-ring "0.12.5"]  ;; "0.12.2"
            [lein-codox "0.10.7"]] ;; "0.10.3"

  :ring {:handler xxx.portal.route/app-routes
         :exploded true
         :uberwar-name "war"}

  :source-paths ["src"]

  :main xxx.portal.core

  :profiles {:dev {:source-paths ["dev" "src"]}})

thheller09:08:36

looks fine

gratitude-thank-you 2
jeaye21:08:46

Does there exist a full unit test suite for clojure.core fns, written in Clojure? 😁

jeaye21:08:57

Asking since it looks like Clojure JVM doesn't have a corresponding test file for core.clj and a full test suite for clojure.core would be incredibly useful for dialect creators. If it doesn't exist, I'll make it and share it.

dpsutton21:08:58

there’s a corpus of solutions to the 4clojure problems. I think it might be called coal-mine or canary. It’s used to check for regressions in clojure.core functions. So not exactly checking the core functions themselves but can be a good indicator

jeaye21:08:51

Hm, that's very useful. Thanks, both of you.

👍 2
phronmophobic21:08:15

you can search "coal mine" and there's similar discussions like https://clojurians.slack.com/archives/C06E3HYPR/p1675264254772879

jeaye21:08:57

I still think a unit test suite would be beneficial on top of that, since dialect creators need to know that their core fns behave the same as Clojure's in every scenario, if they want to avoid surprises.

phronmophobic21:08:23

Seems like it's ok for dialects to have differences since there may be practical platform or performance tradeoffs.

jeaye21:08:50

Each difference is a cut to the UX and sanity of the user.

phronmophobic21:08:02

right, tradeoffs

jeaye21:08:04

That's the approach I'm trying to take with jank, anyway.

jeaye21:08:46

:thinking_face:

phronmophobic21:08:43

For example, clojurescript has differences with clojure and many of them are intentional.

jeaye22:08:40

Oh, I'm familiar. This sort of incongruence is mentally taxing on people trying to write portable Clojure.

6
jeaye22:08:12

As Clojure gets more and more dialects, which is definitely happening, we'll hopefully converge on a subset of Common Clojure which works across all of them without additional thought. Anything outside of that set becomes a burden. But I think it falls on the dialect creators to ensure this set remains as large as possible.

👍 4
2
Alex Miller (Clojure team)22:08:35

There are a lot of unit tests for clojure.core functions, but they are split across a lot of test files not a single test file. I would consider those to be both an under and over specification of what the actual functions promise.

jeaye22:08:46

Thanks, Alex. If I were to make a full unit test suite for clojure.core, is it something that the Clojure team would have interest in maintaining?

andy.fingerhut22:08:48

It is really up to the Clojure team to answer that, of course, but note that any such offer is also likely to end up with a stream of questions about corner cases, of whether the behavior is "official Clojure" or "implementation detail".

jeaye22:08:51

Excellent. These are questions we need to answer so that dialect creators can know what the heck we're designing against.

jeaye22:08:50

As of now, there's no spec for Clojure, no official test suite, and the two most popular Clojure dialects (CLJ and CLJS) already diverge in some situations. Establishing what it means to be a Clojure sooner, rather than later, can help ensure the upcoming dialects arrive at that Common Clojure mark I mentioned above. Starting with common, tested clojure.core behavior is as good as any. We can build it from CLJ, reconcile any differences with CLJS (and maybe find some bugs along the way), and then use it as a north star for jank, ClojureDart, Ferret, Clojerl, Lingy, etc.

Alex Miller (Clojure team)23:08:08

I’m interested in this, but it would probably be better to do it in a separate repo. If you wanted to increase the odds that this is useful to core team, require signing the CA and license it EPL

Alex Miller (Clojure team)23:08:59

Chunking it up into easily digestible pieces would also be helpful. Making it EPL would also allow you to just adopt core tests where possible

andy.fingerhut23:08:22

I would recommend asking Mike Fikes for any stories he is willing to share from his creation and maintenance of the coal-mine suite of tests.

👍 2
Alex Miller (Clojure team)23:08:16

Coal-mine is a separate (also very useful!) idea

jeaye23:08:21

Sounds good. Thanks, Alex. I'll get this going this year, as part of building out jank's clojure.core fns. Will be following up once I have something to show.

Alex Miller (Clojure team)23:08:58

Would be a great thing to be funded by Clojurists Together for example

Alex Miller (Clojure team)23:08:02

Now that we’ve gone hard into adopting GitHub actions I think we could also automate this stuff from an external repo pretty easily in Clojure

👍 2