@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?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"
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.
@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 fineWhat’s the :injections [(javafx.application.Platform/exit)]
for
?
Ok that’s clear. Now I have to figure out how to do somethings similar with depstar.
oh, you also use tools-deps, nice!
well, if you don't do aot, everything should be fine
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)
ah, depstar does aot for you automatically
Disabled aot and now it works!
thanks
also made sure i use the same jdk for building and running the jar, that seemed to have fixed the daemon thread thing