Comparison of Java Web Frameworks

Neal Ford
CTO
The DSW Group, Ltd.
neal.ford@dswgroup.com
http://www.dswgroup.com

Building web applications is one of the most common uses of Java today. Over the serveral years that Java web API's have existed, best practices have emerged.Along with best practices (such as the almost universal use of the Model 2 design pattern, covered below), web frameworks have also appeared. In fact, Java web frameworks, particularly open source ones, have sprouted like mushroom after a rain storm. Variety is a good thing, but how can developer make intelligent choices when so many are available?

That is the purpose of this paper. It provides an overview of a variety of web application frameworks, comparing and constrasting their advantages and disadvantages. Where possible, the same sample application is implemented in each framework, allowing you to compare apples to apples and see which framework you like best.

Most of these frameworks use the Model 2 design pattern, based on the Model-View-Controller design pattern found in the book Design Patterns: Elements of Reusable Object-oriented Design by Gamma, et al. First, I'll cover a little history of Model 2, then provide comparisons of the following frameworks:

Model 2

If you are familiar at all with design patterns, you have probably heard of the Model-View-Controller pattern (affectionately known as MVC). It is the poster child for design patterns. In the GoF book, MVC appeared in the introductory chapters as the example pattern. MVC has its origins in Smalltalk, where it was used in the graphical user interface for “traditional” (non-web) applications. It is a design pattern for separating data from its representation. The developers of Smalltalk realized that it is a Bad Thing to have the data and the view of a system coupled together too closely. Any change in either the data or the view requires changes to the other. MVC mitigates this problem. It separates the constituent parts of the system depending on their function.

The Model is responsible for the data and rules in the system. The model coordinates business logic, database access, and all the other critical non-visual parts of the system. In a spreadsheet, the model represents the numbers and formulas that make up the data. The View in MVC renders the display of the data. In the spreadsheet example, you can look at the numbers either in a grid, a chart, or a graph. The numbers are the same, only the visual representation differs. The grid can become a chart or vice versa without touching the underlying values of the numbers. The Controller is the mechanism by which the view and the model communicate. In a spreadsheet, this can be the keyboard, mouse, or some pen-based input device. In any case, the controller changes the value shown by the view and in turn changes the underlying model value. The controller acts as a conduit between the model and the view.

A good example of MVC in action is the Swing user interface controls in Java. In Swing, each control (even components like JButton) has an underlying model that controls its content. This is why it is so easy to change the look and feel of a Java application because you are changing the view without touching the model. If you have written code for the more complex controls like the JTable or JTree, you have ample experience writing models. In Java, models are most frequently implemented as interfaces. You can think of the interface as a list of questions you must answer about the data being modeled. If you can answer the questions, the control can take care of rendering the correct view.

MVC was created to handle the graphical user interface portion of Smalltalk applications. The underlying idea is a good one. However, MVC as it is stated in the GoF book and elsewhere doesn’t seem to mesh well with the web application world. It wasn’t until recently that this pattern was extended to make it suitable for the distributed web world.


The Emergence of Model 2

Back to the problems stated above concerning the shortcomings of the servlet-centric and JSP-centric application development. Managers and beleaguered developers both reached the same conclusion: there must be a better way to build web applications. The problem faced here is the same one that spawned MVC in the first place: the desire to separate business logic from user interface. MVC was designed with traditional applications in mind, where the user interface portion has rich capabilities and is closed tied to the rest of the application. Web applications are different. The user interface is rendered as HTML, which is then interpreted by the browser. This user interface model is more decoupled than in traditional development environments like Smalltalk or desktop Java applications. Designers looked at MVC and modified it to work within this new development paradigm. This work led to what is now popularly called “Model 2”, as in the second version of MVC. Model 2 doesn’t change the definition of MVC, it just casts it in terms of web development. In Model 2 for Java web applications, Java beans represent the model. Notice that this may include either simple Java beans, Enterprise Java beans, or Java beans that act as proxies for EJB’s. The view is rendered with JSP, which makes sense because JSP is already a type of HTML document. The controller is a servlet, which is well suited to executing Java code. This plays to the strengths of servlets, utilizing the services of the servlet container for lifecycle and invocation, without forcing servlets to generate mixed Java code and HTML.


The typical Model 2 scenario is shown in figure 1. The user invokes a controller servlet (more about this design later). The servlet instantiates one or more Java beans that perform work. The servlet then adds the bean or beans to one of the JSP collections and forwards control to a JSP. The JSP extracts the Java beans and displays the results. One of the key concepts in this design mandates that no real logic be performed by the JSP. The JSP is just the view and shouldn’t be involved in any code that better implemented in the model. The model beans in this design should not be aware that they are being used in a web application. If you ever find yourself importing any of the web development packages (such as javax.servlet.*), you have erred. The model beans should be useful in non-web applications. Just as in traditional MVC, the controller servlet acts as a facilitator between the model and the view.


Figure 1 The Model 2 design pattern separates the working parts of the application into specialized parts.

In contrast to more haphazard design, Model 2 features a clean separation of responsibilities between the parts of the application.


Using Frameworks

Model 2 is a perfectly good paradigm for building web applications. As developers build applications and become more experienced, they start discovering common parts that can be used over and over. Developers quickly discover that many of these parts are generic and can be combined to form larger generic parts. For example, the controller servlets that are generated in Model 2 applications have many identical features. These generic parts can be built in such a way as to foster reusability. Design patterns facilitate building these types of reusable artifacts. Once you have a collection of pre-built, generic parts, you have the beginnings of a framework. A framework is a set of related classes and other supporting elements that make application development easier by supplying pre-built parts. Building larger parts from generic parts is an example of a framework. Frameworks provide infrastructure for application development. Similar to the frame that exists when you construct a building, a framework provides the skeleton on which you can hang the specifics of the application.
Frameworks exist in abundance. Just like there are numerous kinds of frameworks used when constructing buildings, there are many different web application frameworks. Some are offer very specific, limited infrastructure while others provide everything including the kitchen sink. Table 1.1 lists a few of the available frameworks. This list is far from exhaustive – there are dozens of frameworks available.

Because there are so many available, frameworks are available to fit virtually any project. Most are free and/or open source. The only expensive frameworks are those that incorporate some sort of proprietary technology. For example, BEA sells a framework called Jolt for incorporating their Tuxedo messaging service with their application server. Given the wealth of availability, which one should you choose? And should you use one at all? The rate of turn over in the technology world frequently generates questions like this. Before choosing a framework, you should be careful to understand the distinction between a design pattern and a framework. Model 2 is a design pattern; Struts is a framework that utilizes the Model 2 design pattern. Turbine is also a framework that uses the Model 2 design pattern. Part two discusses both these and other frameworks. While looking at these frameworks, you must decide how suitable it is for your project. In the construction world, the framework to create a doghouse is different from a skyscraper framework. Now matter how sexy a framework is, choosing the wrong one can impede your progress rather than enhance it.

To give you an idea of how a framework fits together and how you might use it, the following sections provide an overview of the architecture and capabilities of two of the more popular frameworks, Struts and Turbine.

A Flavor of the Struts Framework

Struts is an open source framework for building Model 2 web applications. It is part of the Jakarta project hosted by Apache. You can download Struts including the documentation at the Struts homepage: http://jakarta.apache.org/struts. The primary areas of functionality in Struts are:

The information flow of an application based on the Struts framework is shown in the figure 2.


Figure 2 Struts provides a framework consisting of a generic controller servlet, classes to encapsulate actions, and infrastructure to pass information within the web application.

In Struts, the information flow is very similar to that of plain Model 2 applications. All requests are dispatched through a single controller servlet that is part of the framework. This controller provides numerous application wide services, such as database connection pooling and automatic request dispatching. The controller creates action classes, which are built by the developer to perform the work of the application. These action classes extend the Struts Action class. This is a perfect example of a reusable framework part – the controller is designed to create Action sub-classes to perform work. This aspect of Struts is based on the Command design pattern, which allows for parameterizing activities.

The action instances create model beans that perform domain specific activities. This includes executing business logic, connecting to databases, and calling other bean methods. The model beans encapsulate the real work of the application just as in Model 2. Once the action instance has utilized the model beans to perform work, it forwards the models that contribute to the display via the controller to a view component, generally a JSP (although other view options are possible – see the discussion on Velocity). The view extracts the model beans and presents the visual results to the user. As you can see, this is the same general information flow described in Model 2. Struts provides a great deal of the infrastructure to make it easy to accommodate this information flow.


Struts handles other details of application development as well. The framework includes numerous custom JSP tags to aid in constructing the view. It also includes classes to aid in internationalization, database connection pooling, flexible resource mapping, and a host of other facilities.

Struts provides a fairly lightweight framework whose primary job is to facilitate building web applications using Model 2. I estimate that Struts saves from thirty-five to forty percent of the typical amount of effort to build a Model 2 application. One of Struts strengths is its cohesiveness – it doesn’t provide services outside those needed for building Model 2 applications. Other frameworks are much more extensive. The Turbine framework is one of them.

A Flavor of the Turbine Framework

Turbine is a much broader web application framework. It is also an open source project available from the Jakarta web site hosted by Apache. You can download Turbine at http://jakarta.apache.org/turbine. Turbine is a large services based framework. It is like the hardware bus on a computer, where you can plug in parts to provide capabilities. Figure 3shows this concept. Turbine acts as a foundation for services. These services cover a wide variety of capabilities. You can use as many or as few as you need to implement your application. The classes that define the services are registered with Turbine through a configuration Properties file.

Figure 3 Turbine acts as a loose framework where services can be “plugged in” to build up the behavior of the web application.

The Turbine framework consists of numerous classes (over 200) to handle a wide variety of pluggable services. A list of the base services provided by or supported by Turbine appears in the following table.

