Art of Java Web development: WebWork

Build Model 2 applications with WebWork

WebWork is an open source Web development framework for building Model 2 applications. Philosophically, it is closer to Struts than Tapestry. It works within the existing Web APIs in Java rather than attempting to replace them completely. WebWork contains several concepts and constructs that are unique and that set it apart from other frameworks, such as the Pull Hierarchical Model-View-Controller design and the value stack, which supplies values to their custom JSP (Java Server Pages) tags. We begin with a history and background of the framework. We then explore some key concepts and constructs that are vital when you're working with the framework. As always, the principles of Model 2 development provide the guidelines for the samples and dictate a firm separation of concerns.


WebWork is produced by the Open Symphony project. This project includes many embedded projects; WebWork is just one of them. The framework is currently at version 1.3, and you can download it from the Open Symphony Website. It is based on best practices and design patterns that have long-standing records of accomplishment-patterns such as Model-View-Controller, the J2EE Front Controller, and others. It is also based on a strong motivation to keep things as simple as possible while maintaining flexibility (which the creators acknowledge is a difficult balancing act).

WebWork implements what its documentation calls "Pull Hierarchical Model-View-Controller," or "Pull HMVC." This is the creators' own take on the Model 2 design. The "pull" part of this definition indicates that the view component is responsible for pulling the model information from the controller on demand. This is different from the traditional Model 2, where the view accesses information that has been placed within the model and passed to it from the controller. In this case, the view understands what information it wants and accesses it without necessarily having to wait for a controller to make it available. This architecture requires the presence of a repository of data available to all views, which access it on a just-in-time (JIT) basis.

The "hierarchical" part of the description describes the repository of view data. In the case of WebWork, the "value stack" is used to provide information to the view. (We describe this construct in the "Expression Language" section below.) The rest of the architecture is Model-View-Controller. That means that WebWork enforces the normal semantics of Model 2, but with a different twist on how that model information is made available. WebWork is not the only project to use this approach. Turbine's documentation and white papers also refer to this "pull" paradigm of Model 2.

WebWork takes advantage of the Web APIs in Java rather than hiding them. However, it doesn't rely on them as much as unadorned Model 2 or Struts. Like Struts, WebWork includes a central controller, based on the J2EE Front Controller design pattern, which creates Action objects (thus using the Command design pattern). However, the return and packaging of model information is different in WebWork.

The architecture

The architecture of WebWork follows the common architecture of most Model 2 Web application frameworks. The figure below shows the overall architecture and flow.

The WebWork architecture has much in common with unadorned Model 2 and Struts, with changes

You can configure WebWork through configuration files. When WebWork starts, the ServletDispatcher is invoked. This is the main controller for WebWork, similar to other Model 2 frameworks. The ServletDispatcher reads several configuration files (covered in "The Configuration" section below) and uses that information to create an Action object to handle the request. The action in turn creates model beans, which access data, mutate it, and otherwise perform the real work of the application. WebWork does not require the use of model beans. Properties can appear directly in the Action class but shouldn't for most Model 2 applications because such an arrangement violates the separation of responsibilities.

The action returns a response code, used by the ServletDispatcher to look up the appropriate view. The ServletDispatcher dispatches control to the view component, which can be any view framework (for example, JSP or Velocity), or it can be an action chain, which will execute another action. The view extracts information needed from the value stack. The framework maintains this construct by caching information from both actions and model beans for use by the view. The value stack is discussed in "The Expression Language" section.

On the surface, WebWork looks just like the architectural diagram for Struts. However, the details of information flow are different. WebWork makes accessing information kept in actions and model objects easier by handling much of the information transport for you. WebWork includes numerous custom JSP tags that are savvy about the information flow within the framework.

Validation is also handled differently in WebWork. It allows you to create metadata classes around standard HTML controls to handle formatting, validation, and other facilities. In this regard, the HTML elements become much more like desktop user interface (UI) widgets.

The configuration

Configurability is one of the hallmarks of WebWork. The framework includes a default properties file and allows you to override these settings in additional application-specific properties files. WebWork uses the properties files shown in the table below to configure the application.

WebWork properties files

Properties FilePurpose
webworkThis is the primary configuration file for the framework. It includes package names, UI settings, and entries that point to the other configuration files.
defaultThis is the default properties file for WebWork. The framework reads all these values, then selectively overrides them from the webwork properties file.
viewsThis file contains all mappings for visible resources in the application. It includes mappings for actions and UI elements. The actions return values that reside in this file point to a destination resource.
log4jThis file is used to set up logging for WebWork. WebWork uses the Commons logging framework, whose default logging implementation is log4j. This properties file is a standard log4j file.
Action-specificInternationalization is handled through properties files mapped to actions. Each action can have a properties file that defines the visual elements exposed to that action's view.

