JavaFx: my experience so far - No Fluff Just Stuff

JavaFx: my experience so far

Posted by: Andres Almiray on August 7, 2008

The long awaited date arrived, the JavaFx SDK (a preview as you probably know by now) was released on July 31st, I then jumped into the site to download it. Imagine my surprise when I found out that the SDK comes bundled with NetBeans 6.1 and it is supposed to work on Windows and OsX only, which means me and my Mandriva laptop would have to wait. Along comes Weiqi Gao demonstrating that is possible to run the OsX version on Linux, sadly the link to the zip file is not available due to some limit restriction, whatever, so I'm back into square one. Sure I could switch to Windows (why on earth would I want to do that on the first place?) and install NetBeans, but not being a NetBeans user (yet) I stayed away from that option.

Luckily for me the openjfx-compiler project seems to include all the tools and files needed to get you up and running. A quick svn checkout and Ant build and I have the basics to start hacking JavaFX Script apps (or so I thought). Browsed the demos, run a few to assert that my jfx distro was working, so far so good.

Those of you that have followed this blog in the past now that I'm a Groovy fan (also a Groovy committer), which means I was bit (nah, a lot!) disappointed when Sun unveiled JavaFX Script during JavaOne 2007 and posted this on its FAQ. That single answer prompted the appearance of GraphicsBuilder into the scene, which I believe demonstrates that Groovy really is capable of aiding Swing developers (and in due time, content authors) to create desktop applications and RIAs with ease, so take the following opinions with a grain of salt.

Alright, where to start? JavaFx exposes your regular Java2D shapes plus two more from Swinglabs' Swingx (Star & Morph), GraphicsBuilder has those shapes plus a couple more, why not try to expose those extra shapes to the JavaFx crowd as well? so shapes are it, but there is a catch, instead of following the "traditional" path of creating a custom node (like the one shown by Joshy here) I will implement those shapes as if the JavaFx team has done it with the current ones, this means two classes must be created for each shape: an SceneGraph node and a JavaFx node. Also decided to take this chance to refactor the original shapes from GraphicsBuilder into their own package/project (more on that later), so in the end the work was split in three files per shape.

