Thursday, January 26, 2012

JavaFX 2.1: JavaFX 2's @DefaultProperty Annotation with FXML

The JavaLobby/DZone syndicated version of my blog post Focus on JavaFX 2 FXML with NetBeans 7.1 was recently published and Mihai Dinca-panaitescu (author of DZone article Tuning Your Java VM) added an interesting and useful feedback comment. Specifically, he stated:
I needed to put <children> tag in JavaFx2Menus.fxml

before MenuBar tag.

otherwise an Exception is raised:

javafx.fxml.LoadException: javafx.scene.layout.VBox does not have a default property.

I'm glad that Mihai posted this response for several reasons. First, it will help anyone else reading my post to be aware of that issue. Second, it has allowed me to speculate on the cause of this message in this blog post.

My first thought at reading Mihai's comment was that perhaps the difference was that I was using JavaFX 2.1 (still beta) when I ran the example and perhaps Mihai was using production-ready JavaFX 2.0. Assuming this is the case, the next question was, "What changed in JavaFX 2.1 to make this example work without the children element? Feeling that I need to balance out recent cogitations on my blog with rampant speculation, I decided to do some of that speculation in this post. I speculate that JavaFX 2.1 has applied @DefaultProperty to more controls than in JavaFX 2.0 and that VBox was one of these which now has it applied.

The Javadoc description of the DefaultProperty annotation states, "Specifies a property to which child elements will be added or set when an explicit property is not given." The "Default Properties" section of the highly useful Introducing FXML adds:

A class may define a "default property" using the @DefaultProperty annotation defined in the javafx.fxml package. If present, the sub-element representing the default property can be omitted from the markup.

For example, if the Group class were to define a default property of "children", the <children> element would no longer be required.

My speculation was that JavaFX 2.1 had added @DefaultProperty annotation to the VBox (among others) control. Although the Javadoc for JavaFX 2.1's VBox does not show this annotation applied, the JavaFX 2.1 Javadoc documentation for its parent class, Pane, does indicate the presence of the annotation (and the @DefaultProperty annotation is itself marked @Inherited). The next image shows Pane JavaFX 2.0 and JavaFX 2.1 Javadoc versions side-by-side.

The circled portion of the JavaFX 2.1 API documentation for Pane shows that this control (and controls inheriting from it such as VBox) have children as the component's default property. This explains why children must be explicitly specified in JavaFX 2.0, but is optional for VBox in JavaFX 2.1.

The @DefaultProperty annotation has also been applied to the MenuBar control in JavaFX 2.1. Comparing Javadoc for MenuBar in JavaFX 2.0 to the Javadoc for MenuBar in 2.1 proves this. The next screen snapshot shows them side-by-side.

The circled portion of the JavaFX 2.1 API documentation shows that an annotation has been added in JavaFX 2.1 to the MenuBar class to specify that the default sub-element for MenuBar is now "menus" in JavaFX 2.1. Incidentally, Menu also has a new @DefaultProperty with "items" as its default property. With the @DefaultProperty annotation of MenuBar, I decided to try removing the <menus> elements from my FXML and this appeared to work fine, removing a couple lines of XML from my source FXML and allowing many lines to be less indented. It worked and I had a little more concise of an FXML representation of the same menus application layout.

The more widespread use of the @DefaultProperty annotation is a small, but very welcome addition to JavaFX 2.1. Although adding opening and closing "children" tags adds only two lines per use, it does increase the indentation as well for a well-formatted FXML file. FXML can be appealing because of its visual similarity to the presentation itself and having fewer "extra" lines for common cases can make it even more readable. Although the @DefaultProperty annotation itself was available in JavaFX 2.0, it's much more widely applied and can be more widely used in FXML when using JavaFX 2.1.

No comments: