Friday 26 February 2016

JavaFX with Spring (and a few other technologies...)

A few weeks ago I was asked to develop a little software that would solve a real-life issue: A teacher with a worldwide audience, who regularly sends out standard emails reminding his listeners of the next lesson which includes dates and times in different places around the world, asked for a way of reducing the time he spends on creating these emails. So far, he had used one of the many websites out there to convert the date and time in his timezone into the respective dates and times around the world, but always only one at a time - and then copied the results into a standard text (again, obviously, one by one). Due to the mass email service he uses, calendar invites were not an option.
So I spent some time researching and to my own surprise didn't find a free service or software which would help reduce his worktime. Thus, I wrote one myself. The result is visible on my GitHub account. In this post, I'd like to give an overview of how I used what I consider the main technologies for this little project:

JavaFX

No big surprise here, this is the only choice you should make nowadays when using Java for desktop development. Maybe it's the fact that I'm old-school, but I just did everything in pure Java without any FXML. Comes more natural to me. The UI does the job, but can certainly use some improvement - in particular the ZoneIdSelectionDialog. It's way too large and lacks a nice structure. If anyone has some ideas how to improve this, please go ahead and fork me.

Spring

It's a Java SE project, so there's no native CDI. Therefore I added Spring into the mix. The annotations work like a charm. The aforementioned ZoneIdSelectionDialog is also a Spring component - which shows the (from a developer's point of view) only downside of using Spring (or any other Dependency Injection framework) within a JavaFX application:
The lovely Application class follows a very straightforward pattern when launched:
  1. Constructs an instance of the specified Application class.
  2. Calls the init() method.
  3. Calls the start(javafx.stage.Stage) method.
  4. Waits for the application to finish, which happens when either of the following occur:
    • the application calls Platform.exit()
    • the last window has been closed and the implicitExit attribute on Platform is true
  5. Calls the stop() method
So far, so good. So think for a moment: Where would you want to instantiate your Spring beans? Sounds like it should be part of the init(), doesn't it?
The bad news is: This doesn't work when you use Spring (or any other DI framework) to initialize a JavaFX component, because these are only allowed to be constructed on the so-called JavaFX Application Thread. If you've never heard of it, this is where all the UI beauty is actually executed (for Swing veterans like me: It's the equivalent of the Event Dispatch Thread).
So this leaves us no choice but to initialize the Spring context first thing in the start(javafx.stage.Stage) method which seems unnatural, but is a technical restriction. Nevertheless, the gain outweighs this.

The Java Time API

A great addition to Java 8 and probably the one which generated the biggest buzz aside from Lambdas and Streams, I found it nice to use. This application only shows a small portion, but it already highlights a few key advantages over the much older Date and Calendar classes:
  • Instant and the other "value" classes in the package are immutable. This eases their usage and automatically makes them thread safe.
  • The same holds for the DateTimeFormatter - which I consider even more valuable. I've stopped counting how often in my career I stumbled over a strange behavior which I traced back to an unsafe usage of SimpleDateFormat, e.g. as a constant. This is bound to break in a multithreaded environment, as this class isn't thread safe.

Apache Velocity

OK, this library's usage in here is really a no-brainer. I'm using it in a very basic way to replace two tokens with values which are computed in the application. Probably smarter usage is possible, but I wanted to give the user an option of not using a template at all. I know that Velocity can do a lot more, but I really had no need for anything else here.

Lessons learned

  1. Use JavaFX! It's even better than you think.
  2. DI fits in nicely with FX if you keep in mind that you must use it in a slightly "unnatural" way.
  3. The Java Time API is just great. If you haven't done so yet, get acquainted with it. In my view, it's now about time (please excuse the pun) to deprecate Calendar and SimpleDateFormat.
Questions? Criticism? Ideas for improvement? Please feel free to leave any of these in the comments section or as mentioned, fork me on GitHub.

No comments:

Post a Comment