In March 2018 Oracle released its Java Client Roadmap update. The document was significant because it acknowledged the creeping obsolescence affecting all desktop-oriented Java technologies including Swing, Applets, Web Start, and JavaFX. The roadmap update mentions the shift to mobile-first and web-first development as the culprits but doesn’t go into specifics of what the technical erosion of Java desktop actually is. In this article we will examine the technical erosion affecting the one component still supported by Oracle and included in Java: Swing.
From the very beginning, the aim of Swing has been to extend Java’s core idea of “write once, run anywhere” to graphical applications. At its launch with Java 1.2 in 1998, Swing accomplished that with great success. Technical erosion has set in in a big way for Swing however, and as we will see in this article, this erosion affects all of the critical aspects of running and developing Swing applications. This includes portability, achieving a consistent look and feel, resource consumption patterns, the single-language developer experience, transferable developer skills, and free deployability
In 1999, a Swing application could work on just about every graphical computing device without having to be recompiled. Not just 32-bit and later 64-bit Windows, but Linux, Solaris, and later Mac OS X as well. The trend of BYOD that started in 2010 and got underway in 2012, however, meant that increasingly the desktop-only vision for enterprise applications could no longer be sustained.
Swing did not run on most of these devices and today still does not. Nowadays, desktops account for less than half of devices sold and Swing’s usefulness as a portability enabler is largely lost.
Consistent rendering and pixel-based graphics
Swing originally took portability to the max by displaying and animating consistently on every screen of every OS thanks to pluggable Look-and-Feel themes. Swing achieved this by relying heavily on graphical primitives and a coordinate system that was mapped to device specific pixels.
Over time high DPI displays were developed that could increase image quality by squeezing pixels closer together. This introduced a lot of variety between the pixel densities in use, and Swing applications would look very different depending on the device used. Solving this could mean clunky fiddling with desktop-specific settings to magnify the user interface for specific monitors and became a configuration challenge.
The problem reached its critical point in 2014 with Java 8, with new displays having such high DPI that Swing applications became unusable on Windows and Linux. This prompted Oracle to bring out a HiDPI fix in JDK 9 called JEP 263. The fix has been a difficult since despite over 50 bug fixes to OpenJDK since, full consistency still has not been re-achieved.
The image above illustrates the challenges with solving the scalability problem while maintaining backwards compatibility with the original pixel-based behavior:
- On the sample with no scaling, both lines start and end at the exact same y coordinate positions, but on the sample with scaling, the line with a stroke width of 1 is shorter. At the same time the line with a stroke width of 2 is shown longer when scaling is applied;
- The line with a stroke width of 1 is 50% thicker with scaling than without;
- Scaling makes the border of the JTextField appear 50% thinner and the background bleeds outside the border on the left-hand side.
So JEP 263 did succeed in keeping text readable on HiDPI displays and ensured Swing remained usable. The drawback is that Swing now renders inconsistently on the same platform, scaling alone being a determining factor. For a variety of applications like software automation and pixel-based testing this inconsistency is problematic.
Resource consumption antipatterns
Swing applications tend to have resource consumption patterns that are ill-suited to the needs of today’s IT environments in at least three ways. Each of these poses a roadblock to innovation.
First is peripherals. Swing applications were conceived to work as desktop foreground processes with direct, privileged access to ports and peripherals such as keyboard and mouse. Swing was not limited to data driven business applications and the library supported all manner of graphical uses. A consequence is that Swing deals with mouse move events, whereby a handful of wrist movements can result in over a hundred events being fired. The high throughput of event messages is a challenge to run Swing in full emulation or virtualization setups where this data needs to be sent over a network.
Second is the data. In enterprise settings, data hungry Swing applications can connect to databases throughout the network and MVC views would refresh themselves based on the latest data updates. Optimizing Swing applications with any kind of caching meant one thing - bringing data to the client. This might not have been a problem for the high-speed, low-latency cabled ethernet networks of the time but as wireless networks have gained in popularity the assumption of cable connectivity is invalid and Swing performance is more problematic.
And third is the video. Swing did not use video cards, which were expensive and not included in most enterprise desktops. Instead Swing used double-buffering, drawing its screens in an application memory buffer from sequences of graphical primitive instructions that were invoked with refreshes. These buffers were then copied to the display. In the meantime, video cards have become much cheaper and more accessible, and even appear on enterprise clients. Today’s desktop virtualization technology is able to leverage client video cards, but Swing applications don’t render as VDIs expect and scale poorly inside them, forming yet another roadblock to companies simplifying the management of their infrastructure.
If you knew Java, you did not have to learn a new programming language or a new syntax to start developing GUI applications with Swing. A bit of SQL knowledge was enough moreover to make the application data-driven and access a variety of databases using JDBC or other protocols. Today, developers are more comfortable with multi-language projects and how object-oriented programming, with its strengths, can be complemented with best-of-breed declarative languages that allow for improved modelling, understanding and maintainability. This trend for complementing procedural programming with declarative elements gained traction in other frameworks like JavaFX, Microsoft’s WPF and also Vaadin. These tools are unavailable to the core Swing developer.
Transferable developer skills
If you had the experience of developing an application with Swing and perhaps became a Certified Java Developer and applied MVC as a best practice, the idea was you would have the skills needed to maintain the Swing applications of other companies. The problem that emerged with Swing is that it is generic, and Swing is well-suited to developing a game, a business application, or a statistical application. It also means Swing is not perfectly suited for developing any specific application, and over time companies have developed libraries to customize and extend the Swing framework with domain-specific custom APIs. We have seen software companies operating at national or industry level serving Swing developers with domain-specific extensions. With the plethora of options, Swing developers have much less readily transferable skill sets working for complex applications than the original emphasis on Java and MVC patterns would assume.
Freely available and deployable
When Swing was released, all you needed to develop and run was built in to Java’s Standard Edition JDK. It was likely your desktop had all the tools you needed to start at least casually developing, testing, and running a Swing application. Getting your applications installed on people’s desktops was easy with Web Start and you could even run Swing in a browser when using Applets. Today this is all gone: the notion of a “Standard Edition” is discontinued, Web Start and Applets are now deprecated or broken. Desktop operating systems have switched to sandbox webstore concepts so that distributing Swing applications that rely on pre-installed Java Runtime Environments is now a challenge and finding the tools to build one today takes determination.
In the Java Client Roadmap, Oracle has pledged to support Swing until at least 2026. That date may seem comfortably far in the future, but the technical erosion of Java Swing makes migrating from Java Swing to web applications much more urgent than official support timelines would suggest. Since application migration projects often take several years, it becomes prudent to start with the assessment sooner rather than later.
Whether making the most of new business opportunities brought by digitalization or consolidating on future proof architectures to achieve cost savings, companies using Swing should start initiatives soon to explore the options available.
Looking to learn more about how to migrate Swing desktop apps to the web?