このエントリは、JavaFX Advent Calendar 2012 の6日目です。

JavaFXのアプリケーションは、普通に作ればアプレットやJava Web Startとしても動作します。
そしてjavafxpackagerを使えば、実行可能jar、Applet、JavaWebStart、全部まとめて作ってくれます。

しかし微妙に罠があり、ちょっとハマったのでその件について。

先日の第8回JavaFX勉強会で発表した資料はScalaFXで作成したので、アプレットとして公開しようと思ったわけです。
しかし、なぜか動かない。Javaコンソールを見てみると、どうもFXMLLoaderのloadで落ちてる模様。

ちょっとソースでも見てみるかと思いOpenJFXのソースをのぞいてみると、なぜかFXMLLoader.javaが無い。あれー?OpenJFXってまだ全ソース公開にはなってなかったんだっけ?
しょうがないのでもう一回スタックトレースをよく見てみると、getDeclaredFieldsメソッドがセキュリティ的にはじかれている。
まあAppletだからそういうもんか、と思いながらさらに見ると、FXMLファイルのどの行がダメなのか、エラーメッセージにちゃんと出ている。そこで、FXMLの中を確認してみるとどうやら fx:id 属性があやしい。

つまりfx:idがついたコントロールのインスタンスを、コントローラクラスのフィールドに設定する処理でgetDeclaredFieldsを使っているからダメってことらしい。それってFXML使ってたら大抵ダメってことでは。
そういえば@FXMLをつけるフィールドはprivateでもいいよーというのを聞いた事があるような気が。
とはいえ、publicにしておけばたぶんgetFieldsで取れて、セキュリティ的にも大丈夫なんじゃないかなーと考えると、これバグなんじゃね?という気もする。
署名してやればできそうな感じだけど、署名が必須ってのもどうかという。

というわけでいろいろ調べてみたら、OpenJFXのJIRAにそれらしきものが。 RT-23622
やはりそういうことらしく、バグとして登録されているようだ。しかしFix Version/sが"Lombard"になっているということは、Java8まで修正するつもりは無いってこと?
※英語力がアレなので気になる人は自分でちゃんと読んでください...

じゃあ、(あまり意味はないけど)単純にLabelだけ表示するとかなら大丈夫かな?と試してみると...さらに罠。

単にLabelを並べるだけなら確かに大丈夫。しかしSceneBuilderで、
  Label置く → フォント変更 → コピペ
とやって複数Labelを作ると、やはり同じ現象で失敗。
FXMLを見てみると、コピーして作った方のフォント指定は、font="$x1"という属性なっていて、コピー元のfontタグに fx:id="x1" という属性が。
子タグがあるコントロールをコピペすると、元のコントロールの子タグに自動でfx:idがつく?ってことのようで、そうなると自分ではfx:idを設定したつもりはないけどこの現象で落ちるということに。うーん。

結論として「FXMLを使うアプリをAppletとして動かす場合、(ほぼ)署名が必須」ということになるらしい。(たぶんJavaWebStartも)
2.2のマイナーバージョンアップとかで直してくれないかなぁ...