As I am in the process of developing an application for data analysis on chemical data the need for building a desktop GUI came up. Why desktop you ask? Excellent question! I think for this particular project, the combination of ease of use, data privacy and performance make it worth exploring an approach with a local, self-contained application instead of anything involving remote servers.
Actually in the end we might build a SaaS too or move to such a model completely.
Nevertheless I am exploring the desktop GUI application space now and wanted to see how one could do that in Clojure in beginning of 2017.
GUI Frameworks
The most promising candidates are JavaFX and Electron (based on Chromium, NodeJS, HTML5). I ruled out Swing even though I got only positive feedback about it from the few people who used it in anger ( Seesaw would be the Clojure lib of choice). Swing is getting old and has found its official successor in JavaFX. That being said, there are also people who already claimed JavaFX dead… which would leave us without any GUI framework alive in the Java world!?
JavaFX
JavaFX is Oracle’s take on a framework for rich client applications and it is included in the official JDK and JRE bundles since Java 7. As it is included in those bundles it is readily available in many cases without even having to pull in additional dependencies. Being a Java library it can be accessed via interop from Clojure conveniently. When growing the application once might want to create some wrapper functions and macros to map it more nicely to Clojure idioms.
There are also a couple of wrapper libraries available but it seems like most of them are not actively maintained and a rather early versions or even prototypes. There is one library that is quite new and tries to map the React model to JavaFX: Having a declarative UI tree spec which gets rendered from a single source of truth state and uses efficient diffing to find out what actually needs to be rendered. That library is halgari/fn-fx developed by Timothy Baldridge. As I really like that rendering model for being close to the functional programming paradigm while still being very practical and pragmatic, I wanted to give this a try too. Especially as the declarative UI building would be very close to how I would approach it on the web. Which brings us to Electron…
Electron
Electron bundles Chromium with NodeJS and provides a framework to build desktop applications with HTML5 technologies. Electron became very popular quickly and has been adopted by some high profile projects including Slack and Microsoft Visual Studio Code. The cross platform support seems to be really good and it comes with nice features like automatic updates and crash reporting. As it is based on web technologies it is indeed very easy and natural for web developers to build applications with it and it supports most things that you would use for building websites too including React. All of that sounded very good to me! Even though I am not a huge fan of HTML, CSS and JS I knew I would be able to be fast with those technologies.
One major downside with that approach for me though: You would be living in a JS runtime (actually two: Chromium & NodeJS) and had to use Clojurescript where I would really prefer using just Clojure. First I would like to leverage some Clojure and JVM libs that are not available for Clojurescript and secondly I always had rather mixed experience with the Clojurescript REPL development. When things were going well it worked half-decently but often it was just broken and a PITA to get it to work again.
Of course with Electron you can call out to any remote or local server or even start local processes via the included NodeJS backend. This way you could for example communicate with another Clojure program. One approach to integrate a Python backend is described here. However this seems a bit too much for me when I could just go with a single Clojure application instead.
Conclusion and what’s next?
The support for desktop GUIs with Clojure does not look that great IMHO. I would think that is most likely because not many people are working on such GUIs. As a JVM-native approach JavaFX still seems to be the best bet. If one can live with the JS runtime then Electron would be an excellent choice.
For the data analysis application I am currently working on, I will most likely go with JavaFX. Either via simple interop and some wrappers or using halgari/fn-fx because I want to have access to the JVM and a good REPL experience. I am however evaluating Electron too and you can find some spike implementations I did with those technologies over here on GitHub. As I am writing this those are still work in progress with the fn-fx-ui being the most complete.
I plan on finishing the spikes in the repo and blog about the experience and its outcomes.