http://java.sun.com/ http://java.sun.com/ http://java.sun.com/javaone
JavaOne - ExperiencingJava technology through education, industry, and community
2007 Conference
Home
Registration
   Conference Hotels
Schedule
   Activities
Tracks
Sessions
   General Sessions
   Business Day
   TV Day
   JavaOne Camp
Hands-on Labs
Pavilion
   Cosponsors
   Exhibitors
   Media
   How to Exhibit
Blogs
Multimedia
Java University
 
Conference Tools
Schedule Builder
Event Connect
My Registration Details
 
Conference Programs
Alumni Program
   Alumni FAQ
Eco Corner
Rock Stars
 
Related Resources
JavaOne Library
JavaOne Online
2006 Site Archive
 
Community
Forums
Sun Developer Network
 
Popular Items
Java Wear
Duke Images
 
Related Sites
java.sun.com
java.com
java.net
 
 
  Home > Simplify Application Development With the Swing Application Framework

 Simplify Application Development With the Swing Application Framework

   
By John O'Conner  

Have you ever fretted over the difficulty of creating a desktop application with a Swing-based user interface (UI)? Developers have sometimes complained that building Swing applications is just too hard. Sun has taken much of the feedback and has tried to simplify the process of building Swing-based applications on the desktop. The recent simplifications have taken shape as two separate Java Specification Requests (JSRs): JSR 295, Beans Binding, and JSR 296, the Swing Application Framework.

Although both JSRs focus on the problematic areas common to typical Swing applications, desktop engineers Hans Muller and Joshua Marinacci focused on the framework in the session titled "JSR 296: The Swing Application Framework" (TS-3942). The two predict that the JSR will be part of the Java SE 7 platform, but you don't have to wait that long to benefit from their work. The Swing Application Framework is available online now as Project Appframework on java.net, where you can find the documentation, code, and samples.

The term framework sometimes causes apprehension because frameworks can be large, complicated, and overbearing. For small applications, a framework can introduce more complexity than the original system they supposedly help. However, the Swing Application Framework has goals that minimize its size and weight, as well as its negative effects on your applications.

The framework was built with the following goals:

  • To be as small and simple as possible
  • To require less than an hour to explain
  • To work well for both small and medium applications

Additionally, the framework does not introduce fluff such as docking frameworks, data models, scripting languages, or graphical user interface (GUI) markup schema. The framework simply helps provide the kernel of a typical Swing application.

The framework API supports five main aspects of an application: life cycle, resources, actions, tasks, and session state.

The framework architecture has two singleton classes that help you manage your application: ApplicationContext and Application. The ApplicationContext provides support for storage, session state, action and resource management, and task control.

Understanding how to use the framework takes very little time. Typically, you'll use the framework in four steps:

  1. Create a subclass of the Application class for your specific application.
  2. Create and show your GUI by overriding a startup() method.
  3. Use ApplicationContext services to manage actions, tasks, resources, and session state.
  4. Call Application.launch() from your application's main method.

The typical "Hello, World!" application might look like this:  

// SingleFrameApplication is a subclass of Application.
public class MyApp extends SingleFrameApplication {
    @Override protected void startup() {
        JLabel label = new JLabel("Hello World");
        show(label);
    }
    public static void main(String[] args) {
        Application.launch(MyApp.class, args);
    }
}

Managing Application Life Cycle

Most applications will start with a class that extends the Application class, usually the SingleFrameApplication subclass. Your subclass should override the life-cycle methods, which run on the event dispatch thread (EDT). The life-cycle methods run in a specific order:  
launch() -> initialize() -> startup() -> ready() -> exit() -> shutdown()

Your application will start by calling the Application.launch() method, which itself calls initialize(), startup(), and ready() on the EDT. Override the initialize() method to perform steps that must occur before the GUI appears. For example, you should set your UI look and feel from within the initialize() method. Create your initial GUI from within the startup() method. All applications will override startup(). Use the ready() method to perform any work that should occur after the GUI is visible. Finally, use the exit() method to close down your application. The exit() method checks with ExitListener objects to determine whether the application can actually shut down. ExitListener objects can veto exit requests, presumably to finish critical tasks or to query the user to confirm the exit request.