Each of these properties files is loaded from the classpath. You can place them anywhere on the classpath (including the classes directory under WEB-INF in the Web application). One of the properties in both the default and webwork properties files is, which points to all the other properties files. If you want to store most of the properties files in another location, you can point to that location from this property in the main configuration file. The framework looks for and tries to load both the default and webwork files upon startup. All the other files can load based on property settings in one of the two main files. Developers sometimes like to keep all configuration files together and away from the output classpath, so WebWork facilitates that design via its property-loading mechanism.

Some of these files may also be XML files. In particular, WebWork includes a document type definition (DTD) to use with an XML document for view mappings. If you prefer to keep view information in XML, WebWork can support that. The webwork.configuration.xml property in the webwork properties file allows you to specify an XML view file instead of the standard properties file.

To make it easier for you to set up the directory and configuration file structure WebWork expects, the framework install includes a "skeleton" project named that resides in the /etc directory. This zip file includes a reasonable directory structure, libraries, an Ant build file, templates, and configuration files. This is an excellent starting point for building a WebWork project rather than setting it up on your own.

Key concepts

Like all nontrivial frameworks, WebWork contains some key concepts that you must understand before you can leverage the framework to its best potential. WebWork includes Action classes, which are an implementation of the Command design pattern; the ServletDispatcher, which is modeled after the Front Controller design pattern; and an innovative data structure called the value stack, which makes it easy to pass information from the controller to the view.


Like most frameworks that use the Command design pattern to create a central controller servlet, WebWork includes a base class for all actions. This class, named ActionSupport, is a convenience class that implements the ActionInterface. It provides access to result view mapping, error handling, and internationalization. The Action interface includes some handy mappings (implemented as constants) to standard views that frequently reside in the view configuration document (for example, the SUCCESS constant).

In WebWork, the developer creates action subclasses that handle the individual page code for the application. The actions reside in a package or packages specified in the file and map to a particular extension (the default is .action). The names of the actions themselves appear in the file, which maps the action back to the action package. To invoke an action, the user types a URL that includes the Web application name, followed by the mapping name of your action with the .action suffix. The suffix matches a URL pattern in the web.xml file, pointing it to the WebWork dispatch servlet. Once that servlet has the action, it follows the normal framework flow of events. This structure is similar to Struts, particularly the way the controller servlet acts, but with additional configuration files.

One key difference from other frameworks lies in the fact that WebWork actions are not coupled to the servlet API. Actions are essentially just JavaBeans, with no intrinsic knowledge of constructs like HttpServletRequest. The actions can be made aware of these objects via interfaces, but the action itself knows nothing about what context it is running within. This makes WebWork actions more loosely coupled than Struts actions. In fact, WebWork documentation warns you when you try to use the interfaces to couple your application to the Web API. While it is unlikely you would write a WebWork application that isn't a Web application, a more loosely coupled application has greater flexibility.

Key interfaces

WebWork attaches behavior to actions and other classes via the use of interfaces. For example, if you need one of your actions to interact with HttpServletRequest, your action must implement the ServletRequestAware interface. This interface includes only a single method (setServletRequest()), which is called by the framework on any action that implements the interface. Your action can include a private request member variable that is set through this method. In WebWork 1.3, this interface has been replaced with a call to the static method ServletActionContext.getRequest().

An interesting variant on this theme is the SessionAware interface. It provides access to this user's session. Like ServletRequestAware, it includes a single set method (setSession()). However, the type passed as the user's session is a java.util.Map, not HttpSession. WebWork maintains the session information for you, keeping it in a Map instead of HttpSession. This means that you can support session tracking without being tied to the servlet API. In WebWork 1.3, this interface has been replaced with a call to the static method ActionContext.getContext().

Most of the behavior that isn't intrinsic to the framework is attached to individual classes using interfaces. The interfaces are very cohesive, generally offering a single method. This provides an elegant means of enabling behavior without overburdening the framework with unneeded functionality.

The value stack

One of the built-in facilities of the framework is the value stack. This is a utility class that supports the access of information from the view. Semantically, it is a stack of values, implicitly placed there by actions in the course of execution. The WebWork expression language (covered next) uses the value stack heavily.

Regardless of the implementation, the value stack makes writing view elements (i.e., JSP) much easier than other frameworks do. For example, consider the use of localized properties for holding the label text for the fields on a page. As the page is loaded, the framework calls the getText() method on your action, passing the key, which looks up the message body from the ResourceBundle. It then places that value on the value stack. For example, to populate the label for a textfield (one of WebWork's UI components) with the value from the properties file, you can use the value stack method text:

<ww:textfield label="text('input.duration')"
   value='<webwork:property value="duration"/>' />
1 2 Page 1
Page 1 of 2