人生、気合いと具合 - blog

タグ:javafx

This post is written as 6th in JavaFX Advent Calendar 2012.

JavaFX application runs also as Java applet and java web start.
With javafxpackager, you can make executable jar, applet, java web start.

However, there was a small trap, I was trapped, I write about it.

Since I made presentation document for the 8th JavaFX workshop, I was trying to publish it as an applet.
However, the applet did not run. I look at the Java console, the error seems to have occurred in the load method of FXMLLoader.

I think I will look at the source of OpenJFX, but there was no FXMLLoader.java.
Is not been publishing all the source of OpenJFX?

Since it can not be helped, I was looking closely at the stack trace once more, getDeclaredFields method have failed due to security.
When I look further, which line of FXML file is invalid, it was written to the error message. So when I try to check inside FXML, "fx:id" attribute is doubtful.

It seems to be an error because it uses the getDeclaredFields method in the process of setting a field of the controller class, an instance of the Control that has the fx:id attribute.
I think so, the application using FXML would not be able to run most of the time.I have heard it is okay that @FXML field is private.
However, if @FXML field is public, can access it by getFields method, and no problem in terms of security.That means, I think this is a bug.
If the applet is signed, then it probably runs. But I think the signature is required is not good.

When I examine, it seemed to be registered as a bug in JIRA. RT-23622
However, Fix Version/s is "Lombard", they won't fix it until JavaSE8?

So, (it isn't much sense) I tried to display only Label, but there was a further trap.

Using SceneBuilder, I operated

Put Label -> Change Font -> Copy & Paste

then, same error occured.
When I look at FXML, Label tag which was copied had font attribute like font="$x1", and original Label tag has fx:id attribute like fx:id="x1".
If JavaFX Control having a child tag is copied, the child tag automatically create fx:id attribute?
Then, Although I am not supposed to create fx:id attribute, same error occured.

In conclusion, if you want to run the application using FXML as Applet, we seem to be (almost) the signature is a requirement. (And perhaps JavaWebStart)
I hope that they fix this bug at JavaFX2.2 minor version up...

このエントリは、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のマイナーバージョンアップとかで直してくれないかなぁ...

このページのトップヘ