Wednesday Feb 06, 2013

Source Code for JavaFX Scoreboard Now Available

For the last few years, many of the JavaFX related blog posts found here have made reference to all or parts of a Scoreboard application written in JavaFX.  For example, the entry prior to this contains a video demonstrating how this Scoreboard application can be run on an embedded device such as a Raspberry Pi and displayed on an ordinary flat screen TV.

Alongside those posts, some have asked for access to the source code to this application.  I've always felt uncomfortable releasing the code, not under the delusion that it has any commercial value, but rather because, let us say, it was not developed with the strictest software engineering standards in mind.  Having gotten over those insecurities (not really), I've decided to place it in a java.net project called javafx-scoreboard.

If you are interested in gaining access to this code you'll need to do the following:

  1. Register on http://home.java.net  to get a java.net account.  It's free and painless.  If you already have an account, terrific! You can skip this step.
  2. Send an email to me at james.connors@oracle.com  asking to be added to the javafx-scoreboard project.  Include your java.net username in the email.
  3. Once you're added to the project, you'll have download access to the contents of the project.

For grins, here's document that gives an overview of the Scoreboard application.

Cheers.

Saturday Dec 22, 2012

A Raspberry Pi / JavaFX Electronic Scoreboard Application

As evidenced at the recently completed JavaOne 2012 conference, community excitement towards the Raspberry Pi and its potential as a Java development and deployment platform was readily palpable.  Fast forward three months, Oracle has announced the availability of a JDK 8 (with JavaFX) for Arm Early Access Developer Preview where the reference platform for this release is none other than the Raspberry Pi.

What makes this especially interesting to me is the addition of JavaFX to the Java SE-Embedded 8 platform.  It turns out that at $35US, the (not so) humble Raspberry Pi has a very capable graphics processor, opening up a Pandora's box of graphics applications that could be applied to this beloved device.  As a first step in becoming familiar with just how this works, I decided to dust off a two year old JavaFX scoreboard application, originally written for a Windows laptop, and see how it would run on the Pi.  Low and behold, the application runs unmodified (without even a recompile).

The video that follows shows how an ordinary flat screen TV can be converted into a full screen electronic scoreboard driven by a Raspberry Pi.  The requirements for such a solution are incredibly straightforward: (1) the TV needs access to a power receptacle and (2) it must be within range of a WiFi network in order to receive scoreboard update packets.  The device is so compact and miserly from a power perspective, that we velcro the Pi to the back of the TV and get our power from the TV's USB port. If you can spare a few moments, it just might be worth your while to take a look.



Tuesday Jun 21, 2011

Observations in Migrating from JavaFX Script to JavaFX 2.0

Observations in Migrating from JavaFX Script to JavaFX 2.0

Introduction

Having been available for a few years now, there is a decent body of work written for JavaFX using the JavaFX Script language. With the general availability announcement of JavaFX 2.0 Beta, the natural question arises about converting the legacy code over to the new JavaFX 2.0 platform. This article reflects on some of the observations encountered while porting source code over from JavaFX Script to the new JavaFX API paradigm.

The Application

The program chosen for migration is an implementation of the Sudoku game and serves as a reference application for the book JavaFX – Developing Rich Internet Applications. The design of the program can be divided into two major components: (1) A user interface (ideally suited for JavaFX design) and (2) the puzzle generator. For the context of this article, our primary interest lies in the user interface. The puzzle generator code was lifted from a sourceforge.net project and is written entirely in Java. Regardless which version of the UI we choose (JavaFX Script vs. JavaFX 2.0), no code changes were required for the puzzle generator code.

The original user interface for the JavaFX Sudoku application was written exclusively in JavaFX Script, and as such is a suitable candidate to convert over to the new JavaFX 2.0 model. However, a few notable points are worth mentioning about this program. First off, it was written in the JavaFX 1.1 timeframe, where certain capabilities of the JavaFX framework were as of yet unavailable. Citing two examples, this program creates many of its own UI controls from scratch because the built-in controls were yet to be introduced. In addition, layout of graphical nodes is done in a very manual manner, again because much of the automatic layout capabilities were in flux at the time. It is worth considering that this program was written at a time when most of us were just coming up to speed on this technology. One would think that having the opportunity to recreate this application anew, it would look a lot different from the current version.

Comparing the Size of the Source Code

An attempt was made to convert each of the original UI JavaFX Script source files (suffixed with .fx) over to a Java counterpart. Due to language feature differences, there are a small number of source files which only exist in one version or the other. The table below summarizes the size of each of the source files.

JavaFX Script source file

Number of Lines

Number of Character

JavaFX 2.0 Java source file

Number of Lines

Number of Characters




ArrowKey.java

6

72

Board.fx

221

6831

Board.java

205

6508

BoardNode.fx

446

16054

BoardNode.java

723

29356

ChooseNumberNode.fx

168

5267

ChooseNumberNode.java

302

10235

CloseButtonNode.fx

115

3408

CloseButton.java

99

2883




ParentWithKeyTraversal.java

111

3276




FunctionPtr.java

6

80




Globals.java

20

554

Grouping.fx

8

140




HowToPlayNode.fx

121

3632

HowToPlayNode.java

136

4849

IconButtonNode.fx

196

5748

IconButtonNode.java

183

5865

Main.fx

98

3466

Main.java

64

2118

SliderNode.fx

288

10349

SliderNode.java

350

13048

Space.fx

78

1696

Space.java

106

2095

SpaceNode.fx

227

6703

SpaceNode.java

220

6861

TraversalHelper.fx

111

3095




Total

2,077

79,127


2531

87,800

A few notes about this table are in order:

  • The number of lines in each file was determined by running the Unix ‘wc –l’ command over each file.
  • The number of characters in each file was determined by running the Unix ‘ls –l’ command over each file.
  • The examination of the code could certainly be much more rigorous. No standard formatting was performed on these files.  All comments however were deleted.

There was a certain expectation that the new Java version would require more lines of code than the original JavaFX script version. As evidenced by a count of the total number of lines, the Java version has about 22% more lines than its FX Script counterpart.

Furthermore, there was an additional expectation that the Java version would be more verbose in terms of the total number of characters.  In fact the preceding data shows that on average the Java source files contain fewer characters per line than the FX files.  But that's not the whole story.  Upon further examination, the FX Script source files had a disproportionate number of blank characters.  Why?  Because of the nature of how one develops JavaFX Script code.  The object literal dominates FX Script code.  Its not uncommon to see object literals indented halfway across the page, consuming lots of meaningless space characters.

RAM consumption

Not the most scientific analysis, memory usage for the application was examined on a Windows Vista system by running the Windows Task Manager and viewing how much memory was being consumed by the Sudoku version in question. Roughly speaking, the FX script version, after startup, had a RAM footprint of about 90MB and remained pretty much the same size. The Java version started out at about 55MB and maintained that size throughout its execution.

What About Binding?

Arguably, the most striking observation about the conversion from JavaFX Script to JavaFX 2.0 concerned the need for data synchronization, or lack thereof. In JavaFX Script, the primary means to synchronize data is via the bind expression (using the “bind” keyword), and perhaps to a lesser extent it’s “on replace” cousin. The bind keyword does not exist in Java, so for JavaFX 2.0 a Data Binding API has been introduced as a replacement.

To give a feel for the difference between the two versions of the Sudoku program, the table that follows indicates how many binds were required for each source file. For JavaFX Script files, this was ascertained by simply counting the number of occurrences of the bind keyword. As can be seen, binding had been used frequently in the JavaFX Script version (and does not take into consideration an additional half dozen or so “on replace” triggers). The JavaFX 2.0 program achieves the same functionality as the original JavaFX Script version, yet the equivalent of binding was only needed twice throughout the Java version of the source code.

JavaFX Script source file

Number of Binds

JavaFX Next Java source file

Number of “Binds”



ArrowKey.java

0

Board.fx

1

Board.java

0

BoardNode.fx

7

BoardNode.java

0

ChooseNumberNode.fx

11

ChooseNumberNode.java

0

CloseButtonNode.fx

6

CloseButton.java

0



CustomNodeWithKeyTraversal.java

0



FunctionPtr.java

0



Globals.java

0

Grouping.fx

0



HowToPlayNode.fx

7

HowToPlayNode.java

0

IconButtonNode.fx

9

IconButtonNode.java

0

Main.fx

1

Main.java

0

Main_Mobile.fx

1



SliderNode.fx

6

SliderNode.java

1

Space.fx

0

Space.java

0

SpaceNode.fx

9

SpaceNode.java

1

TraversalHelper.fx

0



Total

58


2

Conclusions

As the JavaFX 2.0 technology is so new, and experience with the platform is the same, it is possible and indeed probable that some of the observations noted in the preceding article may not apply across other attempts at migrating applications. That being said, this first experience indicates that the migrated Java code will likely be larger, though not extensively so, than the original Java FX Script source. Furthermore, although very important, it appears that the requirements for data synchronization via binding, may be significantly less with the new platform.

Thursday May 26, 2011

The Shackles are Off

Today marks an important milestone for JavaFX 2.0.  Prior to this date, only a select few partners had early access privilege to the technology, and for good reason.  During that early access period, the API was in a very fluid state, and from personal experience I can tell you that changes to the JavaFX 2.0 API were done almost on a build-by-build basis.  The announcement of a public beta not only makes the software available worldwide, but also signals that the JavaFX 2.0 API is on much more solid footing.

So check out the javafx.com website for the latest JavaFX 2.0 information.   Three software downloads are now available:

  1. JavaFX 2.0 Beta SDK - the JavaFX functionality needed to develop directly via the command line or with other tools
  2. JavaFX 2.0 Beta Runtime - the runtime environment required for running JavaFX 2.0 applications 
  3. JavaFX 2.0 Beta Plugin for NetBeans IDE 7.0 -  for building, previewing, and debugging JavaFX applications in NetBeans 7.

Sunday Nov 28, 2010

Why I like the New JavaFX

I have a vested interest in seeing the original JavaFX Script based platform prosper. As an early adopter of this technology, a good portion of my life these past few years has been spent developing, blogging and even co-authoring a book on the subject. So when the inevitable demise of JavaFX Script was formally announced, those of us intimately involved did not take it lightly.

Perhaps not unlike yourselves, I’ve viewed the plans to morph JavaFX into a Java API with a bit of skepticism. The new resulting coding paradigm is unquestionably less stylish than its predecessor and can be downright verbose. But the new way grows on you. Having the privilege to experiment with early versions, I’ve come to like the new platform. In fact I like it a lot. Here’s why I think the new JavaFX platform is more attractive:

The community has spoken and it doesn’t feel the need for yet another scripting language. The attempt to lure graphics designers into the Java camp by offering a simplified Rich Internet Application environment never really panned out. Why? First, there already exists a wealth of mature, established RIA scripting alternatives. These address much of what designers need and JavaFX Script is not sufficiently different enough. Second, the clamor to provide RIA capabilities in Java comes from the Java community proper, not the graphics artists. These developers have a lot invested in Java and are not interested in learning a new language. What they want is a Java API with RIA capabilities. By making JavaFX a first class citizen of the Java platform, it goes a long way towards meeting these desires.

The JavaFX API is a more universal solution. By building an API in Java, the opportunity for developers of other dynamic languages (like JRuby and JavaScript) to access JavaFX has been made much easier. Moreover, as the trend to host other languages atop the Java Virtual Machine accelerates, these too will profit from this move.

No more mapping between JavaFX Script and Java. A derivative of Java, one of the touted advantages of JavaFX Script is its ability to seamlessly integrate and leverage the wealth of Java code written already. Indeed a very important benefit, Java/JavaFX Script integration is mostly straightforward; however there are subtle differences between both languages that the developer must take into consideration. Mapping primitive Java data types to JavaFX basic types can be an issue. The original JavaFX classes can only extend Java classes that contain a default (no arguments) constructor. Features familiar to Java programmers, like multidimensional arrays, generics, annotations, and multi-threading have no real equivalent in JavaFX Script. Bringing the JavaFX class libraries directly onto the Java platform eliminates all of these concerns. If you want to use some external Java code, just use it.

Superior Development Environment. Attempting to debug JavaFX Script within an Integrated Development Environment is at best a tricky endeavor and at worst a waste of time. Additionally only NetBeans, and to a lesser extent Eclipse, are the only viable JavaFX Script capable IDEs. As the new JavaFX platform is entirely based on Java, not only is debugging support first rate, the option of choosing other Java IDEs opens up considerably.

The new JavaFX results in, for lack of a better term, more predictability. One of the primary JavaFX Script mechanisms used to define and place graphical assets (Nodes) into the scenegraph is the object literal notation. Being static in nature, the notion of a sequential flow of events inside an object literal may not make much sense. To compensate, JavaFX Script introduces the powerful concept of binding. Without question, binding is very elegant, but it comes with a price. It is not uncommon to see liberal and arguably unnecessary use of binding throughout JavaFX script code.

One can argue that bringing JavaFX to Java should lessen, but certainly not eliminate, the need for binding. Rather than defining objects inside a static initializer, JavaFX API objects are created and defined sequentially by constructor and method calls respectively. By defining objects in an order that makes sense, there is potential to eliminate a certain class of dependencies that were previously resolved with binding.

Improved performance. Although by default the JavaFX compiler generates Java bytes codes from JavaFX Script source, there is a command-line option which can be invoked to save the intermediate Java code that is produced as part of the process. A brief perusal of this source shows that even the most humble of JavaFX Script constructs churns out a lot of complicated Java code. Eliminating this overhead is bound to improve performance in many instances. Furthermore, significant optimizations to memory and static footprint as well as startup time are underway. Finally a new lightweight, fast graphics subsystem, dubbed project prism, will obviate the need to utilize older Java graphics windowing systems.

It’s not how you feel, it’s how you look. A superficial difference, but nonetheless one that should not be underestimated, lies in what your code looks like. In JavaFX Script, graphical Nodes are typically placed in the scenegraph via the definition of object literals. Even the least sophisticated of object literal scenegraphs can be grouped and nested several levels deep, each nesting moving the source code further to the right. Some JavaFX Script code is so indented it leaves little room to write anything of consequence without having to split a line of code into two or more lines.

It didn’t take very long to come up with these talking points. No doubt, as development progresses and more folks jump on board, additional benefits will become apparent.

Wednesday Feb 10, 2010

JavaFX, Sockets and Threading: Lessons Learned

When contemplating how machine-dependent applications might communicate with Java/JavaFX, JNI or the Java Native Interface, having been created for just such a task, would likely be the first mechanism that comes to mind.  Although JNI works just fine thank you, a group of us ultimately decided against using it for a small project because, among others:

  • Errors in your JNI implementation can corrupt the Java Virtual Machine in very strange ways, leading to difficult diagnosis.
  • JNI can be time consuming and tedious, especially if there's a varied amount of interchange between the Native and Java platforms.
  • For each OS/Platform supported, a separate JNI implementation would need to be created and maintained.

Instead we opted for something a bit more mundane, namely sockets.  The socket programming paradigm has been around a long time, is well understood and spans a multitude of hardware/software platforms.   Rather than spending time defining JNI interfaces, just open up a socket between applications and send messages back and forth, defining your own message protocol.  Following are some reflections on using sockets with JavaFX and Java.  For the sake of simplicity, we'll skip the native stuff and focus on how sockets can be incorporated into a JavaFX application in a thread safe manner.

Sockets and Threading

Socket programming, especially in Java, lends itself to utilizing threads.  Because a socket read() will block waiting for input, a common practice is to place the read loop in a background thread enabling you to continue processing while waiting for input at the same time.  And if you're doing this work entirely in Java, you'll find that both ends of the socket connection -- the "server" side and the "client" side -- share a great deal of common code.  Recognizing this, an abstract class called GenericSocket.java was created which is responsible for housing the common functionality shared by "server" and "client" sockets including the setup of a reader thread to handle socket reads asynchronously.

For this simple example, two implementations of the abstract GenericSocket class, one called SocketServer.java, the other called SocketClient.java have been supplied.  The primary difference between these two classes lies in the type of socket they use.  SocketServer.java uses java.net.ServerSocket,  while SocketClient.java uses java.net.Socket.  The respective implementations contain the details required to set up and tear down these slightly different socket types.

Dissecting the Java Socket Framework

If you want to utilize the provided Java socket framework with JavaFX, you need to understand this very important fact:  JavaFX is not thread safe and all JavaFX manipulation should be run on the JavaFX processing thread.1 If you allow a JavaFX application to interact with a thread other than the main processing thread, unpredictable errors will occur.  Recall that the GenericSocket class created a reader thread to handle socket reads.  In order to avoid non-main-thread-processing and its pitfalls with our socket classes, a few modifications must take place.

[1] Stolen from JavaFX: Developing Rich Internet Applications - Thanks Jim Clarke

Step 1: Identify Resources Off the Main Thread

The first step to operating in a thread safe manner is to identify those resources in your Java code, residing off the main thread, that might need to be accessed by JavaFX.  For our example, we define two abstract methods, the first, onMessage(), is called whenever a line of text is read from the socket.  The GenericSocket.java code will make a call to this method upon encountering socket input. Let's take a look at the SocketReaderThread code inside GenericSocket, to get a feel for what's going on.

    class SocketReaderThread extends Thread {

        @Override
        public void run() {
            String line;
            waitForReady();
            /\*
             \* Read from from input stream one line at a time
             \*/
            try {
                if (input != null) {
                    while ((line = input.readLine()) != null) {
                        if (debugFlagIsSet(DEBUG_IO)) {
                            System.out.println("recv> " + line);
                        }
                        /\*
                         \* The onMessage() method has to be implemented by
                         \* a sublclass.  If used in conjunction with JavaFX,
                         \* use Entry.deferAction() to force this method to run
                         \* on the main thread.
                         \*/
                        onMessage(line);
                    }
                }
            } catch (Exception e) {
                if (debugFlagIsSet(DEBUG_EXCEPTIONS)) {
                    e.printStackTrace();
                }
            } finally {
                notifyTerminate();
            }
        }

Because onMessage() is called off the main thread and inside SocketReaderThread, the comment states that some additional work, which we'll explain soon, must take place to assure main thread processing.

Our second method, onClosedStatus(), is called whenever the status of the socket changes (either opened or closed for whatever reason).  This abstract routine is called in different places within GenericSocket.java -- sometimes on the main thread, sometimes not.  To assure thread safety, we'll employ the same technique as with onMessage().

Step 2: Create a Java Interface with your Identified Methods

Once identified, these method signatures have to be declared inside a Java interface.  For example, our socket framework includes a SocketListener.java interface file which looks like this:

   package genericsocket;

   public interface SocketListener {
       public void onMessage(String line);
       public void onClosedStatus(Boolean isClosed);
   }
Step 3: Create Your Java Class, Implementing Your Defined Interface

With our SocketListener interface defined, let's take a step-by-step look at how the SocketServer class is implemented inside SocketServer.java.  One of the first requirements is to import a special Java class which will allow us to do main thread processing, achieved as follows:

   import com.sun.javafx.runtime.Entry;

Next, comes the declaration of SocketServer.  Notice that in addition to extending the abstract GenericSocket class it also must implement our SocketListener interface too:

   public class SocketServer extends GenericSocket implements SocketListener {

Inside the SocketServer definition, a variable called fxListener of type SocketListener is declared:

       private SocketListener fxListener;

The constructor for SocketServer must include a reference to fxListener.  The other arguments are used to specify a port number and some debug flags.

       public SocketServer(SocketListener fxListener,
                int port, int debugFlags) {
            super(port, debugFlags);
            this.fxListener = fxListener;
       }

Next, let's examine the implementation of the two methods which are declared in the SocketListener interface.  The first, onMessage(), looks like this:

       /\*\*
        \* Called whenever a message is read from the socket.  In
        \* JavaFX, this method must be run on the main thread and
        \* is accomplished by the Entry.deferAction() call.  Failure to do so
        \* \*will\* result in strange errors and exceptions.
        \* @param line Line of text read from the socket.
        \*/
       @Override
       public void onMessage(final String line) {
           Entry.deferAction(new Runnable() {

               @Override
               public void run() {
                   fxListener.onMessage(line);
               }
           });
       }

As the comment points out, the Entry.deferAction() call enables fxListener.onMessage() to be executed on the main thread.  It takes as an argument an instance of the Runnable class and, within its run() method, makes a call to fxListener.onMessage().  Another important point to notice is that onMessage()'s String argument  must be declared as final.

Along the same line, the onClosedStatus() method is implemented as follows:

       /\*\*
        \* Called whenever the open/closed status of the Socket
        \* changes.  In JavaFX, this method must be run on the main thread and
        \* is accomplished by the Entry.deferAction() call.  Failure to do so
        \* will\* result in strange errors and exceptions.
        \* @param isClosed true if the socket is closed
        \*/
       @Override
       public void onClosedStatus(final Boolean isClosed) {
           Entry.deferAction(new Runnable() {

               @Override
               public void run() {
                   fxListener.onClosedStatus(isClosed);
               }
           });
       }

Another Runnable is scheduled via Entry.deferAction() to run fxlistener.onClosedStatus() on the main thread. Again, onClosedStatus()'s Boolean argument must also be defined as final.

Accessing the Framework within JavaFX

With this work behind us, now we can integrate the framework into JavaFX.  But before elaborating on the details, lets show screenshots of two simple JavaFX applications, SocketServer and SocketClient which, when run together, can send and receive text messages to one another over a socket.

These JavaFX programs were developed in NetBeans and utilize the recently announced NetBeans JavaFX Composer tool.  You can click on the images to execute these programs via Java WebStart.  Note: depending upon your platform, your system may ask for permission prior to allowing these applications to network.  Source for the JavaFX applications and the socket framework in the form of NetBeans projects can be downloaded here.

Step 4: Integrating into JavaFX

To access the socket framework within JavaFX, you must implement the SocketListener class that was created for this project.  To give you a feel for how this is done with our JavaFX SocketServer application, here are some code excerpts from the project's Main.fx file, in particular the definition of our ServerSocketListener class:

public class ServerSocketListener extends SocketListener {
    public override function onMessage(line: String) {
        insert line into recvListView.items;
    }
    public override function onClosedStatus(isClosed : java.lang.Boolean) {
        socketClosed = isClosed;
        tryingToConnect = false;
        if (autoConnectCheckbox.selected) {
            connectButtonAction();
        }
    }
}

Sparing all of the gory details, the onMessage() method will place the line of text read from the socket in to a JavaFX ListView control which is displayed in the program user interface.  The onClosedStatus() method primarily updates the local socketClosed variable and attempts to reconnect the socket if the autoconnect option has been selected.

To demonstrate how the socket is created, we examine the connectButtonAction() function:

var socketServer : SocketServer;

...

public function connectButtonAction (): Void {
     if (not tryingToConnect) {
            if (socketClosed) {
                socketServer = new
                    SocketServer(ServerSocketListener{},
                    java.lang.Integer.parseInt(portTextbox.text),
                    javafx.util.Bits.bitOr(GenericSocket.DEBUG_STATUS,
                                           GenericSocket.DEBUG_IO));
                tryingToConnect = true;
                socketServer.connect();
            }
        }
    }
 
  
 
  

Whenever the user clicks on the "Connect" button, the connectButtonAction() function will be called.  On invocation, if the socket isn't already open, it will create a new SocketServer instance.  Recognize also that the SocketServer constructor includes an instance of the ServerSocketListener class which was defined above.

To round this out, when the user clicks on the "Disconnect" button, the disconnectButtonAction() function is called.  When invoked, it tears down the SocketServer instance.

   function disconnectButtonAction (): Void {
        tryingToConnect = false;
        socketServer.shutdown();
   }

Conclusion

Admittedly, there's a fair amount to digest here.  Hopefully, by carefully reviewing the steps and looking at the complete code listing, this can serve as a template if you wish to accomplish something similar in JavaFX.


Tuesday Aug 11, 2009

JavaFX Scenegraph Performance Revisited

Prior to the release of JavaFX 1.2, an earlier blog post explained how creating an application with a scenegraph containing a large number of nodes can have performance implications.  That entry was subsequently picked up by Java Lobby and recently posted here.  Partly because it was a few months old, it resulted in a rash of, shall we say, interesting comments.

As one commenter pointed out, the initial results represent JavaFX performance in the 1.0/1.1 timeframe.  JavaFX 1.2 has since been released, and performance has improved substantially.  As a case in point, you can click on the image below to run the clock application.  This same application, developed and compiled with JavaFX 1.1 can be run from the previous blog post.  Further instructions are there

This application, compiled with JavaFX 1.2 and run on identical hardware, uses about a third of the CPU resources of the original version.  Specifically, using OpenSolaris vmstat(1M) to monitor CPU usage, the following average statistics were collected for one minute when the clock display is updated every 10th of a second.  The abbreviations have the following meanings:

  • us = percentage usage of CPU time in user space
  • sy = percentage usage of CPU time in system space
  • id = percentage usage of CPU time idling
  • The sum of (us + sy + id) should approximate 100%.

And here are the utilization numbers:

 Version  # Nodes per Digit
 CPU Utilization
 BulbClockNode JavaFX 1.1
 27 BulbNodes
 us: 22%  sy: 2%  id: 76%
 BulbClockNode JavaFX 1.2  27 BulbNodes  us: 7%  sy: 2%  id: 91%

Yes,  performance has improved significantly and will continue to do so.  In fact, the JavaFX team is promising even better results with the advent of JavaFX 1.3 (code named SoMa), when considerable refining of the underlying architecture will take place.  At this stage in it's lifecycle, it's important to "subscribe" to the JavaFX technology.  Advances are coming fast and furious, and they don't promise to slow down anytime soon.

Friday Jul 24, 2009

Getting the JavaFX Screen Size

In a previous post, I showed one way in which you could size the nodes in your scenegraph relative to the screen size without having to use binding, thus eliminating the potential for a bindstorm.  At the time, the suggestion was to get the screen coordiantes via a call to AWT (Advanced Windowing Toolkit) as follows:

 var AWTtoolkit = java.awt.Toolkit.getDefaultToolkit ();
var screenSizeFromAWT = AWTtoolkit.getScreenSize ();

This currently works for JavaFX Desktop deployments but is far from an optimal solution primarily because it is non-portable.  There is no guarantee that AWT will exist-- in fact I'm pretty sure it will not exist -- in the JavaFX Mobile and JavaFX TV space.  So attempting to utilize the code snippet above in a JavaFX Mobile or TV context will result in an error.  Unfortunately at the time of the original post (Java FX 1.1), I didn't know of a better alternative.

With the advent of JavaFX 1.2, this problem is solved.   A new class called javafx.Stage.Screen  is provided which describes the characteristics of the display.  The API definition of the class can be found here.  So now you can query the JavaFX runtime in a portable fashion to get the screen coordinates as follows:

 import javafx.stage.\*;
 //set Stage boundaries to consume entire screen
 Stage {

fullscreen: true width: Screen.primary.bounds.minX as Integer height: Screen.primary.bounds.minY as Integer ... }

 Cheers.

 

Tuesday Jun 09, 2009

JavaFX Book Arrives!

Since the beginning, the deadlines set forth for producing our book have been aggressive to say the least.  Ultimately, we wanted them to be physically available for sale at the JavaOne 2009 conference.  These things arrived literally hot off the press, having been flown in the opening day of the show.  This effort was not in vain; the results are in.  According to our friends at Digital Guru, JavaFX was definitely the hot topic of the week and JavaFX - Developing Rich Internet Applications was the best seller.  Furthermore as of 9:52AM Eastern Time 09-June-2009, Amazon reports that its sales rank is a very respectable 21,873.  Not bad for just a few days showing.

These sales were no doubt fueled by Larry Ellison's cameo appearance during the first JavaOne keynote.  Clearly hampered by what he could and could not say due to Oracle's pending acquisition of Sun, Larry went out of his way to promote the future of JavaFX.  He must have mentioned it a half dozen times during his 10 minute or so appearance.  On behalf of Eric and the other Jim, thanks bud.



Friday May 01, 2009

JavaFX Book Available Online at Safari.com

Our book, entitled JavaFX: Developing Rich Internet Applications, having gone through the copyedit and proof stages, is now available online at Safari @ http://my.safaribooksonline.com/9780137013524.  Please feel free to provide feedback/comments on any aspect of the book that you've chanced to read.  We're still on schedule to have hardcopies available at the Java ONE show which will start on June 2.  If you plan on attending, please stop by the Addison-Wesley/Pearson/SMI Press booth.  Happy reading.


Monday Apr 06, 2009

Node Count and JavaFX Performance

In a recent blog entry entitled Best Practices for JavaFX Mobile Applications (Part 2), Michael Heinrichs espouses that keeping the scenegraph as small as possible helps JavaFX applications perform optimally. Regardless what version of JavaFX you're using, this is sage advice.  Having spent some time trying to create components for a scoreboard-like application, I was concerned over the amount of CPU time being consumed by the clock component pictured directly below.


You can click on the preceding image to run this mini application via Java WebStart.   By placing your mouse over any of the digits and typing in, via keyboard input, a valid number, you can set the clock.  Clicking on the "START/STOP" text will toggle the clock on and off.  Like many scoreboard clocks, when the time remaining is less than one minute, 10ths of seconds are displayed.  It is during this phase, when digits are being updated every tenth of a second, that this application can be especially taxing.  You can imagine how troublesome this clock might be if it were to be part of say a hockey scoreboard which could have an additional 4 penalty clocks ticking simultaneously.

The major factor affecting performance appears to be the sheer number of nodes in the scenegraph that require recalculation for every clock tick.  For this first implementation, each of the five clock digits is comprised of 27 BulbNodes, (my naming) which are switched on or off depending upon what value needs to be displayed.

In an effort to see how decreasing the node count might effect performance, this second implementation of the clock component uses the same underlying framework, except that each digit is now composed of 7 LED SegmentNodes (my naming again) instead of 27 BulbNodes.   You can run this version of the clock component by clicking on the image that follows.


For our final example, in order to truly minimize node count, each digit is represented by a single ImageView node. When the value of a digit changes, a new Image is displayed.  By caching all of the possible digit values (blank, 0-9) you can very quickly switch images.  No doubt, prettier images can be created, but I think you get the point.  Click on the image that follows to try this version.


The Results

The slower the compute platform, the more pronounced the differences in performance should be.  Thinking along those lines, a very modest 1.4 GHz Pentium M laptop was chosen as the test environment to compare CPU utilization for these applications.  OpenSolaris provides an easy-to-use well-known command-line tool called vmstat(1M), which was chosen as the mechanism to analyze the individual applications. In contrast, the Performance Tab which is part of the Windows Task Manager, seemed to produce wild performance variations.

For each run,  the clocks were set to one minute, and run until the time expired.  The data shown below represents the average CPU utilization, after startup, for each of the three implementations.  In particular we'll look at the following fields returned by vmstat:

  • us - percentage usage of CPU time in user space
  • sy - percentage usage of CPU time in system space
  • id - percentage usage of CPU time idling
The sum of (us + sy + id) should approximate 100%.


Number of Nodes per Digit
CPU Utilization
Implementation 1: BulbClockNode
 27 BulbNodes
 us: 22%  sy: 2%  id: 76%
Implementation 2: LEDClockNode
 7 SegmentNodes
 us: 9%    sy: 2%  id: 89%
Implementation 3: ImageClockNode
 1 ImageNode
 us: 3%    sy: 2%  id: 95%


The JavaFX engineering team is well aware of this limitation, and hopes to redesign the underlying scenegraph plumbing in the future.  Regardless, it's still a good idea to take into consideration the size of your scenegraph.

JavaFX book status:  Our upcoming book, JavaFX: Developing Rich Internet Applications, is in copy edit.  Coming soon: Rough cuts of certain chapters will be available on Safari.

Thursday Mar 19, 2009

Bindstorming

It is within our nature, even in the most infinitesimal way, to leave our mark on this world before we exit it.  I'd like to coin the following term, heretofore unseen in the JavaFX space, and submit it as my humble contribution to the human collective:

bindstorm \\'bïnd•storm\\ (noun): condition where a multitude of JavaFX bind recalculations severely hampers interactive performance

Yeah, I know, using the word you wish to define inside its definition is bad, but there is precedent for this: (1) Fancy-schmancy, hoity-toity college dictionaries do it all the time. (2) Mathematicians and computer scientists call this recursion: that mysterious concept which developers use to impress others of their programming prowess.

Don't get me wrong, JavaFX binding is incredibly powerful.  Heck, we dedicated a whole chapter to it in our soon-to-be-released book JavaFX: Developing Rich Internet Applications.  But binding does come with a price, and like most anything else, over-consumption can lead to abuse.

Consider this use case: you've got a JavaFX application with dozens or maybe even hundreds of Nodes that are part of the scenegraph.  Each of the Nodes are ultimately sized and positioned in proportion to height and width instance variables that are passed on down.  If you define width and height at startup and have no interest in a resizeable interface, then you stand a good chance of avoiding the use of many bind expressions.  The one potential twist here is that if you're sincerely interested in a non-resizeable application, but want it to consume the entire screen, what do you do?  As screens come in all shapes and sizes, you may not know what the resolution is at start time.  JavaFX has an elegant solution for this which uses binding.

Here's a simple application which defines a Rectangle and Circle that fill the entire screen.  You can click anywhere within the Circle to exit the application.  Notice the number of binds required to get this to work.

import javafx.stage.\*;
import javafx.scene.\*;
import javafx.scene.shape.\*;
import javafx.scene.paint.\*;
import javafx.scene.input.\*;

function run() : Void {
    var stage: Stage = Stage {
        fullScreen: true
        scene: Scene {
            content: [
                Rectangle {
                    width: bind stage.width
                    height: bind stage.height
                    fill: Color.BLUE
                }
                Circle {
                    centerX: bind stage.width / 2
                    centerY: bind stage.height / 2
                    radius: bind if (stage.width < stage.height) then
                            stage.width / 2 else stage.height / 2
                    fill: Color.RED
                    onMouseClicked: function(me: MouseEvent) {
                        FX.exit();
                    }
                }
            ]
        }
    }
}

Imagine what this would look like if you had lots of complex custom components with many more dependencies on height and width.  In addition to the potential performance impact, this could be error-prone and cumbersome to code.  To avoid the over usage of binding and the potential for a bindstorm, applications of this sort could be re-written as follows:

import javafx.stage.\*;
import javafx.scene.\*;
import javafx.scene.shape.\*;
import javafx.scene.paint.\*;
import javafx.scene.input.\*;

function run() : Void {
    var AWTtoolkit = java.awt.Toolkit.getDefaultToolkit ();
var screenSizeFromAWT = AWTtoolkit.getScreenSize (); Stage { fullScreen: true scene: Scene { content: [ Rectangle { width: screenSizeFromAWT.width height: screenSizeFromAWT.height fill: Color.BLUE } Circle { centerX: screenSizeFromAWT.width / 2 centerY: screenSizeFromAWT.height / 2 radius: if (screenSizeFromAWT.width <
screenSizeFromAWT.height) then
screenSizeFromAWT.width / 2
else screenSizeFromAWT.height / 2 fill: Color.RED onMouseClicked: function(me: MouseEvent) { FX.exit(); } } ] } } }

We achieve the same effect as the first example by first making a call to a method in the java.awt.Toolkit package.  With this information we can statically define our scenegraph without the use of binding.

There is one caveat to this solution.  As the AWT (Advanced Windowing Toolkit) is an integral part of Java SE, this code should be portable across all JavaFX desktops.  However, if you wish to deploy a JavaFX Mobile solution, the AWT calls would likely change.  Is there a mechanism that might work across both models?

As a final thought, while we're on this theme of coining terms, my compadres Jim Clarke and Eric Bruno, co-authors of the aforementioned JavaFX book, jokingly asked what word could be used to describe this scenario:

"Condition where binds lead to binds that leads back to the original bind, ending up in a Stack fault?"

BindQuake? BindTsunami? Bindless? BindSpin? BindHole (BlackHole)? BindPit?


        
    

Tuesday Feb 24, 2009

Registering Multiple Actions (or Handlers) in JavaFX

Java developers, especially those performing any type of GUI work, will ultimately encounter Java's event-driven programming paradigm.  In short, if programmers want to act upon some kind of event they bundle up a chunk of code into a Java method, typically referred to as a handler, and register the handler with that event.  Whenever that event occurs, the handler code will automatically be executed.

JavaFX provides a similar mechanism.  For a straightforward example, the code below defines a simple timer in JavaFX with a resolution of 1 second.  Each time a second expires, the function specified by the action instance variable will be executed.  Here's what it looks like:

import javafx.animation.\*;

public class SimpleTimer {
    public def timeline = Timeline {
        repeatCount: 5
        interpolate: false
        keyFrames: [
            KeyFrame {
                time: 1s
                action: function () : Void {
                    println("tick");
                }
            }
        ]
    }
}

Adding a run() function, as follows, to the bottom of this source will enable you run an instance of this timer:

function run() : Void {
    var s = SimpleTimer{};
    s.timeline.playFromStart();
} 

The output from this run looks like this:

tick
tick
tick
tict
tick 

It's all well and good if you only need a single action.  What if you wanted to perform multiple actions and/or dynamically add or subtract a number of actions?  We can enhance our previous SimpleTimer class to dynamically register and unregister handlers by taking advantage of two of JavaFX's features: sequences and function pointers.

Our new class provides more flexibility:

  • It defines an instance variable called duration, which enables the user to specify the resolution of a clock tick at object instantiation.
  • It defines two additional public functions called registerHandler() and unRegisterHandler() which take a function pointer (a handler) as an argument.  By registering a handler, the function will be included in the list of handlers to be executed each time the specified duration expires.
  • A handler is registered by inserting it's function pointer argument into an internal sequence of function pointers called handlers[].
  • A handler is similarly unregistered by deleting it's function pointer argument from the handlers[] sequence.
  • The action instance variable, which is part of the KeyFrame instance, now calls an internal function called runHandlers()runHandlers() sequentially executes the functions found in the handlers[] sequence.
Here's the new class:
import javafx.animation.\*;

public class Timer {
    /\*\*
     \* User-definable:  specifies the length of time for one cycle.
     \*/
    public var duration = 100ms;

    public def timeline = Timeline {
        repeatCount: Timeline.INDEFINITE
        interpolate: false
        keyFrames: [
            KeyFrame {
                time: duration
                action: runHandlers
            }
        ]
    }

    // Holds the list of handlers to run
    protected var handlers: function() [];

    /\*\*
     \* Add the function, represented by the handler argument, to the list
     \* of handlers.  These will run when the elapsed time, specified
     \* by the duration instance variable, expires.
     \*/
    public function registerHandler(handler : function()) : Void {
        for (func in handlers) {
            if (handler == func) {
                return;  // handler already registered -- skip
            }
        }
        insert handler into handlers;
    }

    /\*\*
     \* Remove the function, represented by the handler argument, from
     \* the list of handlers.
     \*/
    public function unRegisterHandler(handler : function()) : Void {
        delete handler from handlers;
    }

    protected function runHandlers() : Void {
        for (handler in handlers) {
            handler();
        }
    }
} 

To test this class out, we'll add a run() function at the script level.  The run() function creates a Timer instance and registers two handler functions, decrementTenthsRemaining() and processTicks().  Here's the code:

function run() : Void {
    var t = Timer {};
    var tenthsRemaining = 100;
    var decrementTenthsRemaining = function() : Void {
        tenthsRemaining -= 1;
    }
    var processTick = function() : Void {
        if (tenthsRemaining mod 10 == 0) {
            println("seconds left: {tenthsRemaining / 10}");
        }
        if (tenthsRemaining == 0) {
            t.timeline.stop();
        }
    };
    t.registerHandler(decrementTenthsRemaining);
    t.registerHandler(processTick);
    t.timeline.play();
}

And this is the output from the run:

seconds left: 9
seconds left: 8
seconds left: 7
seconds left: 6
seconds left: 5
seconds left: 4
seconds left: 3
seconds left: 2
seconds left: 1
seconds left: 0

Shameless Promotion:  Keep up to date with the latest status of our upcoming JavaFX Book entitled JavaFX: Developing Rich Internet Applications at jfxbook.com.


Tuesday Feb 17, 2009

JavaFX Book Coming to a Theatre Near You

Despite the considerable attention JavaFX has garnered, publications (i.e. books) that discuss JavaFX in any detail are few and far between, and anything that has been published, as good as it may have been, is unfortunately hopelessly out of date.  The reality is that up until recently, the JavaFX platform has been a moving target.  With the advent of JavaFX 1.1 however, the platform has stabilized to the point where you should begin to see legitimate books appearing on the subject.

Jim Clarke, Eric Bruno and I have been working steadfastly on a book entitled JavaFX: Developing Rich Internet Applications, which should be among the first -- if not the first -- of these new books.  From our standpoint the content is nearly finished.  What remains is the editing and publication process which takes a few additional months to complete.  Plans call for this book to be available in time for the JavaOne 2009 Conference, if not earlier.

We also plan on making rough cuts of certain chapters available on Safari.  As soon as these are ready, we'll let you know.  Finally, check out our website, jfxbook.com, dedicated to the book.  There you will find additional resources that accompany the book, including sample code and applications.  One such application is a JavaFX version of the popular Sudoku game, pictured below.

Visit jfxbook.com and give it a try.

Thursday Dec 04, 2008

Why JavaFX is Relevant

This week marks the formal release of JavaFX 1.0.  During the interval between the early marketing blitz and now, we've heard a lot from our friends in the press and the blogosphere, and in many instances what they had to say was not very pretty.  Some think the Rich Internet Application platform battle lines are already drawn between Adobe and Microsoft, and dismiss Sun as having arrived too late to the party.  Others opine that JavaFX's underlying Java platform is so yesterday.  In fact Java is the primary reason why JavaFX will, much to the chagrin of many, receive serious consideration.  Here's why:

  • Java is ubiquitous.  It is the proven, de-facto platform for web-based deployment.  On the desktop, it is estimated that approximately 90% of PCs have Java installed. In fact the major PC OEMs have seen fit to install it for you out of the box.  In the mobile world, Java is the dominant deployment platform.  Billions (that's with a 'b') of devices run Java.
  • The Java development community is arguably the largest on the planet.  Java gained initial widespread acclaim as a productive development environment, and continues to do so.  As JavaFX is an evolution of Java and seamlessly integrates with it, human nature tells us that individuals will naturally want to work with and leverage that which they already know and are familiar with.
  • Alternatives are still no match for the Java Virtual Machine.  It has been extensively studied, vetted, scrutinized, poked, prodded, abused, cloned, and optimized more than any other virtual machine in the history of computing. And just in case you're under the impression that the Java Virtual Machine is limited only to the Java (and now JavaFX script) programming languages, think again.  At last count there were over 200 projects integrating modern dynamic languages to the Java VM.  That list includes the usual suspects like PHP, Ruby, JavaScript, Python, and [insert your favorite language here].
  • The amount of Java Standard Edition online updates is staggering.  We know.  We supply the downloads.  And once a desktop is upgraded, it will be able to take full advantage of the features JavaFX brings to the table, effectively trivializing the barriers to entry.
Many of our most talented folks have been working feverishly to reach this milestone.  That being said, there's still lot's more work to do.  But we're off to a real nice start.  Check out http://javafx.com.  Hmm.  looks like the site is a little sluggish right now.  Maybe we underestimated all the interest?

About

Jim Connors

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today