Boost Struts with XSLT and XML

An introduction to Model 2X

Since the Java Servlet API's inception, developers have used diverse technologies to develop Web applications in Java. Recently, developers have started to recognize the merits of Model 2, a scheme derived from the Model-View-Controller (MVC) paradigm. Model 2's benefits include an improved separation of the application logic and presentation layers. Struts, built on top of Model 2, additionally offers Java developers a generic controller servlet, centralized configuration, resource management, and error handling.

In this article, we introduce Model 2X, a scheme that further enhances Struts. By replacing JSPs (JavaServer Pages) with XML and XSLT (Extensible Stylesheet Language Transformations), Model 2X offers an even better approach to separating logic and presentation. We start with an introduction to Model 1 and Model 2, describe how Struts implements MVC, and finally show how XML and XSLT can be used to improve the existing models.

Model 1

Understanding Model 1 is crucial to understanding the subsequent architectures we discuss in this article. Model 1's cornerstone is the JSP file, which extracts parameters from an HTTP request, calls the required business logic, handles the HTTP session, and then generates HTML.

A complete Model 1 application is composed of a collection of JSP files, mostly independent of each other, and, optionally, a collection of support classes and other components. Earlier technologies, such as ASPs (Active Server Pages) and PHP (hypertext preprocessor), used this same model.

Model 1's major, and possibly only, benefit: simplicity. However, Model 1 encourages the developer to mix business logic and presentation logic, a significant drawback. While this model is appropriate for creating small applications, complex application development with Model 1 can become difficult to manage.

Model 2, MVC, and Struts/JSP

Object-oriented paradigms in the form of the MVC architecture rescued the JSP and servlet world by defining Model 2. Figure 1 illustrates MVC's three parts and their implementation in Struts/JSP.

Figure 1. Model 2

Controller

As Figure 1illustrates, the Struts' main component is a generic controller servlet. The Struts controller provides the initial entry point for all HTTP requests routed to Struts. It interprets and dispatches all requests to individual actions implemented by the developer as subclasses of the Struts Action class. It also automatically fills out form beans from request parameters. Individual actions implement core business logic by, for example, making EJB (Enterprise JavaBean) calls, and access the model through JavaBeans. An XML file that maps request URIs to actions and form classes configures the controller servlet.

Model

The model takes the form of one or several JavaBeans. Those beans fall into three categories:

  • Form beans hold either the data the user entered in HTML forms or, more generally, any attribute passed either on the URL or in a POST. For instance, a form bean for a login page could have two properties: login and password. Form beans extend the Struts ActionForm class.
  • Request beans hold information needed to generate the HTML page. In the case of a bank account statement page, a request bean would have properties with information about the account as well as a transaction bean collection detailing the most recent transactions to display.
  • Session beans hold session information that persists between two HTTP requests by the same user.

View

The controller servlet forwards a request to a JSP implementing the view. The JSP can access the form, request, and session beans and outputs a result document (usually an HTML document) sent to the client. Struts provides four JSP tag libraries:

  • HTML: Helps create HTML tags, particularly by filling out HTML forms with data from the model.
  • Bean: Manipulates beans.
  • Logic: Implements logic constructs based on bean values.
  • Template: Handles page templates.

With the Struts tag libraries, you can usually avoid using any Java code in the view.

Struts/JSP drawbacks

While the Struts/JSP approach features many advantages over other models, it exhibits several drawbacks:

  • As in Model 1's case, nothing prevents a developer from embedding application logic into the JSP. Experience shows that many developers actually fall into that trap, often to perform a quick fix. This can lead to applications that are hard to understand and maintain.
  • The JSP syntax is not XML compliant and therefore fails to guarantee that resulting XML or HTML documents will be well formed.
  • The developer must learn new APIs -- the Struts tag libraries. Experience shows that gaining an understanding of the Struts tag libraries, particularly the bean and HTML libraries, can take a long time.
  • You can't implement a real processing pipeline in the view with JSP. Only basic includes and forwards are possible, effectively limiting the view's flexibility. For example, separating layout and style proves difficult.
  • With JSPs, you must recompile after every change, which can be time consuming. Just ask any JSP developer waiting for page compilation after every mouse click.

The solution to these problems must:

  • Restrict the visibility in the view to the model and some well-defined context information, such as resources.
  • Enforce well-formed XML and HTML.
  • Leverage existing languages or APIs.
  • Ease the separation of different view aspects, like layout and style.
  • Allow for a faster development cycle.

As detailed, the Model 2 technology currently features many issues that must be addressed. We believe the lightweight framework detailed below, based on an unmodified version of Struts and XSLT, exceeds the given requirements. We call the new architecture Model 2X.

Model 2X: Architecture overview

Model 2X is the symbiosis between Struts and XSLT. Model 2X uses the Struts model (its controller servlet), but the view implementation uses XSLT and beans serialized into XML instead of JSPs.

What is XSLT?

XSLT is a functional language designed to perform transformations on XML documents. It is part of a stylesheet language for XML known as XSL. XSLT uses XPath, an expression language that accesses or refers to parts of an XML document. In addition to XML dialects such as XHTML, XSL/FO (formatting objects), or SVG (Scalable Vector Graphics), XSLT can output any text format, including HTML or CSV (comma-separated values). Also part of the XSL specification, the XSL/FO language displays elements on a page. Its main application: generating PDF documents.

Integrate XSLT with Struts

The first approach to integrating XSLT with Struts is to call an XSLT transformer from within a JSP. You do that with a tag library -- the Jakarta Project's XSL tag library, for example. You now generate XML, instead of HTML, in the JSP. Thanks to an XSLT stylesheet, the XML then transforms into HTML or other formats. However, this transformation requires changes to Struts itself.

The most common way to generate HTML forms is through the Struts HTML tag library, which is not XML compliant and therefore unusable in conjunction with XSLT. Modifying the HTML tag library to output XHTML is easy, but it still changes the existing Struts 1.0 codebase.

Furthermore, the tag library solution requires programming in four separate places: the Action class (controller), the model beans, the JSP, and the XSLT stylesheet (view). This requirement creates a labor-intensive solution. Additionally, the roles of the JSP and tag libraries are limited to converting the model beans into an XML document.

The second approach, which is our proposed Model 2X solution, automates this task, effectively removing JSPs from the equation. As Figure 2 illustrates, this design decision forms the heart of Model 2X.

Figure 2. Model 2X

As you can see in Figure 2, the first part of the Model 2X pipeline is the regular Struts pipeline. The request is sent to the Struts controller servlet, then dispatched to the appropriate business logic, an Action subclass. The controller creates an ActionForm object; the object is filled with the appropriate request parameters. The Action subclass encapsulates the business logic, fills out the beans, and then forwards the beans to the view.

That is where the Model 2X pipeline differs from regular Struts: instead of a JSP implementing the view, a servlet, XSLServlet, now implements it with an XSLT stylesheet's help. This servlet first generates an XML document from the beans and context, and calls the XSLT transformer. We detail this process below, which you can achieve without changing Struts because you can forward a request to any URL in the Struts configuration.

XML generation

The process of transforming an object into a stream is known as serialization. Since Java 1.1 introduced the java.io.Serializable interface and related APIs, Java developers have understood binary serialization well. Binary serialization transforms a Java object into a binary stream that can be sent over the network or saved into a file. In contrast, XML serialization transforms a Java object tree into a textual XML stream.

Many closed and open source software packages, such as Castor, perform XML serialization. For the Model 2X application, we used a simple custom implementation. This simple implementation assumes that all bean properties are either primitive Java types or java.util.Collection subclasses.

The custom implementation recursively introspects the form, request, and session beans, and creates a DOM (Document Object Model) tree. Concurrently, the implementation serializes the resources and Struts configuration data known as context information. Figure 3 illustrates this process.

Figure 3. XML/XSL workflow

XSLT processing

The XML stream represents a translation of the model on which the XSLT stylesheet is applied. In the Model 2X application, XSLT transformation is limited to a single stylesheet cached by XSLServlet and applied to the XML stream provided by the Struts pipeline. You can enhance this simple architecture to provide several successive transformations or more advanced configurations as seen in the Apache Cocoon framework. An XML publishing framework, Cocoon uses XML and XSLT to build server-side applications. Its pipeline-based architecture makes it easy to separate content and logic, and to interact with many different data sources. XSLT allows Cocoon to adapt its output to different device capabilities such as HTML, WAP (Wireless Application Protocol), and so on.

Figure 3 shows an XSLT pipeline example. The following section presents another example of content and layout separation.

Transformation example

Consider a Struts application with a simple form bean containing two attributes:

  public class TestForm extends ActionForm {
      private String testString;
      private List testList;
  }

The XML serialization code produces the following XML fragment, assuming testString and testList are populated respectively with My Test String and One, Two, Three. Note that the element names in the XML document are predictable, making it easy to write the stylesheet:

  <page name="TestForm">
    <request>
      <TestForm>
        <testString>My Test String</testString>
        <testList>
          <item>One</item>
          <item>Two</item>
          <item>Three</item>
        </testList>
      </TestForm>
    </request>
  </page>

This simple XSLT template transforms the serialized stream to an XHTML fragment:

  <xsl:template match="page">
     <h2>Please enter some text and submit</h2>
     <br/>
     <form name="testForm" method="get" action="result">
       <input type="text" name="testString" 
value="{request/TestForm/testString}"/>
       <br/>
       <select name="outSelect">
          <xsl:for-each select="request/TestForm/testList/item">
            <option><xsl:value-of select="."/></option>
          </xsl:for-each>
       </select>
       <br/>
       <input type="submit" value="Submit"/>
     </form>
     <hr/>
   </xsl:template>

After transformation and HTML serialization, the result will look like this:

  <h2>Please enter some text and submit</h2>
  <br>
  <form name="testForm" method="get" action="result">
    <input type="text" name="testString" value="My Test String">
    <br>
    <select name="outSelect">
      <option>One</option>
      <option>Two</option>
      <option>Three</option>
    </select>
    <br>
    <input type="submit" value="Submit">
  </form>
  <hr>

Model 2X's major benefits

In this section, we explain the benefits that Model 2X offers compared to the earlier models.

Business and presentation logic separation

The raw material used by the stylesheet is the XML stream, which is entirely defined by the model and the context. Although some XSLT transformers support extensions, letting you call Java code or other languages from within a stylesheet, use of such extensions is limited due to the additional effort required and the resulting lack of portability. This difficulty effectively removes any possible side effects during the XSLT transformation and separates the business and presentation logic.

Use of standards

XPath is more powerful than the Struts 1.0 expression language and thus is the language of choice for extracting data from the source XML stream. With XSLT constructs -- such as <xsl:for-each>, <xsl:if>, <xsl:choose>, and attribute value templates -- Struts HTML, logic, and bean tag libraries become obsolete. XSLT provides not only similar but enhanced functionality over the Struts tag libraries using languages standardized by the W3C (World Wide Web Consortium). In addition, XSLT is more powerful than just a few tag libraries; for example, it supports functions and recursion.

Other considerations

In this section, we explain how to address internationalization and error handling, as well as some current limitations and possible future improvements of Model 2X.

Internationalization

The localization level and the target language's complexity affect entire layouts as well as text messages and images. For instance, Arabic is written right to left, and Mandarin Chinese is written vertically, from top to bottom. Such languages not only require text translation but also a completely different Webpage layout. Struts developers usually save all text messages and image links in resource bundles with one bundle per locale. Depending on the user-chosen locale, the appropriate resource bundle is loaded.

Model 2X handles resources by automatically storing them in the DOM passed to the view. Reading resource bundles and creating a DOM can be cached for efficient access. Model 2X simply inserts the resources DOM into the final DOM tree, including the dynamic content generated from beans. You can then access resources easily with XPath in an XSLT stylesheet. You can switch stylesheets dynamically depending on the current locale, although in most cases resource-based localization proves sufficient.

Error handling

Validation errors need to be distinguished from more severe errors. Validation errors occur when input parameters are encountered in an HTML form. All other errors are considered severe.

In Struts, form validation in form beans can return ActionError objects. Those objects are stored in the request and then serialized into the DOM tree for use by the stylesheet, which can conveniently display them next to the form, for example.

Similarly, the user can manually identify errors in the Action and store them in the request for further serialization and handling in the stylesheet.

Depending on the type and content of the request's error object, the stylesheet can choose to display an error message or redisplay the previous page to let the user resubmit the form.

Workflow

In the Model 2X architecture, the struts-config.xml file does not control the workflow as it does in the original Struts architecture. This is actually more a limitation of this implementation than of Model 2X itself. You can fix this concern in subsequent implementations.

Output

Model 2X can dynamically change the output's content type and/or the user interface's style, an important feature of the architecture. For example, the same application can generate HTML 3.2 code for older browsers and HTML 4.0 code for newer ones. XSLT allows output in a variety of formats, including XHTML, XSL/FO, WML, simple text, CSV, PDF, SVG, and so on.

XSLT pipeline

As mentioned briefly above, Model 2X features a useful improvement: the ability to easily channel stylesheets, separating layout and styling logic. As is true with the Apache Cocoon Framework, one stylesheet can define, for example, how a particular table type displays across a whole site. The first stylesheet can output a table as follows:

  <xsl:template match="customer-info">
    <table>
      <tr>
        <td>Name</td>
        <td><xsl:value-of select="name"/></td>
      </tr>
    </table>
  </xsl:template>

The second stylesheet can style the table by creating an embedded table as follows:

  <xsl:template match="table">
    <table cellpadding="0" cellspacing="0" border="0" bgcolor="red">
      <tr>
       <td valign="top">
          <table cellpadding="4" cellspacing="1" border="0">
            <xsl:apply-templates select="tr"/>
          </table>
        </td>
      </tr>
    </table>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

Performance

Model 2X's current implementation dynamically creates an XML DOM tree and sends it to the XSLT transformer. Using SAX (Simple API for XML) notably enhances performance, particularly latency and large documents' memory footprints. In addition, stylesheet compilation improves XSLT processing times. Xalan, the Apache Project's XSLT processor, provides a mechanism to compile stylesheets into a set of Java classes, known as translets.

Client-side processing

The latest browsers, such as Internet Explorer 5/6 and Mozilla, can perform client-side transformations, which can relieve application servers' processing load. Similarly, XInclude (XML Inclusions), if supported, can download and cache resources and other data from the application server. XInclude provides a generic mechanism for recognizing and processing inclusions, and as such, can offer a simpler overall authoring experience, greater performance, and less code redundancy. This approach's drawback: developers must ensure that the XML documents and stylesheets sent to the clients contain only information the user is allowed to see.

Enhance Struts with Model 2X

In conclusion, XML and XSLT use in Model 2X encourages developers to separate business and presentation logic and brings the Web applications world a step closer to delivering on MVC's original promise. Additional benefits, such as well-formed output documents, reliance on standardized languages, increased presentation layer flexibility, and shortened development cycles make the new model not only elegant but also powerful and efficient.

You could easily improve the simple implementation described in this article to refine the model, tune performance, and add flexibility.

Julien Mercay is a senior software engineer at Orbeon, a company specializing in J2EE (Java 2 Platform, Enterprise Edition) and XML technologies. Before joining Orbeon as a Unix, Java, and XML guru, Mercay worked at Sun Microsystems where he received the Technical Achievement Award for his major contribution on Sun's Web-based auctioning system. Gilbert Bouzeid created several J2EE applications for big companies, including NEC Computer, Context Integration, and Symantec before joining Orbeon. He is well versed in e-commerce applications, particularly in databases and XML technologies.

Learn more about this topic

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