Managing Resources

Most applications use common resources such as text, icons, colors, and font definitions. If you ever want to localize your application to other locales or platforms, you should externalize resources to facilitate easy modifications or translations to other spoken languages. Resources are defined in ResourceBundle classes, and the framework helps you manage resources with ResourceMaps.

The ResourceMap class encapsulates a list of ResourceBundle objects. You can define application- or package-wide resource bundles to organize strings, fonts, or other platform-specific resources that are retrieved by way of key-value pairs.

ResourceMap instances support automatic resource injection. By following a few naming conventions or by using the @Resource annotation, you can make your application automatically load and apply text, fonts, colors, and more to UI components and fields.

The advantage of resource injection is that you don't have to manually set labels and visual properties. Additionally, your UI becomes localizable by default.

Creating Actions

An Action class encapsulates an ActionListener and includes some visual properties and state. You can reuse Actions in different parts of your application to perform the same behaviors with different UI elements. Actions are helpful because they allow you to reuse common text and behavior among many components, and they can be enabled or disabled easily. However, creating them is sometimes tedious, and developers often forget that the visual properties should be localizable. Also, Action code tends to become tangled and difficult to manage over time.

The new @Action annotation improves on some of the weaknesses of Actions, making them more convenient to use.

You can define and use Action annotations for your methods like this:  

@Action public void sayHello() {
    String s = textField.getText();
    JOptionPane.showMessageDialog(s);
}
// Use sayHello -- set the action property.
Action sayHello = getAction("sayHello");
textField.setAction(sayHello);
button.setAction(sayHello); 

The Application.getAction utility method creates and uses an Action for each @Action method. The default key is the action's method name, and it caches that information in an ActionMap. Resources such as text, icons, and accelerators are loaded from the ResourceMap of the target class. The ResourceMap gets its information from resource bundles, and resource injection can automatically apply the resources from a property file like this:  

# resources/MyForm.properties
sayHello.Action.text = Say &Hello
sayHello.Action.icon = hello.png
sayHello.Action.accelerator = control H
sayHello.Action.shortDescription = Say hello

Performing Background Tasks

You should always use a background thread for I/O bound or computationally intensive tasks. Long-running tasks can block the EDT. The new framework provides support for starting, stopping, and monitoring the progress of a background task. Although the SwingWorker class has most of what's needed, the framework provides a Task class to support more functionality. A TaskService class helps you execute tasks, and a TaskMonitor helps you monitor progress.

Saving Session State

The framework provides a way to save session state. Saving GUI state allows you to restart the application and return to the same window or form at a later time. The framework provides SessionStorage and LocalStorage classes for those purposes.

Demos, Demos, and More Demos

Marinacci and Muller provided several demos during their presentation. The demos not only showed off the new framework APIs, they also showed how well the upcoming NetBeans IDE 6.0 integrates the framework. This NetBeans IDE release will provide several plug-ins to make using the framework easier. Additionally, the IDE can help you generate much of the common scaffolding of a simple application, which includes menu bars and items for common actions such as Open, Save, Print, and so on.

Find More Information

If you missed session TS-3942, you can still learn about this new framework by reviewing source code, documentation, and binaries on the java.net Project Appframework site.

Don't be shy with questions either. Direct your queries to the Project appframework email address.

Check out related sessions at the 2007 JavaOne conference:

  • Why Spaghetti Is Not Tasty: Architecting Full-Scale Swing Apps (TS-3316), Thursday, 2:50 to 3:50 p.m.
  • Beans Binding (TS-3569), Thursday, 4:10 to 5:10 p.m.

Session times and room assignments sometimes change, so check the online schedule on the JavaOne conference home page for updates.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.