Featured Post

This example uses the same controller as in a previous post but adds a use case to support email validation. A Commons Validator object is ...

Wednesday, July 13, 2016

The Swing / JavaFX Hybrid App

Adding JavaFX to a Swing app incrementally is a great way for an organization to learn about the productivity benefits, API, and deployment characteristics of JavaFX. If your app needs a new form for the next release, build it in JavaFX (with Scene Builder and CSS) and integrate it in the existing Swing code. That way, the new feature can give early feedback on how well JavaFX is working without breaking existing functionality.

In terms of coding, there are two bridging components -- SwingNode and JFXPanel -- that enable the integration. SwingNode will add a Swing component to a JavaFX container. JFXPanel will add a JavaFX component to a Swing container. Both Swing and JavaFX have utility methods for making sure that UI code gets run on the appropriate thread: SwingUtilties.invokeLater() and Platform.runLater().

In forming the analysis for a project like this, there are a few things to consider.

Threading

You'll be dealing with at least two threads in your program: JavaFX and AWT (for Swing). If your app has been around a while and is handling long-running operations correctly, there will be additional threads. While the aforementioned invokeLater() and runLater() methods should fend off threading issues, this isn't always the case. I've seen AppKit exceptions, JVM crashes, and hanging.

For that reason, I recommend integrating at the JFrame / Stage level. In my opening suggestion, a Swing app might open a JFrame containing a JFXPanel. Going the opposite way, you might have a Stage/Scene/SwingNode containing a JPanel. If there are threading problems, closing the window might dispel any problems without hanging the app.

It is feasible to put JavaFX and Swing on the same screen (JFrame or Stage) and you may not experience any threading issues. I've done this myself. Here are a few guidelines to help with that type of implementation.

Don't go back-and-forth. Stick to having the Swing portion create and call JavaFX components or vice versa. Don't have a Swing ActionListener call a JavaFX EventHandler which calls more Swing code, etc.

Test everywhere. I've seen an app throw a "not on AppKit thread" on a Mac but run fine on Windows. In another case, I've seen a Linux app hang but run fine on Windows. Get a cheap laptop and put Ubuntu on it. Get a Mac Mini. Think WORA, but test everywhere.

UI Design

I don't recommend Swing-ifying the JavaFX code. While you can go line-by-line through a Swing program and map every JButton to a JavaFX Button or a JTextField to a JavaFX TextField, JavaFX brings a design-oriented paradigm through Scene Builder and CSS styling. This adds the rapid development of the web world into your Java desktop coding where the WYSIWYG edit (Scene Builder) can be tweaked and updated immediately without going through a compile/run sequence.

The first 3 parts of this video series -- not specific to a Swing project -- give you a feel for what development with Scene Builder and CSS would look like.

There may be cases where you have to build the UI through code just as you did with Swing, but even in these cases make sure you're using CSS.

Legacy Code

Surprisingly, the biggest obstacle to adding JavaFX to an existing app is probably legacy code. If you have an older Swing app, chances are that business logic has infiltrated its presentation layer. For example, complex calculations or business rules are mixed with UI-updating code that can be difficult to extract. So, a JavaFX porting project might involve a refactor of this business logic to push it down to a lower layer (ex, RESTful web services, Spring components, EJBs) or to produce a UI-neutral front-end class like a Business Delegate.

Remember, Swing has been around since the 90's and if your app is that old, don't overestimate your understanding about what the program does.

Now is a great time to add JavaFX into your Swing program. Previous versions of JavaFX were separate downloads the wrecked havoc with deployments (pre-Java 8). Once you get a basic feel for JavaFX, go ahead and add something to your existing program and see if anything breaks. Remember to test thoroughly and allow yourself a small enough increment to get feedback on your JavaFX code as quickly as possible.