Service Description Use
Assembler Broker The service that allows assemblers such as Screens, Actions, Layout and Scheduled Jobs to be loaded. Facilitates building Model 2 applications within Turbine.
Cache Provides a persistent object storage mechanism within your application. Allows you to cache object references (for example, serialized beans).
Castor The Castor service provides support for the Castor object-relational database-mapping tool. Castor is an well known open source project that is supported by Turbine. Used to model relational database tables and rows as objects. See www.castor.org.DB A common front end to all database systems, it handles database connectivity within Turbine. This service also provides the brokers for Connection Pooling and Database Map Objects Handles database management and interaction within the framework.
Factory A service for the instantiation of objects with either the specified loaders or default class loaders. Acts a an object factory to abstract the creation of objects.
FreeMarker FreeMarker is an alternative to JSP for rendering HTML output. This service process FreeMarker files inside the Turbine Layout/Navigations and Screen structure. Use FreeMarker instead of JSP or Velocity for the user interface part of the web application.
Intake Provides input validation along with a standard parameter-naming framework. Execute validation code for web applications (such as range checking, formatting, etc).
JSP Set of classes that process JSP files inside the Turbine Layout/Navigations and Screen structure. Supports the use of JSP as the user interface for the web application.
Localization Single point of access to all localization resources. Used for building internationalized and localized applications.
Logging The default Logging implementation for Turbine. Allows custom logging for errors and application events.
Mime Type Maintains the mappings between MIME types and corresponding file name extensions as well as between locales and character encoding. Handles the valid document types for the web application as well as character set definitions.
Naming Provides JNDI naming contexts. Provides support for Java Naming and Directory Interface, which allows resources such as Enterprise JavaBeans to be referenced.
Pool A service for the pooling of instantiated Objects, allowing for the recycling and disposal of Objects in the pool. Provides support for generic object pooling. It provides the same kind of pooling mechanism that the Servlet engine uses for Servlets but exposes it to the application developer.
Pull Manages the creation of application tools that are available to all templates in a Turbine application. Enables the developer to create tools (such as image processors) and makes them available to the web application via the standard attribute collections.
Resources The set of classes and the functionality that allows for the reading and accessing data from within properties file. Supports accessing configuration information from Properties files.
RunData The service that manages the higher-level operations surrounding requests and responses. Provides an infrastructure around the standard request and response mechanism of the Servlet engine.
Scheduler Manages the schedule queue giving Cron like functionality. Allows the application to configure and run scheduled tasks.
Security A service for the management of Users, Groups, Roles and Permissions in the system, allowing for those Objects to interact with either Database or LDAP back ends. Handles authentication and authorization via this centralized service. This is similar to how most application servers handle security.
Servlet Encapsulates the information provided by the ServletContext API, and makes it available from anywhere in the code. Provides infrastructure to make information from the Servlet engine available to the web application.
Template The Service for the mapping of templates to their screens and actions. Supports user interfaces built from template languages (like Velocity).
Unique ID Allows for the creation of Context unique and pseudo random identifiers. Provides a generic mechanism for generating unique and random identifiers, useful for database keys or random number generation.
Upload Manages multipart/form-data POST requests, storing them temporarily in memory or locally. Provides the infrastructure to handle complex information passed to the web application from an HTML form tag, such as images or video.
Velocity The service for the processing of Velocity Templates from within the Turbine Layout/Navigations and Screen structure. Use Velocity as the user interface generator of the web application. Velocity is an open source template engine for generating web output (i.e., HTML).
WebMacro The service for the processing of WebMacro Templates from within Turbine Layout/Navigations and Screen structure. Use WebMacro as the user interface generator. WebMacro is an open source template engine for generating web output (i.e., HTML).
XML-RPC Manages xml-rpc calls to a remote Server. Allows the application to handle remote procedure calls, such as SOAP requests. This is an important component of Service-oriented Programming.
XSLT Used to transform XML with an XSLT stylesheet. Allows XML output of the web application that is transformed into suituable output (i.e., HTML) via the Extensible Stylesheet Language Transformation.

 

Many of the services listed in the table are not a part of Turbine per se. Rather, they are external API’s that are supported by the Turbine framework. For example, you can easily use Castor (which is an independent open source project) without using Turbine. Turbine is designed to be a loose framework with pluggable services.

Building Model 2 web applications with Turbine is only a small part of the overall framework. It is designed to offer one stop shopping for just about any kind of service you might need when building a web application. As you can see from table 1.1, it covers a vast range of capabilities via its services. When building Model 2 applications with Turbine, several services interact to produce results. The general relationship of these services appears in figure 4.

Figure 4 To produce Model 2 applications using Turbine, these Assembler types cooperate to encapsulate both business logic and visual layout.

Assemblers in Turbine are classes that build (or assemble) things and are part of the Assembler Broker service. For example, the Screen assembler is responsible for building the body of a response page, whereas the Navigation assembler builds the navigation header or footer for the page. Each of the assemblers are responsible for a small part of the overall handling of the request. This granular approach is good because the assemblers can be easily mixed and matched to customize what behavior is required.


When building Model 2 applications in Turbine, the flow of information is similar to Struts. It is shown in figure 5.

Figure 5 The information for a Model 2 application built in Turbine uses very granular assemblers to build up the appropriate response to a request.

The page assembler is the outer level container for the other modules in a Model 2 application. It processes a request, which is analogous to the controller servlet in Struts. When a request is received, the page matches an action class to the request and executes it. The Action module in Turbine is very much like the Action implementation in Struts. After the action has executed, the Page assembler uses the Screen, Layout, and Navigation assemblers to generate output. The Layout assembler is responsible for the general layout of the output. The Navigation assemblers provide an easy mechanism for header and footer-style navigation on the page. The Screen assembler is the interior of the generated page. The relationship between the Page, Screen, Layout, and Navigation assemblers is shown in figure 6.

