Solve your servlet-based presentation problems

Flex the MVC presentation layer with these viable alternatives to JSP

Sun Microsystems created Java servlet technology, and it was good. (See Resources.) All subsequent Java server techniques have been based on servlets. And while nobody argues against servlets' efficacy, the debate rages on over which follow-on technologies (if any) are best for solving Web-based presentation problems. Those problems include:

  1. Separating presentation (HTML) from content generation code (code that accesses databases and generates XML documents, result-set data structures, Java object data, and so on)
  2. Maintaining consistency with the modern component-based software construction paradigm, to leverage modularization and code reuse
  3. Reuse and nesting of markup in different page contexts (templating)
  4. Minimizing the learning curve for new scripting languages and tag vocabularies, and maximizing their compatibility with HTML authoring tools

Combining code and presentation obfuscates the design intent behind both elements, and encourages the designer/programmer to design the software and the page simultaneously -- two very distinct activities. Or, even worse, if separate page designers and programmers work on the site, they won't be able to work simultaneously without breaking each other's code.

Disregard for object-oriented software-component construction and the inability to reuse and nest markup blocks are closely related to the blending of markup with content generation code. Mingling code and markup means specific content generation code is hardwired to specific formatting. That limits your ability to build encapsulated objects for generating content. There is a similar problem for presentation components (templates): if the presentation is mingled with the content generation code, you have little chance of reusing or nesting page elements.

The techniques discussed in this article (besides raw servlets) enhance HTML documents by employing scripting languages, sets of custom markup tags, and automatic Java class generation to help solve the first three problems in the above list. If it is too difficult for nonprogrammers to learn to use these tools, then we must still deal with the problem of programmers being forced to become page designers. Page designers rely on HTML authoring tools, so new tags and scripts should be as friendly to authoring tools as possible.

I did not include performance and scalability in the list of problems, but they are primary issues. Commercial servlet engines generally provide excellent performance and most now offer high-end scalability features, so most servlet-based presentation solutions will perform and scale well. However, some techniques add loads to the server, such as realtime XML parsing and XSL processing. The performance-analysis details of adding those loads are beyond the scope of this article.

The following discussion describes some servlet-based Webpage-presentation techniques, with respect to the above list of problems. Specifically, this article discusses the main techniques for solving presentation problems by focusing on a small, representative sampling of systems that implement them. A raft of servlet-based templating engines and server-side Java application frameworks are available or in development, but are not mentioned here.

Raw servlets

Servlets are a vast improvement on the heavyweight process-per-request programming model used by CGI scripts. The servlet model of handling requests using lightweight Java threads (one per client request) is much more efficient. The mini-programs also add a degree of persistence across requests, without using a formal database or disk storage. Servlets remain the mainstay on the Java server for managing client requests.

However, trading in CGI scripts for Java servlets does not address the problem of the HTML deeply embedded within the code -- be it Perl or Java -- that generates the page content. Servlets are commonly used to dynamically generate HTML pages for interactive Websites by aggregating the HTML text and writing it to a java.io.PrintWriter object. This tedious process couples presentation and content generation. (Perl's text manipulation prowess actually makes it the better language for this.) As a direct result, either the page designer must learn Java programming, or the Java programmer must learn page design.

Building presentation components using raw servlets is conceivable, especially if the design included some mechanism for using and reusing blocks of HTML, into which dynamic content could be embedded at request time. The rest of the techniques rely on the addition of some form of templating to raw servlets. You can consider these as alternatives to a roll-your-own approach to Webpage templates.

Templating engines

Templating is a technique that enhances static HTML documents by adding either scripting code or custom tags, or by automating the creation of Java classes that represent the documents. A template, then, is a reusable piece of enhanced HTML that, through Java manipulation or embedded scripting, can facilitate the runtime inclusion of dynamically generated content. The rest of this section briefly describes three exemplary open source templating engines.

WebMacro

WebMacro provides a minimal framework for implementing the Model/View/Controller (MVC) architecture in a Web context. (See Resources for links.) The framework facilitates the mapping of requests to and the execution of templates, and provides them with session information and any business object data they need to access. The scripting language allows the templates to randomly access the business objects. In MVC parlance, the business object data comprise the model, the templates are the views, and the code that maps the requests to and executes the templates is the controller.

WebMacro's core feature is its support for a simple scripting language (with a syntax resembling Perl's). Actually, WebMacro's creator, Justin Wells, calls it a "templating language" to distinguish it from a full-fledged scripting language. The language supports:

  • Primitive branching
  • Iterating through lists of objects
  • Access to data generated by external Java objects
  • Inclusion of other template files or any text file (static include)
  • Parsing of template files (dynamic include)
  • Local variables

WebMacro uses a deep Java reflection (see Resources) process to ascertain the topography of objects. This gives the templates access to data without the need for a special syntax to declare objects, bind local identifiers to object classes and properties, or get and set properties. A template can simply refer to a deeply embedded field (or a method) with dot-separated identifiers that match the object's field and method identifiers.

The most straightforward way to implement a service using WebMacro is to subclass Webmacro's WMServlet class and override the handle() method, which takes a request Context object and returns a Template object:

org.webmacro.Template handle(org.webmacro.servlet.WebContext)

The handle() function implements these steps:

  1. Use the WebContext information (including the HttpServletRequest object) to determine which template to use
  2. Put any data the selected template needs into the context
  3. Get the parsed template -- cache it if it's not yet in the cache
  4. Return the template to WebMacro, which will execute and render it back to the client

WebMacro completely removes HTML from Java code and embeds server-side scripting in the HTML files, transforming them into WebMacro template files. This makes the HTML more complex, and at least marginally reduces the utility of HTML-authoring tools. The added overhead for HTML authors is presumably outweighed by the programmer productivity gained by relieving you of the burden of generating HTML. WebMacro's simple, yet flexible, templating supports template reuse, and the dynamic-include feature supports template nesting.

The addition of a scripting -- sorry, "templating" -- language introduces a learning curve for HTML designers. WebMacro minimizes this problem by keeping the language primitive, but capable enough to handle the types of coding needed in a template.

WebMacro has recently been reimplemented by the Apache Software Foundation's Jakarta project (see Resources), and branded as the "Velocity" subproject.

FreeMarker

FreeMarker (see Resources) is remarkably similar to WebMacro. It implements MVC exactly as was described for WebMacro. The main differences are:

  • FreeMarker's scripting language is more sophisticated than WebMacro's: it has functions and Boolean expressions
  • FreeMarker's scripting language has a more heavyweight syntax
  • FreeMarker's template-caching mechanism has automatic cache updating, so modified templates can be automatically incorporated without bringing down the service

Both systems address the four presentation problems admirably, but WebMacro is better. A templating system's main purpose is to separate programming from presentation, so the benefits of FreeMarker's more sophisticated scripting capabilities are dubious -- especially if you consider presentation problems 1 and 4, listed previously. WebMacro's lack of "powerful" scripting features is an advantage, not a weakness.

FreeMarker's cache-updating feature is primitive, and both systems' caching is based on a filesystem. Neither system implements a database-caching mechanism, although both allow you to add one.

XMLC

I've contrasted the way raw servlets support dynamic pages -- by embedding HTML inside the Java code -- with the way the WebMacro and FreeMarker templating engines embed some form of scripting inside HTML files. XMLC's approach is completely different. (See Resources.) XMLC is a specialized Java compiler for HTML (or XML) template files. That's right, XMLC compiles pure HTML files into Java class files, with a unique class for each unique HTML template.

XMLC works by leveraging HTML's ID attribute in conjunction with the XML Document Object Model (DOM). (IDs are document-wide unique identifiers.) HTML templates are compiled into Java classes; each class contains a DOM representation of the document. The classes have access methods for all HTML elements with ID attributes. The Java code that manipulates the documents uses the access methods to modify the template by adding to or changing the corresponding elements. XMLC also uses the SPAN element to insert and modify text, and the CLASS attribute to group element sets.

The template classes implement the org.enhydra.xml.xmlc.html.HTMLObject interface and extend org.enhydra.xml.xmlc.html.HTMLObjectImpl. If you try XMLC, note that the supposedly XMLC-generated source code that appears in the bundled tutorial will not work because the classes fail to extend HTMLObjectImpl. The actual XMLC-generated code does it correctly. (See Resources for a link to the XMLC Website.) Servlet code that populates the template objects follows these steps:

  1. Instance the template object that corresponds to the request being handled
  2. Add dynamic content to the template object's DOM document by using the access methods
  3. Call the HTMLObject.toDocument() method to retrieve the resulting text response

XMLC was once distributed as part of the Enhydra open source Java/XML application server (see Resources); because of its popularity, it is now a standalone project. A new project at Enhydra.org, called Rocks Presentation Framework (see Resources), is underway; it is scheduled for an alpha release in late November. Rocks is one of several projects attempting to design and implement a comprehensive MVC presentation framework; it is built around XMLC.

One of the XMLC project's design goals is stated in the XMLC User's Manual:

The HTML pages will remain a valid mockup of the site. The designer may continue to evolve the pages as needed and updates can be passed to the programmer without losing the information necessary to generate dynamic pages. Since the HTML pages never contain anything but legal HTML, this falls out naturally.

This is a powerful concept. It means that the same HTML files the designer uses for a mockup become the presentation templates and remain valid throughout the project's life. It also means the designers can work independently for long periods, and only when they're satisfied with a large set of mockup changes must they deliver it to the programmers. Although even minor changes to HTML files require recompiling, XMLC has a nice auto-recompilation feature that lets you configure your application to always use the latest templates without having to restart it.

XMLC does the best job (of the three templating engines discussed) of separating code from presentation because the templates are pure HTML, with absolutely no code added. This completely solves the learning-curve problem. The HTML author only needs to learn how to use the ID and CLASS attributes and the SPAN element -- all standard HTML features. This also allows full leveraging of HTML authoring tools.

One problem with XMLC is its lack of support for nesting templates. The Rocks Presentation Framework may add that support.

JavaServer Pages (JSP)

JavaServer Pages (see

Resources

) is Sun's answer to Microsoft's Active Server Pages (ASP). JSP and ASP are similar technologies: both add to HTML special tags, a scripting language, and the ability to call out to external software components. Sun is promoting JSP as the standard frontend to server-side Java, including Enterprise Java (J2EE) tools. You can use JSP as a templating engine (more on that later), but its features and stature as the premier presentation technology put it in a category by itself.

The servlet, JSP specifications, and APIs are owned by Sun, but the official reference implementation of those APIs, Tomcat (see Resources), is now another Apache Jakarta subproject delivered by the Apache Software Foundation.

In a nutshell, a JSP file is HTML (or XML) with any combination of the following added:

  • Java scriptlets (any legal Java statements can be embedded in the HTML)
  • JSP tags for manipulating and querying JavaBeans
  • JSP tags for including and forwarding to other JSP pages
  • Custom (user-defined) tags

The JSP/servlet engine performs the following steps to handle a user request for a JSP page:

  1. The JSP page is converted into Java source code for a servlet
  2. The servlet source code is compiled into a class file
  3. The servlet class is loaded into the servlet engine's JVM
  4. The servlet is executed in a new thread

Steps 1 through 3 are performed only once. The JSP can be preconverted and precompiled; if not, it is converted and compiled when it is initially requested. Once it is loaded, it remains loaded until the servlet engine is brought down.

With access to the full power of Java from within a page file that intersperses the scriptlets with HTML and the special JSP tags, the page developer has an arsenal of tools. Its potential is limited only by the boundaries of the Java platform itself. However, this potential must be harnessed to avoid creating an incomprehensible and unmaintainable rat's nest. For a more complete discussion and debate of JSP's faults, read Jason Hunter's "The Problems with JSP" and "Reactions to 'The Problems with JSP.'" (See Resources for links.)

JSP Model 1 and Model 2 approach

There are two general design philosophies for JSP applications, the "Model 1" and "Model 2" architectures.

Model 1 is the simpler (and more problematic) of the two. It is a page-centric approach. Its components are JSP pages and JavaBeans. It relies on the JSP page itself to perform all logic related to request handling and session handling. You can access data outside the page by calling out to beans, but much of the application logic resides in the page. Nontrivial applications implemented using Model 1 are likely to result in the rat's-nest syndrome.

Model 2 is more interesting and more useful. It adds a controller servlet component that is missing from Model 1, creating what amounts to the MVC paradigm. Model 1 encourages putting session- and request-handling logic in the JSP page; Model 2 offloads that processing to the controller servlet. The controller servlet -- the frontend for handling requests -- maps them to JavaBeans for generating content and to JSP pages for viewing the content. This is equivalent to the steps executed by WebMacro's handle() method.

The Model 2 approach is, for all but the simplest applications, a big improvement over Model 1, but Model 2 is not a panacea for the rat's-nest syndrome. Model 2 still leaves the door open for a lot of misplaced code, which can make your JSP pages ugly and your application brittle. The common setup -- nested HTML tables containing dynamic content -- will routinely harm Model 2 pages that do not have a set of guidelines or a framework for JSP development.

JSP as a templating engine

Prior to JSP 1.1 (released in early 2000), liberal use of Java code scriptlets in JSPs was a virtual necessity. JSP pages containing all this code can hardly be considered presentation "templates" -- they're actually presentation logic source code files. Version 1.1 introduced a powerful tag extension feature that lets you define custom tags and associate them with Java classes. With tag extensions, you can move the scriptlets to the tag handler classes. You can also use JSP as a templating engine by encouraging the development of rich sets of custom tags whose handlers contain all the Java code that would have otherwise been in the JSP page. While this doesn't eliminate the possibility of using lots of scriptlets in the page, it almost eliminates the necessity.

Since the release of JSP 1.1, many application server vendors have bundled extensive tag libraries with their servers (including BEA's WebLogic and Allaire's JRun). Vendors are also developing JSP-enabled authoring tools (such as IBM's WebSphere Studio). These tag libraries and tools raise JSP's usefulness and desirability significantly.

Like WebMacro, JSP has the dynamic- and static-include mechanisms, which support template nesting and reuse. JSP also exposes the dynamic-include mechanism to the tag-handler objects via the PageContext object, which is available to all handlers. Using custom tag libraries and the include mechanism, you can build highly dynamic, interactive sites with JSP pages that contain little or no code. While the overhead for learning to use tag libraries may not be trivial, it is preferable to creating files that combine HTML with code written in a full-fledged programming language, and calling them "pages." Such pages force the page designer to program, or the programmer to do work within a presentation page context.

Jakarta Struts

Struts (see Resources), another subproject of the Jakarta project, is analogous to the Rocks framework, but Struts actually has code. Struts is an MVC implementation of a presentation framework that uses JSP pages as the views. The Struts framework includes an implementation of the controller servlet that maps requests to actions and JSP pages. (The actions drive the state of the model.) The other main part of the system is an extensive custom tag library. The tag library, in concert with the controller servlet and the framework's own classes and interfaces, comprise the most robust presentation solution described so far.

By default, Struts reads an XML configuration file that defines the application's request-to-action mappings. Each mapping defined in the file causes an instance of the ActionMapping class to be constructed and loaded. This happens at startup if the file exists; otherwise, you can write code to instance and load the mapping objects. The mapping objects relate a request's URI with the Action class that implements the action for that request, and optionally with an ActionForm bean that stores the request's form data.

To handle each request, the controller servlet executes the following sequence:

  1. Match the request URI to an ActionMapping object.
  2. If the mapping object specifies an ActionForm bean, try to get an instance from the user session (or the request, depending on the scope of the form). If none are found, construct one and add it to the session (request).
  3. If using the ActionForm bean, call setters on every bean property for which there is a like-named request parameter. (This mechanism supports multi-page forms.)
  4. If the action form bean is a validating bean, call its validate() method.
  5. If the validate() method returns an array of error message keys, store the array as a request parameter and forward-control back to the input form (specified in the mapping object). The error messages will be handled by the <struts:errors/> tag in the input form.
  6. If no instance of the Action class is named in the mapping object, construct one.
  7. Call the Action class's perform() method.
  8. If the perform() method returns a non-null ActionForward object, forward-control to the indicated JSP page to generate the appropriate response.

The Action class's perform() method will generally execute these steps:

  1. Validate the user session
  2. Manipulate business-logic components to process this request
  3. Update any beans used to provide content for the next page
  4. Return the ActionForward object (retrieved from the ActionMapping object) that points to the next JSP page

JSP pages created for Web applications that run within the Struts framework look like Webpages -- no profusion of code snippets and hard-to-read syntax, mostly just HTML-like tags. Moreover, the Struts framework provides at least a partial solution for problems that other presentation tools leave unsolved. In addition to code that maps requests to forms and action classes, Struts provides significant support for localization, input validation, error handling, form input handling, and multipage forms.

Jakarta Struts is a very young open source project, officially begun on May 31, 2000 using a base contributed by Craig McClanahan. Struts is a Web application presentation framework project to watch.

XSL templating

XSL (Extensible Stylesheet Language) has of late become a very popular XML technology. (See Resources.) XSL is an XML language for specifying stylesheets. An XSL stylesheet drives the transformation of an XML document from one XML language into another XML language. In particular, an XSL stylesheet can specify how to display data contained in an input XML document as a Webpage, by describing a transformation and adding some formatting required to generate a desired output HTML document.

The XSL elements that specify transformation operations come from a sublanguage of XSL called XSLT. Another sublanguage, XPath, provides random access to any part of the XML document. XSL adds formatting elements to XSLT and XPath.

Just as various XML parsing programs are available, XSL processing programs that perform transformations are now available. As the XSL specification and related specifications (XPath and XSLT) have matured, the Web has begun to see applications that use XSL processors. These data-driven applications dynamically generate XML content on the server. That content is applied to XSL stylesheets on the server (sometimes on the client) to produce HTML pages for consumption by client browsers.

Applications that use XSL for page presentation rely on an architecture that essentially delivers pure data in XML form -- the final step is styling the data. This data-centric type of application works best in a document-publishing environment, in which the content is largely static. You can then use XSL to target different types of clients. You can format the same XML document uniquely for Web browsers, PDAs, toasters, and so forth by applying different XSL stylesheets.

The performance of XML parsers and XSL processors is adequate, so their use on the server to process the XML-to-HTML transformations is not a disabling bottleneck for real-world applications. However, for dynamically generated content found in interactive Web applications, XSL processing fares poorly with respect to the problem list.

The real-code components (servlets, classes, beans) of these data-centric applications produce XML documents in response to requests. The Java code's job is done when the XML response is produced, but much more processing is required to transform an XML document that contains dynamic content into a Webpage. For example, XML elements must be sorted and filtered, actions often parameterized by other elements. This level of processing requires some level of programming expertise. The templating engines and JSP solutions can script the Java objects to generate prefiltered and presorted data. The XSL stylesheets can't do this, because by transformation time, the XML has already been generated.

In short, XSL stylesheets used to present highly dynamic pages are chock-full of code that traverses, selects, sorts, and formats the XML content. To exacerbate matters, the code is ugly and awkward because XSL documents are XML documents, and XML was meant to represent data -- not to support programming languages. It is not surprising, then, that when programming constructs are implemented in the XML tag-based syntax, the result is code that is hard to read and understand. It is definitely hard for a page designer to step up to XSL programming.

On the positive side, using XSL does force a clean separation of business logic and presentation logic, so you can develop the components that manipulate and update the model independent of the presentation components (the XSL stylesheets). And XSL has a static-include directive (dynamic content has already been generated once XSL is processed) that allows composting pages from multiple XSL template files.

Wrap-up

Many other commercial and open source tools purport to solve the page presentation problems; many of those tools adhere to the MVC architecture. Another such system, whose absence from this article would be conspicuous, is Apache's Turbine project (see Resources), part of the Java Apache Project. Turbine is another comprehensive, MVC-based Web application framework, and a more comprehensive framework than Struts. Some of Turbine's functionality overlaps with services provided by J2EE application servers.

Turbine introduces the concept of combining presentation techniques. There is no reason that a framework cannot accommodate multiple techniques; Turbine was designed to support WebMacro/Velocity, FreeMarker, JSP, and the Cocoon publishing framework. (Cocoon, from the Apache XML Project, is based on XSL.)

A simpler example of a hybrid approach would be a JSP-based Model 2 system that could handle certain requests by executing a bean (or forwarding to a servlet) to perform the XSL processing and return the resulting HTML response. Such hybrids will probably increase in popularity as servlet-based Web applications continue to proliferate.

If you decide that no available framework solves your applications' particular presentation problems, you may want to build your own frameworks. If you decide that neither JSP nor any of the templating engines solve your page-building problems, you may want to do that yourself too. Regardless, here is a set of templating mechanisms that are useful for solving the presentation problems:

  • HTML (enhanced) template documents into which content can be dynamically embedded
  • Some level of scripting support in the templates
  • An include mechanism, especially a dynamic include, that enables template nesting
  • A convenient syntax (or XMLC's DOM access API) for embedding data in the template
  • Template support for HTML forms and form input fields
  • Built-in common presentation components in the form of reusable templates (custom tags, if you are using Struts)
Kevin Unger, a senior software engineer at Niku Corp., is part of a team that is building enterprise-class server frameworks to support interoperating products for the services marketplace. Kevin has been developing in Java for two years, and developed in C++ for seven years. He has a bachelor's degree in computer science from the University of New Hampshire.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies