cljfx

https://github.com/cljfx/cljfx
jlmr 2020-02-14T08:54:44.050500Z

@vlaaad, I looked at it some more with this code:

(defn -main
  [& _]
  (let [app (create-app)
        threads (keys (Thread/getAllStackTraces))]
    (doseq [t threads]
      (println t ": " (.isDaemon t)))
    app))
create-app is just a thin wrapper around fx/create-app . When I compile this and run the jar, I get the following output:
#object[java.lang.ref.Reference$ReferenceHandler 0x4beeb0e Thread[Reference Handler,10,system]] :  true
#object[java.lang.Thread 0x7f92b990 Thread[JavaFX Application Thread,5,system]] :  true
#object[java.lang.ref.Finalizer$FinalizerThread 0x6c1832aa Thread[Finalizer,8,system]] :  true
#object[java.lang.Thread 0x31e04b13 Thread[Signal Dispatcher,9,system]] :  true
#object[com.sun.glass.ui.InvokeLaterDispatcher 0x64355120 Thread[Thread-1,5,main]] :  true
#object[java.lang.Thread 0x33db72bd Thread[AWT-Shutdown,5,system]] :  false
#object[java.lang.Thread 0x64b7225f Thread[QuantumRenderer-0,5,main]] :  true
#object[java.lang.Thread 0x6e8a9c30 Thread[main,5,main]] :  false
#object[java.lang.Thread 0x6145b81e Thread[Thread-2,5,main]] :  true
To me this seems to indicate that the JavaFX thread is started as a daemon thread. Am I misinterpreting this?

vlaaad 2020-02-14T09:52:33.051700Z

Huh, interesting. Tried from the repl:

clj -Sdeps '{:deps {cljfx {:mvn/version "1.6.3"}}}'                                                                                                                                       
Clojure 1.10.1
user=> (require 'cljfx.api)
nil
user=> (doseq [t (keys (Thread/getAllStackTraces))] (prn (.getName t) (.isDaemon t)))
"Finalizer" true
"main" false
"Signal Dispatcher" true
"Common-Cleaner" true
"InvokeLaterDispatcher" true
"JavaFX Application Thread" false
"Reference Handler" true
"QuantumRenderer-0" true
nil
user=> (System/getProperty "java.home")
"/home/vlaaad/software/jdk-11.0.1"
Same on java 8:
clj -Sforce -Sdeps '{:deps {cljfx {:mvn/version "1.6.3"}}}'
Clojure 1.10.1
user=> (require 'cljfx.api)
nil
user=> (doseq [t (keys (Thread/getAllStackTraces))] (prn (.getName t) (.isDaemon t)))
"AWT-XAWT" true
"QuantumRenderer-0" true
"Finalizer" true
"JavaFX Application Thread" false
"Java2D Disposer" true
"main" false
"Reference Handler" true
"Thread-1" true
"Signal Dispatcher" true
nil
user=> (System/getProperty "java.home")
"/opt/jdk1.8.0_231/jre"

vlaaad 2020-02-14T10:08:10.053Z

Don't really know what's happening, but you can create a promise and deref it in main to block until app is done. And closing an app may deliver to this promise.

vlaaad 2020-02-14T10:24:15.055100Z

@jlmr tried in a lein project. project.clj:

(defproject uberjar-cljfx "boop"
  :dependencies [[cljfx "1.6.3"]]
  :main uberjar-cljfx.main
  :profiles {:uberjar {:aot :all
                       :injections [(javafx.application.Platform/exit)]}})
src/uberjar_cljfx/main.clj :
(ns uberjar-cljfx.main
  (:require [cljfx.api :as fx])
  (:gen-class))

(defn -main []
  (fx/create-app
   (atom {})
   :event-handler prn
   :desc-fn (fn [_]
              {:fx/type :stage
               :showing true
               :scene {:fx/type :scene
                       :root {:fx/type :v-box
                              :padding 50
                              :children [{:fx/type :label
                                          :text "Hello world"}]}}})))
Then executed this:
$ lein uberjar                          
Compiling uberjar-cljfx.main
Created /home/vlaaad/projects/uberjar-cljfx/target/uberjar-cljfx-boop.jar
Created /home/vlaaad/projects/uberjar-cljfx/target/uberjar-cljfx-boop-standalone.jar
$ java -jar target/uberjar-cljfx-boop-standalone.jar
A window appeared and everything was fine

jlmr 2020-02-14T10:27:54.055400Z

What’s the :injections [(javafx.application.Platform/exit)] for

jlmr 2020-02-14T10:27:55.055600Z

?

vlaaad 2020-02-14T10:28:07.055800Z

https://github.com/cljfx/cljfx/issues/17

jlmr 2020-02-14T10:31:15.056500Z

Ok that’s clear. Now I have to figure out how to do somethings similar with depstar.

vlaaad 2020-02-14T10:32:20.056900Z

oh, you also use tools-deps, nice!

vlaaad 2020-02-14T10:32:40.057300Z

well, if you don't do aot, everything should be fine

vlaaad 2020-02-14T10:33:44.058400Z

doing aot is pretty easy, just call (compile 'symbol-of-main-ns) as a part of your build step, and after that (javafx.application.Platform/exit)

vlaaad 2020-02-14T10:34:05.058700Z

ah, depstar does aot for you automatically

jlmr 2020-02-14T10:37:08.059200Z

Disabled aot and now it works!

jlmr 2020-02-14T10:37:09.059400Z

thanks

jlmr 2020-02-14T10:37:39.060Z

also made sure i use the same jdk for building and running the jar, that seemed to have fixed the daemon thread thing