We need a project for this experiment, giving that these shapes will be used by GraphicsBuilder, SceneGraph users and JavaFx nodes, each portion will live in its own sub-project (smaller jars after all), prompting for a quick Maven2 module setup (I'm a Maven2 junkie). Here I faced the first obstacle, the openjfx-compiler does not come with a maven plugin (nor I could find one out there) but it does include an Ant task. Armed with the knowledge of the AntRun plugin and a couple of minutes hacking xml, the javafxc task was grafted into the pom. For some strange reason multiple execution targets (bound to different phases) did not work as advertised (there is also few official documentation on the matter, shame), and the javafxc task refused to accept references to a maven path (ugh!). I had to switch to Ant completely after expending some time fixing these issues, my frustration level filled up a bit.

Project 1 of 3, basic geometry, was pretty straight forward to configure. Added a couple of missing no-arg constructors here, added some missing property accessors there, fixed an embarrassing bug in the Balloon shape and it was done. Project 2 of 3, SceneGraph nodes, was also easy to configure, all nodes followed the code laid out in SGRectangle, which is very simple in nature. The problem comes that the current API uses the "com.sun" namespace in its package, meaning it *may* change in the future, making my code a bit brittle, and that it also relies on some magic package protected utility methods (ugh! I hate package protected methods), had to resort to reflection tricks to call those methods (frustration goes one level up, c'mon Sun, can't you follow the open-closed principle? it is not as we will never require a custom shape built following your own code and APIs!).

Finally reached the third project, JavaFx nodes, the meat of the experiment. Making a JavaFx node based on a SGNode turned out to be simpler than I thought, at least the code from Rectangle showed it to be that way. For every such node you need to define the backing SGNode by overriding a building function, an attribute for each property you'd like to expose along with a replace function that will update the backing node's property every time the attribute changes value, like a PropertyChangeListener does. Here is the code from the Cross shape so that you know what I mean

A few things caught my attention. JavaFx Script seems to support optional return keyword, in a similar fashion as Groovy does (guess this is +1 for Groovy abstractions per the jfx FAQ). It also supports type conversion using the as keyword, another feature found in Groovy as well (plus Groovy's as can do more than that, don't know about jfx's), so I guess that is another +1 for Groovy too. The function getSGCross() is there just to return the correct type of node, remember that JavaFx is statically typed, whereas Groovy supports both optional typing, in other words you may specify types whenever they make sense (that is +1 for Groovy in my book but others may disagree). Attribute definition plus replace function looks pretty similar to GORM's dsl mapping, I mean Groovy is flexible enough to let you define a mixture of closures, maps and lists to get the same result. Factor in ASTTransformations/@Bindable in the 1.6 beta branch and I think we have all the tools to cook an attribute mapping dsl (a future +1 for Groovy). Coming into jfx's defense that code is simple and readable enough, then again there is nothing much to do here than instantiating a bean and setting event listeners on each property, definitely easier than doing it in straight Java.

The code is done, now it must be tested somehow, and by tested I mean your run-of-the-mill QA testing, yup manual/visual testing (how do you assert in an automatized way that a drawing is the expected one?), launching a Frame with each shape as the content sounds like the way to go. But first you have to make sure that the setup is right and a basic JavaFx example can be run and displayed, no? here comes the next obstacle and frustration goes up one more level. Search for "javafx HelloWorld" and yout will most likely land on this page, want to know what happened? it doesn't work! care to know why? well the powers-that-be dictated that the JavaFx API required some slight changes one month (!!) prior to its impending release (when we still thought it was going to be a full release, not a pre-release), so that many examples out there were immediately renderered useless as they have not been updated to the latest API (some of those changes were truly needed, so we will have to deal with stale documentation for the time being). Jim Weaver's JavaFx blog gave me the answer I was looking for, a couple of minutes later had a HelloWorld titled frame with some Text (not a Label mind you) as content. Then it was a simple matter of replacing the Text node with the new shapes and see it they were displayed as expected. Here came another surprise, every single shape has sensible defaults for each property (Java side), so I expected to be able to create, say a Cross, with the following code

Right, it didn't work, I forgot to set either a stroke or a fill property (my fault), without any of those there is simple nothing to draw (smart tool), alright, so added a value for fill and got another blank frame! It turns out that you must specify a value for each attribute (??), remember I followed the same steps as the official JavaFx shapes so this came as a big surprise to me. Unless there is a shortcut I'm missing this is a big -1 for JavaFx (+1 in Groovy's GraphicsBuilder, we are happy with default values), so the code was changed to

So far I have a high frustration level with JavaFx, it does help a bit if you want to create toy apps and quick drawings, but I can't see myself coding a Twitter client nor a desktop business application with it in the near future, I'll stick with Groovy's Swing(X)Builder+GraphicsBuilder. On the language side of things I said before that both JavaFx Script and Groovy are pretty close, the only reason to consider JavaFx Script is that it allows you to bind to any expression (like for loops for example) which is pretty powerful, well @shemnon blogged some time ago that Groovy has an alternative to this feature, guess I won't be needing JavaFx Script after all ;-)

The experiment will continue, I hope to find some tricks that only JavaFx can achieve, oh and I'm still waiting for JWebPane to be released, please Sun don't make us wait another year for it.

</rant>

PD: at some point I typed something that only made sense to me but the compiler clearly said otherwise
JavaFxTestSuite.fx:148: Sorry, I was trying to understand a script item but I got confused when I saw '}'.
Andres Almiray

About Andres Almiray

Andres is a Java/Groovy developer and a Java Champion with more than 20 years of experience in software design and development. He has been involved in web and desktop application development since the early days of Java. Andres is a true believer in open source and has participated on popular projects like Groovy, Griffon, and DbUnit, as well as starting his own projects (Json-lib, EZMorph, GraphicsBuilder, JideBuilder). Founding member of the Griffon framework and Hackergarten community event. https://ch.linkedin.com/in/aalmiray

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »