Report about migrating a legacy JavaFX Script 1.3.1 application to ScalaFX

39 views
Skip to first unread message

Alain FAGOT BÉAREZ

unread,
Aug 14, 2012, 4:55:55 PM8/14/12
to scalaf...@googlegroups.com, scala...@googlegroups.com
Dear All,

Some three months ago I wrote about my first migration project: from VisageFX to ScalaFX. It was a rather simple project with about ten classes summing up to one thousand lines of code. Yet it was significant to me because I then had no notion of Scala. Over three days I had my application running.

Since then I have been working intermittently on my other migration project: from JavaFX Script 1.3.1 to ScalaFX. There are more than one hundred classes, making use of some advanced features such as various skins in order to have different behaviours for the same component, depending on where it is used in the layout. Being now at about 60% of the migration, I reached an interesting milestone: the first ScalaFX independent module is functionally equivalent to its JavaFX Script 1.3.1 counterpart.

I'll try to list here some of the lessons learned down the way:

* Lesson 1: NPE is striking back! Again and again! 
While the runtime used to protect me against these by skipping the irrelevant instructions and retrying later on the unsuccessful bindings and som any other nice compiler optimizations... I have to take care again about the correct sequence of variable initializations. This is of critical relevance since the init and postinit blocks do not exist anymore.

* Lesson 2: there is no binding on functions
Not that I was using this feature a lot but, where it was used, I had to find some way to listen for changes on the properties used in the functions in order to fire an explicit call in the change listener.

* Lesson 3: my ScalaFX components cannot be retrieved from the containers' content
What gets stored in there is the JavaFX delegate. This becomes especially critical when it comes to custom controls. These have to extend from the JavaFX class, thus losing some of the facilities about handling the properties and bindings. On the other hand, I can maintain a duplicate of the children collection keeping a grip on my ScalaFX objects in order to refer to them when in need to perform some "business" logic.

* Lesson 4: the syntax is similar... yet not that much
Aside from renaming all "def" to "val" and "function" to "def", there not much that could be automated in the translation process. Well... I also made an automatic replacement of "= bind" with "<==" but I still had to review much of these expressions. My main nightmare has been the change from "blocksMouse = true" to "mouseTransparent = false", which has many other subtle implications... Many of them, I think I did not get right yet!

* Lesson 5: the sizing of the components seems to follow a rather different strategy
This first was a great preoccupation since my layout didn't look like expected at all. But after inspecting my scenegraph through the Scenic View tool, I discovered that my components had their preferred size smaller than their computed minimal values. It might well be that my original code was not really strict about the three sizes: minimal, preferred and maximal. But from now on, I would not code without these three concerns in mind. It is quite comfortable to know I have such a precise control over the sizing of my components.

* Conclusion

When I first read, some eighteen months ago, that JavaFX2.0 was an easy goal to migrate legacy JavaFX 1.3.1 applications since "JavaFX Script code is almost Java code", I joined Stephen Chin in the Visage team in the hope for maintaining a less verbose syntax for my code. However when I read later on some of the demo code for ScalaFX, I could not help noticing the syntax similarities. When considering my main difficulty in wrapping the VisageFX components was the lack of tooling to support our task... I could not resist the call of an IDE to use along with Scala.

Thanks to the work by the 19 contributors, I found until now all the components I needed to turn my codebase from deprecated to up-to-date.

Best regards,
Alain

Stephen Chin

unread,
Aug 14, 2012, 6:36:20 PM8/14/12
to scala...@googlegroups.com, scalaf...@googlegroups.com
That is very good feedback…  some thoughts inline.

On Aug 14, 2012, at 3:55 PM, Alain FAGOT BÉAREZ <alain.fag...@gmail.com> wrote:

Dear All,

Some three months ago I wrote about my first migration project: from VisageFX to ScalaFX. It was a rather simple project with about ten classes summing up to one thousand lines of code. Yet it was significant to me because I then had no notion of Scala. Over three days I had my application running.

Since then I have been working intermittently on my other migration project: from JavaFX Script 1.3.1 to ScalaFX. There are more than one hundred classes, making use of some advanced features such as various skins in order to have different behaviours for the same component, depending on where it is used in the layout. Being now at about 60% of the migration, I reached an interesting milestone: the first ScalaFX independent module is functionally equivalent to its JavaFX Script 1.3.1 counterpart.

I'll try to list here some of the lessons learned down the way:

* Lesson 1: NPE is striking back! Again and again! 
While the runtime used to protect me against these by skipping the irrelevant instructions and retrying later on the unsuccessful bindings and som any other nice compiler optimizations... I have to take care again about the correct sequence of variable initializations. This is of critical relevance since the init and postinit blocks do not exist anymore.
I was prototyping using some static classes with "Bindings.select" calls internally.  It gets around this problem since you can bind to objects that are null or non-existent, but means we need a second wrapper class for everything.


* Lesson 2: there is no binding on functions
Not that I was using this feature a lot but, where it was used, I had to find some way to listen for changes on the properties used in the functions in order to fire an explicit call in the change listener.
Doesn't the advanced binding API take care of this case?


* Lesson 3: my ScalaFX components cannot be retrieved from the containers' content
What gets stored in there is the JavaFX delegate. This becomes especially critical when it comes to custom controls. These have to extend from the JavaFX class, thus losing some of the facilities about handling the properties and bindings. On the other hand, I can maintain a duplicate of the children collection keeping a grip on my ScalaFX objects in order to refer to them when in need to perform some "business" logic.
Theoretically all the ScalaFX proxies are stateless, and the implicit conversions should automatically convert from the JavaFX classes (delegates or otherwise) back to ScalaFX when you access a ScalaFX feature.  If this is not working in some cases, we should treat it as a bug and fix it.


* Lesson 4: the syntax is similar... yet not that much
Aside from renaming all "def" to "val" and "function" to "def", there not much that could be automated in the translation process. Well... I also made an automatic replacement of "= bind" with "<==" but I still had to review much of these expressions. My main nightmare has been the change from "blocksMouse = true" to "mouseTransparent = false", which has many other subtle implications... Many of them, I think I did not get right yet!
I few of us have big JavaFX 1.3 apps, but I think the better approach is rewrite and take advantage of new functionality.



* Lesson 5: the sizing of the components seems to follow a rather different strategy
This first was a great preoccupation since my layout didn't look like expected at all. But after inspecting my scenegraph through the Scenic View tool, I discovered that my components had their preferred size smaller than their computed minimal values. It might well be that my original code was not really strict about the three sizes: minimal, preferred and maximal. But from now on, I would not code without these three concerns in mind. It is quite comfortable to know I have such a precise control over the sizing of my components.
Layout changed quite a bit in 2.0...


* Conclusion

When I first read, some eighteen months ago, that JavaFX2.0 was an easy goal to migrate legacy JavaFX 1.3.1 applications since "JavaFX Script code is almost Java code", I joined Stephen Chin in the Visage team in the hope for maintaining a less verbose syntax for my code. However when I read later on some of the demo code for ScalaFX, I could not help noticing the syntax similarities. When considering my main difficulty in wrapping the VisageFX components was the lack of tooling to support our task... I could not resist the call of an IDE to use along with Scala.
Glad that ScalaFX has worked out for your project.  Visage still has a place, but it is a much larger undertaking because it has its own compiler, tools, plug-ins, etc.  Latching on to Scala, which has an established community and tooling is much faster.


Thanks to the work by the 19 contributors, I found until now all the components I needed to turn my codebase from deprecated to up-to-date.

Best regards,
Alain

Cheers,
--Steve
blog: http://steveonjava.com

Reply all
Reply to author
Forward
0 new messages