Figure 6. The Page assembler encapsulates the other assemblers to construct a complete page. The Layout assembler handles the general layout of the page, which consists of one or more Navigation assemblers and a Screen assembler, which is the body of the page.

As you can see, there are more moving parts when building a Model 2 application in Turbine. This is because Turbine is a more general framework. Each aspect of the web application is handled by a specific service, and the services can be changed in a modular fashion without affecting other services. The advantage of a framework like Turbine appears in the flexibility and options it provides developers. For example, the Screen and Navigation assemblers above may be written in JSP as in Struts. However, other services can be “plugged into” Turbine to handle the user interface rendering. The Turbine developers themselves prefer the Velocity template engine to JSP for generating user interface in web applications. Velocity is discussed in an upcoming section. The disadvantage of Turbine is in its complexity. Because of its service-based architecture, building Model 2 applications is more complex than with Struts.

Tapestry

Tapestry is an open source Java framework for creating web applications in Java. It is developed by Howard Lewis Ship and hosted on Jakarta. It can be downloaded at http://jakarta.apache.org/tapestry/index.html. The project began in January 2000, it was released on SouceForge in July of 2000, release 1.0 was available in May 2001, and the current major release, 2.0, appeared in November 2001. The version I used for this chapter is version 2.2.

Tapestry is a large framework, more like Turbine than Struts. It provides a wealth of pre-built components to handle details like object pooling, session management, HTML components, and others. Because of the nature of the framework, it provides a high level of reusability for commonly needed elements in a web application. Coding in Tapestry is in terms of objects, properties, and methods, not URL’s and query parameters. The framework handles all the low-level web details of the application.

Architecture

Tapestry uses an alternative to scripting languages such as JSP and Velocity for presentation. It provides an all-encompassing framework using a combination of Java reflection, the JavaBeans API, and HTML templates. Much of the interface between components in Tapestry takes place through interfaces designed into the framework. The framework defines the flow of logic through the system with a collection of specifications (written as XML documents) and framework objects.

The application starts when the user accesses the application through the browser by pointing to the Tapestry ApplicationServlet. The servlet acts as the universal controller. It creates the Application Engine. The engine is the framework object that handles a user’s interaction with the application. An instance of the engine is created for each user. Thus, it acts as a proxy for a user. The engine reads the application specification from a configuration file, which defines pages. The engine then reads the page specification and template for the requested page to determine the contents of the page. The engine then uses this information to render the page for the user. This overall architecture appears in figure 7.

Figure 7 The Application Servlet boot-straps the Application Engine, which reads the specifications for the application and renders the results.

The specification documents (both application and page) are XML documents. The template is an HTML document with replaceable parts. It is not a JSP or template-based view like Velocity. Instead, the HTML elements serve as placeholders, replaced by the controls and JavaBeans referenced in the specification document. The Application Servlet serves as the entry point into the framework. Once it has created the engine, there are no other parts of the “traditional” web API in a Tapestry application. Tapestry contains lots of moving parts. Because the framework handles so much of the application for you, it must perform a lot of work.

Tapestry is driven by specification documents. The application, pages, components, and libraries are all referenced through these documents. Generally, the first access to a resource by Tapestry is through the specification document, which leads to the other resources Tapestry must load to fulfill the request. Understanding the specification documents and their uses is critical for using Tapestry.

Tapestry is a very complex framework. To create the simplest web application you must understand a fair amount about the architecture and components. Because it is all-encompassing, you can’t rely on your prior knowledge of the web API’s in Java. It is very much like learning a completely new user interface framework from scratch. Fortunately, the authors did not reinvent the entire wheel. If you have used other GUI frameworks, you can see many familiar features in Tapestry. In particular, it leverages the JavaBeans component model for much of its automatic functionality (like matching access and mutator names to properties on a page).

WebWork

WebWork is produced by the Open Symphony project (www.opensymphony.com). This over-arching project includes many embedded projects, with WebWork as one of them. The framework is currently at version 1.2.1 and may be downloaded from the Open Symphony web site. It is based on best practices and design patterns that have long standing records of accomplishment. It is also based on a strong motivation to keep things as simple as possible while maintaining flexibility (which they acknowledge is a difficult balancing act).

WebWork implements what its documentation calls “Pull HMVC”, which stands for “Pull Hierarchical Model-View-Controller”. This is their own take on Model 2. 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 “normal” Model 2 in that the view accessing information that is already 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 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. This construct is defined and described in section 7.3.4. 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. The Turbine documentation and white papers also refer to this “pull” paradigm of Model 2.

WebWork takes advantage of the web API’s in Java rather than hide them. However, it doesn’t rely on them as much as unadorned Model 2 or Struts. Like Struts, WebWork includes a central controller which creates Action objects (thus using the Command design pattern as described in section 4.3). However, the return and packaging of model information is different in WebWork.

Architecture

The architecture of WebWork follows the common architecture of most Model 2 web application frameworks. The overall architecture and flow appear in figure 8.

Figure 8 The WebWork architecture has much in common with unadorned Model 2 and Struts, with changes in information flow from the model objects.

WebWork is highly configurable 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 and uses the configuration 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.

When the Action returns, it returns a mapping to the ServletDispatcher. It dispatches control to a view component, which can be any view framework (for example, JSP, Velocity, etc.). The view extracts information needed from the “Value Stack”. This construct is maintained by the framework by caching information from both actions and model beans for use by the view.

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 object easier to access 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 meta-data 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 widgets.

Configuration

Configurability is one of the hallmarks of WebWork. The framework is configured by a variety of properties files. The framework includes a default properties file and allows you to override these settings in additional application specific properties files. WebWork uses the following properties files to configure the application.

Properties File Purpose
webwork Primary configuration file for the framework. It includes package names, user interface settings, and entries that point to the other configuration files.
default The default properties file for WebWork. The framework reads all these values, then selectively overrides them from the webwork properties file.
views This file contains all mappings for visible resources in the application. It includes mappings for actions and user interface elements. The Actions return values that reside in this file to point to a destination resource.
log4j This file is used to set up logging for WebWork. This is a standard Log4J properties file (see section 17.6.3 for more information on Log4J).
Action specific Properties Internationalization 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 are 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 default and webwork properties files is “webwork.configuration.properties”, which points to all the other properties files. Thus, if you want to store most of the properties files in another location, you can point to it from this property in the main configuration file. The framework looks for and tries to load both “default” and “webwork” files upon startup. All the other files can load based on property settings in the one of the two main files.

Some of these files may also be XML files. In particular, WebWork includes a DTD to use an XML document for view mappings. If you prefer to keep view information in XML, WebWork now supports that. A property in the main properties file allows you to specify an XML view file instead of the standard properties file.

To make it easier to set up the directory and configuration file structure WebWork expects, the framework install includes a “skeleton” project named “skeleton-project.zip” 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 jumping off point for building a WebWork project rather than setting it up on your own.

Velocity

Velocity is a Java based template engine. It is useful as a stand-alone utility for generating any text based information, such as source code, HTML, XML, SQL, reports, etc. It also includes facilities to incorporate itself into Java web applications via a servlet. It is an open source project, hosted on the Jakarta site at Apache. You can download it at http://jakarta.apache.org/velocity. The first (beta) release was on March 26, 2001, and the current version as of this writing is 1.3.1, released on March 31, 2003.

Velocity provides an implementation for something that is elusive in the development world: a simple, powerful scripting language to handle presentation chores in a web application. It is easier and friendlier than either JSP or JSTL but provides a superset of the capabilities of those techniques. It has found that sweet spot of unobtrusive usefulness without compromising the performance or design of the web application, which is no small feat.

Velocity allows web user interface designers to embed simple script elements in web pages. It helps enforce Model 2 architecture, allowing simple user interface scripting. It does not violate the separation of concerns important to good design. It does not encourage placing business logic or other model code within the page. The scripting language is not well suited to writing that type of code. Rather, it helps make the job of the user interface designer easier by providing a simple scripting language for automating presentation.

Architecture

Velocity works either as a stand-alone template engine or through a servlet. When used as a servlet, the developer extends the VelocityServlet included with the framework. This servlet becomes the controller for a page. Generally, each page has its own controller servlet. The developer adds code to the context object (which the template language uses to store name/value pairs) and merges the template and the context object to produce output. The template is an HTML document that includes Velocity template language constructs. Graphically, building a web application using Velocity is depicted in figure 9.

Figure 9 In Velocity, the VelocityServlet instance acts as the controller, driving model objects, and merging the resulting data with the Velocity language template, which generates the user interface.

The general steps to using Velocity are:

  1. Initialize Velocity. The VelocityServlet handles this for you for web applications. Initialization parameters are specified in a properties file.
  2. Create a Context object. This is passed as one of the parameters for the method you override in the servlet.
  3. Add data objects as name/value pairs to the Context.
  4. Choose a template.
  5. Merge the template and the Context to produce output.

When extending VelocityServlet, you must override a single method, handleRequest(), which returns a template. This method takes as parameters the HttpServletRequest, HttpServletResponse, and a Context object.

If you do not want to extend the Velocity servlet, you can create and initialize the Velocity engine yourself. This is required if you are using Velocity outside the web API or if you are implementing another framework that takes the place of servlets. For example, you could initialize the Velocity engine within an Action in Struts, bypassing the JSP presentation layer. To create the Velocity engine yourself, the steps are the same as above. The listing shows the general template used to bootstrap Velocity.

Listing You can create the Velocity engine yourself if you don’t want to use the VelocityServlet provided with the framework.

 
import java.io.StringWriter;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;

public class Test {
    public doIt() {
        Velocity.init();

        VelocityContext context = new VelocityContext();

        context.put("name", new String("Velocity"));

        Template template = null;

        try {
            template = Velocity.getTemplate("mytemplate.vm");
        } catch (ResourceNotFoundException rnfe) {
            // couldn't find the template
        } catch (ParseErrorException pee) {
            // syntax error : problem parsing the template
        } catch (MethodInvocationException mie) {
            // something invoked in the template
            // threw an exception
        } catch (Exception e) {
        }

        StringWriter sw = new StringWriter();

        template.merge(context, sw);
    }
}

 

InternetBeans Express

InternetBeans Express is a feature of the Enterprise version of JBuilder, which is the version of JBuilder that includes web development. It consists of a series of components that integrates with servlets and a custom taglib for use in JSP. These components are primarily concerned with the presentation tier of a web application. JBuilder contains other components to handle database connectivity. InternetBeans Express components use static template HTML documents and inserts dynamic content from a live data model. It is designed to make it quick and easy to generate database aware servlets and JSPs.

The components fall roughly into three categories:

The InternetBeans Express components appear in the development environment of JBuilder alongside the other components used to create desktop applications. InternetBeans Express has its own palette in the designer, which appears in figure 10.

Figure 10 The InternetBeans Express components appear just as the other components in JBuilder’s design view.

Building an application with InternetBeans Express is extremely fast in the best traditions of RAD development tools. The general steps are:

  1. Create a new project
  2. Create a new Web application
  3. Create the data model for the application (using Data Express components)
  4. Create the user interface template as an HTML document
  5. Create a servlet to act as a controller
  6. Use the designer to drop InternetBeans Express components on the servlet
  7. Use the property inspector to set the property value of the components
  8. Write any event handlers needed
  9. Add a single line of boilerplate code to the servlet’s doGet() and doPost() methods

Before developing an application, you need to understand the architecture and some key concepts about these components.

Architecture

The architecture of the InternetBeans Express components is reliant on some other components that exist in the JBuilder development environment, primarily the Data Express components. First, I’ll show the architecture and behavior of the Data Express components then move to the InternetBeans Express components.

The InternetBeans Express controls are data aware controls that replace are declared in a servlet and replace HTML template elements when the servlet renders the page. The component that controls the rendering process and binds the various data aware controls together is the PageProducer. The relationship between the various controls appears in figure 11.

Figure 11 The overall architecture of the InternetBeans Express controls, relating the controller servlet, the Data Module, the PageProducern, and the HTML template.

The controller servlet contains the PageProducer component as well as the declarations and property settings for the ixControls. When the user connects to the web application, the controller servlet creates a reference to the Data Module, which in this case acts as both a boundary and entity class. It encapsulates both the database connectivity and the data from the table into a single component. The PageProducer then merges the contents of the ixControls with their corresponding controls on the HTML template to produce output.

Evaluating Frameworks

This last section is entirely optional. I have been living with frameworks for a while and have formed some opinions on what I like. While I’ve tried to be objective in the chapters on frameworks, there are some things that I tend to like more than others. This certainly has more to do with my personality than anything else. Someone famous once said that biographies are more about the author than about the subject and this is the case here.

Having disclaimed this section, here are my criteria for choosing a framework. I don’t mean to disrespect any of these frameworks. All the ones I covered are excellent works of craftsmanship.

Transparent Infrastructure

I tend to like frameworks that have a virtually transparent infrastructure. Struts falls nicely into this category. If you understand web development and design patterns, you can understand how Struts works after using it for an afternoon. This probably stems from the fact that I’ve used too many annoying heavyweight frameworks, mostly predating Java. Stuts is a nice mixture of transparent power and ease of use. I suspect this is one of the reasons it is so popular. Struts combined with either JSTL or Velocity is a favorite combination.

Tapestry, Cocoon, and Turbine are the polar opposites of this principle. All of these frameworks are very powerful but have a huge amount of code backing up that power. You must surrender yourself to the framework to use them. For building complex sites, I firmly believe that you could get it done faster, with less code, with one of these heavier frameworks. However, always lurking in the back of my mind, I can’t help but think that I’ll eventually find myself in a corner that I can’t escape. In other words, I’ll reach a point where I need to do something and the support offered by the framework becomes a prison.

Innovative Ideas

I tend to be drawn to innovative ideas, especially ones that are obvious in hindsight. The winner in this category is WebWork and the combination of the Value Stack and the Expression Language. Of the slightly heavier weight frameworks, I’m drawn to this one more than the others. It still uses JSP for the presentation layer (opening the door to mix and match JSTL). I think Cocoon also fits into this category but has other characteristics for which I don’t care.

Ultra High Cohesion and Low Coupling

I am a junky for high cohesion and low coupling. I have seen the benefits for these two principles too much not to admire any framework (or piece of software) that exhibit these characteristics. Velocity fits into this category. It is a single purpose tool for creating the user interface of web applications. It plugs into a variety of different frameworks because it is so modular.

Struts also falls into this category. It does one thing and does it well: it offers plumbing for Model 2 applications. Again, I think this is one of the reasons it is so popular. The code in Tapestry also exhibits low coupling. Everything in Tapestry that the developer sees is an interface, with backing concrete classes. From a coding standpoint, I think Tapestry has done a good job of creating a very flexible architecture.

For More Information

The material presented here is adapted from my book Art of Java Web Development. It is guide to the topics required for state of the art web development. This book covers wide-ranging topics, including a variety of web development frameworks and best practices. Beginning with coverage of the history of the architecture of web applications, highlighting the uses of the standard web API to create applications with increasingly sophisticated architectures, developers are led through a discussion on the development of industry accepted best practices for architecture.

Described is the history and evolution towards this architecture and the reasons that it is superior to previous efforts. Also provided is an overview of the most popular web application frameworks, covering their architecture and use. Numerous frameworks exist, but trying to evaluate them is difficult because their documentation stresses their advantages but hides their deficiencies. Here, the same application is built in six different frameworks, providing a way to perform an informed comparison. Also provided is an evaluation of the pros and cons of each framework to assist in making a decision or evaluating a framework on your own. Finally, best practices are covered, including sophisticated user interface techniques, intelligent caching and resource management, performance tuning, debugging, testing, and Web services.