While the Java community celebrates the release of JavaFX 1.0, two JSRs are striving to teach us again how to write Swing applications – this time, the easy way. JSR 295 addresses property manipulations and bindings, not just in the Swing framework but throughout the Java platform; JSR 296 simplifies Java application creation using Swing, bringing a “Swing for the rest of us” kind of approach.
In this post, I’ll discuss JSR 296 and what it brings, and my opinion of where it could be improved; in the followup post I’ll discuss JSR 295, and try to do the same for that.
JSR 296 has had a long journey, with a gap in development between the time Hans Muller, the previous spec lead, left Sun and Alex Potochkin took his place. As of now, beta versions are being uploaded to the project site, with the latest posted 4 months ago, coinciding with Alex’s latest blog post. Note that for some reason, the main page of the site shows the 1.03 version and not the beta versions. I hope this gets fixed since it can really be confusing..
Swing for the rest of us
The Swing Application Framework (SAF for short) takes the basic flows of Swing application development and packages most of their boilerplate into chewed up template methods, using dependency injection for most of the initialization and internationalization processes.
The framework offers support for:
- Application lifecycle: Application startup and creation of key components. The main panel, toolbar and status bar are now handled via a template method design pattern. In addition, application quitting is handled with ExitListeners which work like a VetoableChangeListener – before exiting the application each listener is asked if it can exit, giving the application the chance to ask the user to save their files or whether theyâ€™re sure of the operation. Only then will the listeners receive an exit notification, allowing them to handle any exit-specific logic.
- Binding for Action: Creating Action objects from POJO methods. Any method can now become an Action object by annotating it with @Action, and declaring which properties define its enabled and selected states. If the method accepts any arguments, a @Parameter annotation can be placed to specify what should be passed to this method when it’s used as an action. The method can return nothing – or if work in the background is required, it could return a Task object.
- Asynchronous task execution and monitoring: SwingWorker, finally published in Java 6, already allows for asynchronous work, monitoring of progress, chewing of information in chunks of data, and more. Task simplifies all these features by adding a message concept describing what the task is doing at the moment, implementing the done() method as a template method design pattern, with different methods for exception handling, success handling, and cleanup. In addition, it sends all the different SwingWorker methods as events to designated event listeners, allowing for code reuse for providing details about the task being run (e.g. a unified progress dialog). Two additional great features are the ability to monitor all the tasks currently performed in the background through a task monitoring service, and the ability to select which scope of the application’s UI to disable while the task is being performed.
- Internationalization support: Internationalization is always a hassle for UI development. SAF helps by putting all internationalization parameters outside the code. These are located in a properties file just like ResourceBundle – but SAF uses filename conventions and dependency injection to free the developer from having to deal with these issues. Also, it leverages Action to set text, icon and other properties on those components to which an action is set, which helps by setting the same text or icons for buttons, menu items and toolbar items in a single definition. It also leverages the Task to set the messages sent from it in an internationalized way. As a result, with this set of features, you barely get to see internationalization code in your application.
- Session state storage: Saves the application session state to disk in an OS-friendly manner, and reloads it again when the application is next started. This is done automatically by the life-cycle management, but can also be hooked into in order to save different state items in addition to the UI state.
The site asks for comments and ideas. I have a few ideas in mind that I’d like to share, since using this framework can save a tremendous amount of time and it can be improved to save even more:
- More complex binding options for enabled and selected attribute properties: Allowing for chained bindings such as “file.isDirectory”, and allowing the usage of operators such as “itemsCount > 3″ or “!isDirectory”.
- Binding to actions through the properties file: I can bind almost any property to the action or component, so why not between the two? I would like to write “label1.action = [MyActions.class, sayHello]“ and get it over with.
- Binding actions to the same method with different parameters: The framework allows for binding actions to methods with parameters, using the @Action.Parameter annotation. It would be great if it could also allow to bind to named actions, allowing each named action to have its own set of parameters. In essence it would put an optional array of @Action.Parameter into the @Action annotation itself, and allow to annotate a method with @Action annotation multiple times.
In many ways, this framework takes away a lot of the boilerplate created when developing UI applications, and makes it easier to bring them to the next level of quality. If you haven’t heard of this framework and you are developing with Swing, get it and send your comments to the project mailing list, or even here!