Exception in thread "main" java.lang.ExceptionInInitializerError (Clojure)


I'm trying to deploy a Clojure app in both .jar and .war format. So far I've successfully deployed a .jar; I'm working on the .war. The app is just a test app which is meant to demonstrate some of the capabilities of Clojure and JavaFX. I'm meaning to deploy it via AWS Elastic Beanstalk to a website I've only just begun to set up. At the moment, the app simply displays a bunch of blurred circles moving around a 600x600 stage for 40 seconds. However, even though the application runs successfully for those 40 seconds, it always terminates suddenly after those 40 seconds of animation. My project.clj file looks like this:

(defproject clojurefx/arg "0.0.10-SNAPSHOT"
  :description "Helper functions and probably a wrapper to simplify usage of JavaFX in Clojure.
                This is meant to be used with Java 8.
  :url "https://www.github.com/zilti/clojurefx" ; my project is essentially forked from this project
  :lein-release {:deploy-via :clojars}
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]]
  :plugins [[lein-marginalia "0.7.1"]
  :profiles {:dev {:dependencies [[midje "1.6-beta1"]]}}
  :main clojurefx.arg.splashpage
  :aot [clojurefx.arg.splashpage])

This is where the -main function lives:

(ns clojurefx.arg.splashpage
    [clojure.reflect :as clj-r]
    [clojure.stacktrace :as stacktrace]
    [clojurefx.arg.core :as core]
    [clojurefx.arg.core :refer [deffx]]
    (javafx.scene.text Font FontPosture FontWeight Text)

(defn -main [& args]
  (println "Up and running! The arguments supplied were: " args))

;=====JavaFX visual objects initialized and displayed with the code below=====
(deffx rt group)
(deffx scn scene
  :width 600
  :height 600
  :root rt
  :fill (. Color BLACK))
(deffx stg stage
  :title "Colorful Circles"
(dofx (.show stg)) ; shows the JavaFX window with the circle animation
(dofx (.play tmln)) ; play 40s of animation

As I said, the animation plays fine for 40 seconds, but I get the following exception at that point:

-> Exception in thread "main" java.lang.ExceptionInInitializerError
->   at clojure.main.main(main.java:37)
     ... ; a long list of traced errors
-> Caused by: java.lang.IllegalStateException: Toolkit not initialized
     ... ; a long list of traced errors
-> Exception in thread "Thread-4" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1}
     ... ; a long list of traced errors
->   at java.lang.Thread.run(Thread.java:724)

I'm thinking that it might have something to do with the way JavaFX threads work. Maybe there's some sort of timeout when the animation stops running. By comparison, there's no timeout when I comment out the main clojurefx.arg.splashpage and :aot [clojurefx.arg.splashpage]) in project.clj and just manually copy, paste, and evaluate the code from the splashpage.clj file into a REPL. Also, when I put the code for the JavaFX object initialization and display in a function, let's say, (init-stage), such that the code isn't evaluated at runtime until the function is explicitly called, the "timeout" begins immediately after the JVM is launched and the (-main) function is called.

Thoughts? I realize that the intersect of the set of people who know Clojure and the set of people who know JavaFX 8 is incredibly small...


I there's another related problem. Now when I try to deploy a .jar file, the file is created successfully like so:

Alexanders-MacBook-Pro:cljfx-arg alexandergunnarson$ lein uberjar
Compiling clojurefx.arg.splashpage
Created /Users/alexandergunnarson/.lein/cljfx-arg/target/arg-0.0.10-SNAPSHOT.jar
Created /Users/alexandergunnarson/.lein/cljfx-arg/target/arg-0.0.10-SNAPSHOT-standalone.jar

But when I run the .jar on my Mac (either the standalone or not), OS X says "The file cannot be launched." Also, the point where the .jar is actually created is the point where either the animation stops or I quit the main app that's displaying the animation (the JVM).

11/14/2013 12:07:53 AM

Accepted Answer

The answer to this is that, for certain JavaFX classes to be imported, the following needs to be called:

(defonce force-toolkit-init (javafx.embed.swing.JFXPanel.))

The defonce is used to make sure the toolkit is not re-initialized somehow.

It's probably advisable to declare this even before importing any JavaFX classes at all.

8/24/2014 2:54:30 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow